不使用持久层框架下的BsaeDao示例

jopen 10年前

本文介绍的是在不使用持久层框架的情况下,用Java反射写的BaseDao,简化Dao层的操作,让Dao的实现层每个方法体只有一行。所有的Dao的实现类继承BaseDao。 下面具体讲如何使用BaseDao

  1. BaseDao代码如下:
    package dao;    import java.lang.reflect.Field;  import java.lang.reflect.Method;  import java.sql.Connection;  import java.sql.PreparedStatement;  import java.sql.ResultSet;  import java.sql.SQLException;  import java.util.ArrayList;  import java.util.List;    import utils.DbHelper;    public class BaseDao {   private Connection conn = null;   private PreparedStatement ps = null;   private ResultSet rs = null;     /**    * 查询符合条件的记录数    *     * @param sql    *            要执行的sql语句    * @param args    *            给sql语句中的?赋值的参数列表    * @return 符合条件的记录数    */   public long getCount(String sql, Object... args) {    conn = DbHelper.getConn();    try {     ps = conn.prepareStatement(sql);     for (int i = 0; i < args.length; i++) {      ps.setObject(i + 1, args[i]);     }     rs = ps.executeQuery();     if (rs.next()) {      return rs.getLong(1);     }    } catch (SQLException e) {     e.printStackTrace();    } finally {     DbHelper.closeConn(conn, ps, rs);    }    return 0L;   }     /**    * 查询实体对象的,并封装到一个集合    *     * @param <T>    *            要查询的对象的集合    * @param sql    *            要执行的sql语句    * @param clazz    *            要查询的对象的类型    * @param args    *            给sql语句中的?赋值的参数列表    * @return 要查询的类的集合,无结果时返回null    */   public <T> List<T> executeQuery(String sql, Class<T> clazz, Object... args) {    conn = DbHelper.getConn();    List list = new ArrayList();    try {     ps = conn.prepareStatement(sql);     for (int i = 0; i < args.length; i++) {      ps.setObject(i + 1, args[i]);     }     rs = ps.executeQuery();     Field[] fs = clazz.getDeclaredFields();     String[] colNames = new String[fs.length];     String[] rTypes = new String[fs.length];     Method[] methods = clazz.getMethods();     while (rs.next()) {      for (int i = 0; i < fs.length; i++) {       Field f = fs[i];       String colName = f.getName().substring(0, 1).toUpperCase()         + f.getName().substring(1);       colNames[i] = colName;       String rType = f.getType().getSimpleName();       rTypes[i] = rType;      }        Object object = (T) clazz.newInstance();      for (int i = 0; i < colNames.length; i++) {       String colName = colNames[i];       String methodName = "set" + colName;       // 查找并调用对应的setter方法赋       for (Method m : methods) {        if (methodName.equals((m.getName()))) {         // 如果抛了参数不匹配异常,检查JavaBean中该属性类型,并添加else分支进行处理         if ("int".equals(rTypes[i])           || "Integer".equals(rTypes[i])) {          m.invoke(object, rs.getInt(colName));         } else if ("Date".equals(rTypes[i])) {          m.invoke(object, rs.getDate(colName));         } else if ("Timestamp".equals(rTypes[i])) {          m.invoke(object, rs.getTimestamp(colName));         } else {          m.invoke(object, rs.getObject(colName));         }         break;        }       }      }      list.add(object);     }     return list;    } catch (Exception e) {     e.printStackTrace();    } finally {     DbHelper.closeConn(conn, ps, rs);    }    return null;   }     /**    * 以对象的形式保存或更新一个实体    *     * @param sql    *            要执行的sql语句    * @param object    *            要保存或更新的实体对象    * @param args    *            不需要赋值的列标组成的数组,例如sql语句    *            "insert into tbl_user values(seq_user.nextval,?,?,?)"应为1    * @return 操作结果,1 成功,0 失败    */   public int saveEntity(String sql, Object object, int... args) {    conn = DbHelper.getConn();    try {     ps = conn.prepareStatement(sql);     Class c = object.getClass();     Field[] fields = object.getClass().getDeclaredFields();     int temp = 1;// 正赋值的?的下标,最大下标为args的长度     int colIndex = 1;// SQL语句中的当前字段下标     int t = 0;// args数组的下标     for (int j = 0; j < fields.length; j++) {      Field field = fields[j];// 得到某个声明属性      String methodName = "get"        + field.getName().substring(0, 1).toUpperCase()        + field.getName().substring(1);      Method method = c.getMethod(methodName);// 得到了当前类中的一个method      String rType = field.getType().getSimpleName().toString();      if (t < args.length && colIndex == args[t]) {       t++;      } else if ("int".equals(rType) || "INTEGER".equals(rType)) {       ps.setInt(temp++, (Integer) method.invoke(object));      } else {       ps.setObject(temp++, method.invoke(object));      }      colIndex++;// 更新索引下标     }     return ps.executeUpdate();    } catch (Exception e) {     e.printStackTrace();    } finally {     DbHelper.closeConn(conn, ps, null);    }    return 0;   }     /**    * 执行可变参数的SQL语句,进行保存、删除或更新操作    *     * @param sql    *            要执行的sql语句,?的赋值顺序必须与args数组的顺序相同    * @param args    *            要赋值的参数列表    * @return 操作结果,正数 成功,0 失败    */   public int saveOrUpdate(String sql, Object... args) {    conn = DbHelper.getConn();    try {     ps = conn.prepareStatement(sql);     for (int j = 0; j < args.length; j++) {      ps.setObject(j + 1, args[j]);     }     return ps.executeUpdate();    } catch (Exception e) {     e.printStackTrace();    } finally {     DbHelper.closeConn(conn, ps, null);    }    return 0;   }  } 
  2. 连接数据库的DbHelper工具类
    package utils;    import java.sql.Connection;  import java.sql.DriverManager;  import java.sql.ResultSet;  import java.sql.Statement;    /**   * 数据库工具类   *    * @author Jzl   *    */  public class DbHelper {     /**    * 获得一个数据库连接    *     * @return    */   public static Connection getConn() {    Connection conn = null;    try {     Class.forName("oracle.jdbc.driver.OracleDriver");     String url = "jdbc:oracle:thin:@localhost:1521:orcl";     conn = DriverManager.getConnection(url, "scott", "tiger");    } catch (Exception e) {     e.printStackTrace();    }    return conn;   }     /**    * 关闭数据库连接资源    *     * @param conn    * @param ps    * @param rs    */   public static void closeConn(Connection conn, Statement ps, ResultSet rs) {    try {     if (rs != null) {      rs.close();      rs = null;     }     if (ps != null) {      ps.close();      ps = null;     }     if (conn != null) {      conn.close();      conn = null;     }    } catch (Exception e) {     e.printStackTrace();    }   }    } 
  3. 接下来就可以测试BaseDao了。用于测试的User实体类:
    package entity;    import java.sql.Date;    /**   * 用于测试的JavaBean,符合JavaBea命名规范   * @author Jzl   *   */  public class User {   private int userId;   private String userName;   private String userPass;   private Date lastDate;     /**    * 无参构造函数,用于反射new一个实例(必须有)    */   public User() {   }     public User(String userName, String userPass, Date lastDate) {    super();    this.userName = userName;    this.userPass = userPass;    this.lastDate = lastDate;   }     public int getUserId() {    return userId;   }     public void setUserId(int userId) {    this.userId = userId;   }     public String getUserName() {    return userName;   }     public void setUserName(String userName) {    this.userName = userName;   }     public String getUserPass() {    return userPass;   }     public void setUserPass(String userPass) {    this.userPass = userPass;   }     public Date getLastDate() {    return lastDate;   }     public void setLastDate(Date lastDate) {    this.lastDate = lastDate;   }    } 
  4. 用于测试的UserDao:
    package dao;    import java.util.List;    import entity.User;    /**   * 用于测试的UserDao   * @author Jzl   *   */  public class UserDao extends BaseDao {   public int addUser1(User user) {    return super.saveEntity(      "insert into tbl_user values(seq_user.nextval,?,?,?)", user, 1);   }     public int addUser2(User user) {    return super.saveOrUpdate(      "insert into tbl_user values(seq_user.nextval,?,?,?)",      user.getUserName(), user.getUserPass(), user.getLastDate());   }     public int deleteUserById(int userId) {    return super      .saveOrUpdate("delete from tbl_user where userId=?", userId);   }     public int modUserById(int userId, User user) {    return super      .saveOrUpdate(        "update tbl_user set userName=?,userPass=?,lastDate=? where userId=?",        user.getUserName(), user.getUserPass(),        user.getLastDate(), userId);   }     public User getUser(int userId) {    return super.executeQuery("select * from tbl_user where userId=?",      User.class, userId).get(0);   }     public List<User> getUserList() {    return super.executeQuery("select * from tbl_user", User.class);   }      public long getUserCount(){    return super.getCount("select count(*) from tbl_user");   }  } 
  5. 用于测试UserDao的测试类:
    package test;    import java.sql.Date;  import java.util.List;    import org.junit.Test;    import dao.UserDao;  import entity.User;    public class UserDaoTest {   private UserDao userDao = new UserDao();     @Test   public void testUserDao() {    testAdd1();    testAdd2();    testDeleteById();    testModById();    System.out.println(testGetById().getUserName());    List<User> users = testGetList();    for (User user : users) {     System.out.println(user.getUserId() + "==" + user.getUserName());    }    System.out.println(testGetCount());   }     public int testAdd1() {    User user = new User("zs", "zs", new Date(System.currentTimeMillis()));    return userDao.addUser1(user);   }     public int testAdd2() {    User user = new User("zs", "zs", new Date(System.currentTimeMillis()));    return userDao.addUser2(user);   }     public int testDeleteById() {    return userDao.deleteUserById(104);   }     public User testGetById() {    return userDao.getUser(104);   }     public int testModById() {    User user = new User("ls", "ls", new Date(System.currentTimeMillis()));    return userDao.modUserById(104, user);   }     public List<User> testGetList() {    return userDao.getUserList();   }     public long testGetCount() {    return userDao.getUserCount();   }  } 
  6. 创建用于测试的数据库表:

这里用Oracle数据库作测试,建表语句如下,

--创建测试表  create table tbl_user  (    userId   number(8) primary key not null,    userName varchar2(20),    userPass varchar2(20),    lastDate Date  );    create sequence seq_user;

来自:http://z2009zxiaolong.iteye.com/blog/1561221