有关java编程

zodiac的学习笔记

统计

留言簿(1)

阅读排行榜

评论排行榜

单纯使用spring(struts可选)的一种架构方案(1)

概述:
感觉hibernate或者jpa之类的orm映射框架硬把关系型数据库映射成对象没有太大的必要性,我想每个数据库表对应一个实体对象已经足够了,其他的关联问题根据需要在service层对应到每一个功能逐个进行解决,最大的好处是可以直接在代码里写出效率较高的sql语句。今天有时间,整理一下这个方案的思路,该思路不排斥团队开发的分工协作,开发效率也比较高。
该思路部分借鉴了公司内一同事的做法,至于最初的来源已不可考。
现在从数据实体类层到view层详述一下。
首先,数据里假定有两个表,建表语句如下:
    create table student(
        id 
NUMBER(19not null,
       name 
VARCHAR2(20not null,
       parent_id 
NUMBER(19),
        
primary key (id)
    )
    
    
create table parent(
        id 
NUMBER(19not null,
       name 
VARCHAR2(50not null,
        
primary key (id)
    )
很简单,一个学生一个家长,生成的实体类代码:
parent.java
package org.zodiac.model;

public class Parent implements java.io.Serializable {

    
private Long id;
    
private String name;

    
public Parent() {
    }


    
public Parent(Long id, String name) {
        
this.id = id;
        
this.name = name;
    }


    
public Long getId() {
        
return this.id;
    }


    
public void setId(Long id) {
        
this.id = id;
    }


    
public String getName() {
        
return this.name;
    }


    
public void setName(String name) {
        
this.name = name;
    }


}
student.java
package org.zodiac.model;

public class Student implements java.io.Serializable {

    
private Long id;
    
private String name;
    
private Long parentId;

    
public Student() {
    }


    
public Student(Long id, String name) {
        
this.id = id;
        
this.name = name;
    }


    
public Student(Long id, String name, Long parentId) {
        
this.id = id;
        
this.name = name;
        
this.parentId = parentId;
    }


    
public Long getId() {
        
return this.id;
    }


    
public void setId(Long id) {
        
this.id = id;
    }


    
public String getName() {
        
return this.name;
    }


    
public void setName(String name) {
        
this.name = name;
    }


    
public Long getParentId() {
        
return this.parentId;
    }


    
public void setParentId(Long parentId) {
        
this.parentId = parentId;
    }


}
数据访问层,实现一个基类来处理简单的查找和删除,该类是针对oracle数据库的实现,该类甚至也实现了分页查找的功能,参见之前的一篇关于PageBean的随笔,代码:
package org.zodiac.service.dao;

import java.util.List;

import org.springframework.jdbc.core.support.JdbcDaoSupport;

import org.zodiac.util.DAORowMapper;
import org.zodiac.vo.PageBean;


public class BaseJdbcDAO extends JdbcDaoSupport {

    
protected String tableName;

    
protected Class<?> objectClass;

    
protected String keyColumn;

    
    
    
public void setKeyColumn(String keyColumn) {
        
this.keyColumn = keyColumn;
    }


    
public void setObjectClass(Class<?> objectClass) {
        
this.objectClass = objectClass;
    }


    
public void setTableName(String tableName) {
        
this.tableName = tableName;
    }


    
public int delete(Object id) {
        String sql 
= "delete from " + tableName + " where " + keyColumn + "=?";
        
int rs = getJdbcTemplate().update(sql, new Object[] { id });
        
return rs;
    }


    
protected List<?> findAll() {
        String sql 
= "select * from " + tableName;
        
return getJdbcTemplate().query(sql, new DAORowMapper(objectClass));
    }


    
protected Object findById(Object id) {
        String sql 
= "select * from " + tableName + " where " + keyColumn + "=?";
        
return getJdbcTemplate().queryForObject(sql, new Object[] { id }new DAORowMapper(objectClass));
    }


    
protected List<?> findByProperty(String name, Object value) {
        String sql 
= "select * from " + tableName + " where " + name + "=?";
        
return getJdbcTemplate().query(sql, new Object[] { value }new DAORowMapper(objectClass));
    }


    
protected void getTotalRows(PageBean pb) {
        getTotalRows(pb, 
"");
    }


    
protected void getTotalRows(PageBean pb, String con) {
        getTotalRows(pb, tableName, con);
    }


    
protected void getTotalRows(PageBean pb, String tables, String con) {
        String sql 
= "select count(*) from " + tables + (con == null || con.trim().length() == 0 ? "" : " where " + con);
        pb.setTotalRows(
new Long(getJdbcTemplate().queryForLong(sql)));
    }


    
protected void getPageBean(PageBean pb) {
        getPageBean(pb, 
"");
    }


    
protected void getPageBean(PageBean pb, String con) {
        getPageBean(pb, con, 
null);
    }


    
protected void getPageBean(PageBean pb, String con, String order) {
        getPageBean(pb, 
"tb.*"this.tableName + " tb", con, order);
    }


    
protected void getPageBean(PageBean pb, String columns, String tables, String con, String order) {
        getPageBean(pb, columns, tables, con, order, 
this.objectClass);
    }


    
protected void getPageBean(PageBean pb, String columns, String tables, String con, String order, Class<?> resultClass) {
        order 
= "";
        String sql 
= "select * from (select dt.*,rownum rn from (select " + columns + " from " + tables + (con == null || con.trim().length() == 0 ? "" :" where " +  con)
                
+ (order == null || order.length() == 0 ? "" : " order by " + order) + ") dt where  rownum<=" + pb.getEndIndex().intValue() + ") dt where dt.rn>=" + pb.getStartIndex().intValue()
                
+ " order by rn ";
        logger.info(sql);
        List
<?> ls = getJdbcTemplate().query(sql, new DAORowMapper(resultClass));
        pb.setList(ls);
    }

}

其中的DAORowMapper代码如下:
DAORowMapper.java
package org.zodiac.util;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.StringTokenizer;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.support.rowset.ResultSetWrappingSqlRowSetMetaData;

public class DAORowMapper implements RowMapper {

    
private Class<?> rowObjectClass;

    
public DAORowMapper(Class<?> rowObjectClass) {
        
this.rowObjectClass = rowObjectClass;
    }
 

    
public Object mapRow(ResultSet rs, int index) throws SQLException {
        Object object;
        
try {
            object 
= rowObjectClass.newInstance();
        }
 catch (Exception e) {
            
throw new RuntimeException(e);
        }


        ResultSetWrappingSqlRowSetMetaData wapping 
= new ResultSetWrappingSqlRowSetMetaData(rs.getMetaData());
        
for (int i = 1; i <= wapping.getColumnCount(); i++{
            String name 
= StringUtils.lowerCase(wapping.getColumnName(i));
            
            StringTokenizer st 
= new StringTokenizer(name,"_");
            
int tokensize = st.countTokens();
            StringBuffer tmpStr 
= new StringBuffer();
            
for(int j = 0;j<tokensize;j++){
                String strTk 
= st.nextToken();
                
if(j>0){
                    strTk 
= StringUtils.capitalize( strTk);
                }

                tmpStr.append(strTk);
            }

            name 
= tmpStr.toString();
            Object value 
= null;
        //此处因为oracle驱动对timestamp字段的读取问题,需要做个判断
            
if (rs.getMetaData().getColumnType(i)==Types.DATE){
                value 
= rs.getTimestamp(i);
            }
else {
                value 
= rs.getObject(i);
            }

            
try {
                BeanUtils.copyProperty(object, name, value);
            }
 catch (Exception e) {
                e.printStackTrace();
            }
            
        }

        
return object;
    }

}

现在以Student为例实现一个对应实体类的数据访问对象,解决其单个查询、条件查询和增加修改操作,代码:
StudentDAO.java
package org.zodiac.service.dao;

import java.sql.Types;
import java.util.List;

import org.springframework.jdbc.core.RowMapper;
import org.zodiac.model.Student;
import org.zodiac.util.DAORowMapper;
import org.zodiac.vo.DataNotFoundException;
import org.zodiac.vo.InsertFailedException;

public class StudentDAO extends BaseJdbcDAO {
    
    @SuppressWarnings(
"unchecked")
    
public List<Student> findByCondition(String condition){
        String sql 
= "select * from "+tableName+condition;
        RowMapper row 
= new DAORowMapper(objectClass);
        List
<Student> students = getJdbcTemplate().query(sql, row);

        
return students;

    }

    
    
public long save(Student student){
        
        
long id = getJdbcTemplate().queryForLong("select STUDENT_SEQ.nextval FROM DUAL");
        
if (id < 1{
            
throw new DataNotFoundException("选择序列出现异常");
        }

        student.setId(id);
        String sql 
= "insert into "+tableName+
                    
" (id,name,parent_id) " +
                    
"values (?,?,?)";
        Object[] params 
= new Object[] {
            student.getId(),
            student.getName(),
            student.getParentId()
        }
;
        
int[] types = new int[] {
            Types.NUMERIC,
            Types.VARCHAR,
            Types.NUMERIC
        }
;
        
if (getJdbcTemplate().update(sql, params, types) != 1{
            
throw new InsertFailedException();
        }

        
return id;
    }

    
    
public Student find(long id){
        Student student 
= (Student)findById((Object)id);
        
return student;
    }

    
public boolean modify(Student student){
        
        Long id 
= student.getId();
        
        
if (id==null&&id<=0){
            
throw new DataNotFoundException("查询数据异常");
        }

        String sql 
= "update "+tableName+
                    
" set name=?,parent_id=?" +
                    
" where id="+id;
        Object[] params 
= new Object[] {
            student.getName(),
            student.getParentId()
        }
;
        
int[] types = new int[] {
            Types.VARCHAR,
            Types.NUMERIC
        }
;
        
if (getJdbcTemplate().update(sql, params, types) != 1{
            
throw new InsertFailedException();
        }

        
return true;
    }

    

}

以上用到的异常类皆继承spring提供的DataAccessException,我暂时放在vo包里,也许有不妥,可以推敲,但不影响整体结构,其代码大同小异:
DataNotFoundException.java
package org.zodiac.vo;

import org.springframework.dao.DataAccessException;


public class DataNotFoundException extends DataAccessException {

    
/**
     * 
     
*/

    
private static final long serialVersionUID = 4631397254851356222L;

    
public DataNotFoundException(String msg, Throwable ex) {
        
super(msg, ex);
    }


    
public DataNotFoundException(String msg) {
        
super(msg);
    }


    
public DataNotFoundException() {
        
super("DataNotFound!");        
    }

}

先到这,下次写服务层和action以及spring的配置文件。

posted on 2008-12-24 17:20 Zodiac 阅读(329) 评论(0)  编辑  收藏


只有注册用户登录后才能发表评论。


网站导航: