Java分层开发BaseDao



Java分层开发BaseDao

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

  1. BaseDao代码如下:
    Java代码  收藏代码
    1. <span style=”font-size: small;”>package dao;
    2. import java.lang.reflect.Field;
    3. import java.lang.reflect.Method;
    4. import java.sql.Connection;
    5. import java.sql.PreparedStatement;
    6. import java.sql.ResultSet;
    7. import java.sql.SQLException;
    8. import java.util.ArrayList;
    9. import java.util.List;
    10. import utils.DbHelper;
    11. public class BaseDao {
    12.     private Connection conn = null;
    13.     private PreparedStatement ps = null;
    14.     private ResultSet rs = null;
    15.     /**
    16.      * 查询符合条件的记录数
    17.      *
    18.      * @param sql
    19.      *            要执行的sql语句
    20.      * @param args
    21.      *            给sql语句中的?赋值的参数列表
    22.      * @return 符合条件的记录数
    23.      */
    24.     public long getCount(String sql, Object… args) {
    25.         conn = DbHelper.getConn();
    26.         try {
    27.             ps = conn.prepareStatement(sql);
    28.             for (int i = 0; i < args.length; i++) {
    29.                 ps.setObject(i + 1, args[i]);
    30.             }
    31.             rs = ps.executeQuery();
    32.             if (rs.next()) {
    33.                 return rs.getLong(1);
    34.             }
    35.         } catch (SQLException e) {
    36.             e.printStackTrace();
    37.         } finally {
    38.             DbHelper.closeConn(conn, ps, rs);
    39.         }
    40.         return 0L;
    41.     }
    42.     /**
    43.      * 查询实体对象的,并封装到一个集合
    44.      *
    45.      * @param <T>
    46.      *            要查询的对象的集合
    47.      * @param sql
    48.      *            要执行的sql语句
    49.      * @param clazz
    50.      *            要查询的对象的类型
    51.      * @param args
    52.      *            给sql语句中的?赋值的参数列表
    53.      * @return 要查询的类的集合,无结果时返回null
    54.      */
    55.     public <T> List<T> executeQuery(String sql, Class<T> clazz, Object… args) {
    56.         conn = DbHelper.getConn();
    57.         List list = new ArrayList();
    58.         try {
    59.             ps = conn.prepareStatement(sql);
    60.             for (int i = 0; i < args.length; i++) {
    61.                 ps.setObject(i + 1, args[i]);
    62.             }
    63.             rs = ps.executeQuery();
    64.             Field[] fs = clazz.getDeclaredFields();
    65.             String[] colNames = new String[fs.length];
    66.             String[] rTypes = new String[fs.length];
    67.             Method[] methods = clazz.getMethods();
    68.             while (rs.next()) {
    69.                 for (int i = 0; i < fs.length; i++) {
    70.                     Field f = fs[i];
    71.                     String colName = f.getName().substring(0, 1).toUpperCase()
    72.                             + f.getName().substring(1);
    73.                     colNames[i] = colName;
    74.                     String rType = f.getType().getSimpleName();
    75.                     rTypes[i] = rType;
    76.                 }
    77.                 Object object = (T) clazz.newInstance();
    78.                 for (int i = 0; i < colNames.length; i++) {
    79.                     String colName = colNames[i];
    80.                     String methodName = ”set” + colName;
    81.                     // 查找并调用对应的setter方法赋
    82.                     for (Method m : methods) {
    83.                         if (methodName.equals((m.getName()))) {
    84.                             // 如果抛了参数不匹配异常,检查JavaBean中该属性类型,并添加else分支进行处理
    85.                             if (“int”.equals(rTypes[i])
    86.                                     || ”Integer”.equals(rTypes[i])) {
    87.                                 m.invoke(object, rs.getInt(colName));
    88.                             } else if (“Date”.equals(rTypes[i])) {
    89.                                 m.invoke(object, rs.getDate(colName));
    90.                             } else if (“Timestamp”.equals(rTypes[i])) {
    91.                                 m.invoke(object, rs.getTimestamp(colName));
    92.                             } else {
    93.                                 m.invoke(object, rs.getObject(colName));
    94.                             }
    95.                             break;
    96.                         }
    97.                     }
    98.                 }
    99.                 list.add(object);
    100.             }
    101.             return list;
    102.         } catch (Exception e) {
    103.             e.printStackTrace();
    104.         } finally {
    105.             DbHelper.closeConn(conn, ps, rs);
    106.         }
    107.         return null;
    108.     }
    109.     /**
    110.      * 以对象的形式保存或更新一个实体
    111.      *
    112.      * @param sql
    113.      *            要执行的sql语句
    114.      * @param object
    115.      *            要保存或更新的实体对象
    116.      * @param args
    117.      *            不需要赋值的列标组成的数组,例如sql语句
    118.      *            ”insert into tbl_user values(seq_user.nextval,?,?,?)”应为1
    119.      * @return 操作结果,1 成功,0 失败
    120.      */
    121.     public int saveEntity(String sql, Object object, int… args) {
    122.         conn = DbHelper.getConn();
    123.         try {
    124.             ps = conn.prepareStatement(sql);
    125.             Class c = object.getClass();
    126.             Field[] fields = object.getClass().getDeclaredFields();
    127.             int temp = 1;// 正赋值的?的下标,最大下标为args的长度
    128.             int colIndex = 1;// SQL语句中的当前字段下标
    129.             int t = 0;// args数组的下标
    130.             for (int j = 0; j < fields.length; j++) {
    131.                 Field field = fields[j];// 得到某个声明属性
    132.                 String methodName = ”get”
    133.                         + field.getName().substring(0, 1).toUpperCase()
    134.                         + field.getName().substring(1);
    135.                 Method method = c.getMethod(methodName);// 得到了当前类中的一个method
    136.                 String rType = field.getType().getSimpleName().toString();
    137.                 if (t < args.length && colIndex == args[t]) {
    138.                     t++;
    139.                 } else if (“int”.equals(rType) || ”INTEGER”.equals(rType)) {
    140.                     ps.setInt(temp++, (Integer) method.invoke(object));
    141.                 } else {
    142.                     ps.setObject(temp++, method.invoke(object));
    143.                 }
    144.                 colIndex++;// 更新索引下标
    145.             }
    146.             return ps.executeUpdate();
    147.         } catch (Exception e) {
    148.             e.printStackTrace();
    149.         } finally {
    150.             DbHelper.closeConn(conn, ps, null);
    151.         }
    152.         return 0;
    153.     }
    154.     /**
    155.      * 执行可变参数的SQL语句,进行保存、删除或更新操作
    156.      *
    157.      * @param sql
    158.      *            要执行的sql语句,?的赋值顺序必须与args数组的顺序相同
    159.      * @param args
    160.      *            要赋值的参数列表
    161.      * @return 操作结果,正数 成功,0 失败
    162.      */
    163.     public int saveOrUpdate(String sql, Object… args) {
    164.         conn = DbHelper.getConn();
    165.         try {
    166.             ps = conn.prepareStatement(sql);
    167.             for (int j = 0; j < args.length; j++) {
    168.                 ps.setObject(j + 1, args[j]);
    169.             }
    170.             return ps.executeUpdate();
    171.         } catch (Exception e) {
    172.             e.printStackTrace();
    173.         } finally {
    174.             DbHelper.closeConn(conn, ps, null);
    175.         }
    176.         return 0;
    177.     }
    178. }
    179. </span>
  2. 连接数据库的DbHelper工具类
    Java代码  
    1. <span style=”font-size: small;”>package utils;
    2. import java.sql.Connection;
    3. import java.sql.DriverManager;
    4. import java.sql.ResultSet;
    5. import java.sql.Statement;
    6. /**
    7.  * 数据库工具类
    8.  *
    9.  * @author Jzl
    10.  *
    11.  */
    12. public class DbHelper {
    13.     /**
    14.      * 获得一个数据库连接
    15.      *
    16.      * @return
    17.      */
    18.     public static Connection getConn() {
    19.         Connection conn = null;
    20.         try {
    21.             Class.forName(“oracle.jdbc.driver.OracleDriver”);
    22.             String url = ”jdbc:oracle:thin:@localhost:1521:orcl”;
    23.             conn = DriverManager.getConnection(url, ”scott”, ”tiger”);
    24.         } catch (Exception e) {
    25.             e.printStackTrace();
    26.         }
    27.         return conn;
    28.     }
    29.     /**
    30.      * 关闭数据库连接资源
    31.      *
    32.      * @param conn
    33.      * @param ps
    34.      * @param rs
    35.      */
    36.     public static void closeConn(Connection conn, Statement ps, ResultSet rs) {
    37.         try {
    38.             if (rs != null) {
    39.                 rs.close();
    40.                 rs = null;
    41.             }
    42.             if (ps != null) {
    43.                 ps.close();
    44.                 ps = null;
    45.             }
    46.             if (conn != null) {
    47.                 conn.close();
    48.                 conn = null;
    49.             }
    50.         } catch (Exception e) {
    51.             e.printStackTrace();
    52.         }
    53.     }
    54. }
    55. </span>
  3. 接下来就可以测试BaseDao了。用于测试的User实体类:
    Java代码  收藏代码
    1. <span style=”font-size: small;”>package entity;
    2. import java.sql.Date;
    3. /**
    4.  * 用于测试的JavaBean,符合JavaBea命名规范
    5.  * @author Jzl
    6.  *
    7.  */
    8. public class User {
    9.     private int userId;
    10.     private String userName;
    11.     private String userPass;
    12.     private Date lastDate;
    13.     /**
    14.      * 无参构造函数,用于反射new一个实例(必须有)
    15.      */
    16.     public User() {
    17.     }
    18.     public User(String userName, String userPass, Date lastDate) {
    19.         super();
    20.         this.userName = userName;
    21.         this.userPass = userPass;
    22.         this.lastDate = lastDate;
    23.     }
    24.     public int getUserId() {
    25.         return userId;
    26.     }
    27.     public void setUserId(int userId) {
    28.         this.userId = userId;
    29.     }
    30.     public String getUserName() {
    31.         return userName;
    32.     }
    33.     public void setUserName(String userName) {
    34.         this.userName = userName;
    35.     }
    36.     public String getUserPass() {
    37.         return userPass;
    38.     }
    39.     public void setUserPass(String userPass) {
    40.         this.userPass = userPass;
    41.     }
    42.     public Date getLastDate() {
    43.         return lastDate;
    44.     }
    45.     public void setLastDate(Date lastDate) {
    46.         this.lastDate = lastDate;
    47.     }
    48. }
    49. </span>
  4. 用于测试的UserDao:
    Java代码  收藏代码
    1. <span style=”font-size: small;”>package dao;
    2. import java.util.List;
    3. import entity.User;
    4. /**
    5.  * 用于测试的UserDao
    6.  * @author Jzl
    7.  *
    8.  */
    9. public class UserDao extends BaseDao {
    10.     public int addUser1(User user) {
    11.         return super.saveEntity(
    12.                 ”insert into tbl_user values(seq_user.nextval,?,?,?)”, user, 1);
    13.     }
    14.     public int addUser2(User user) {
    15.         return super.saveOrUpdate(
    16.                 ”insert into tbl_user values(seq_user.nextval,?,?,?)”,
    17.                 user.getUserName(), user.getUserPass(), user.getLastDate());
    18.     }
    19.     public int deleteUserById(int userId) {
    20.         return super
    21.                 .saveOrUpdate(“delete from tbl_user where userId=?”, userId);
    22.     }
    23.     public int modUserById(int userId, User user) {
    24.         return super
    25.                 .saveOrUpdate(
    26.                         ”update tbl_user set userName=?,userPass=?,lastDate=? where userId=?”,
    27.                         user.getUserName(), user.getUserPass(),
    28.                         user.getLastDate(), userId);
    29.     }
    30.     public User getUser(int userId) {
    31.         return super.executeQuery(“select * from tbl_user where userId=?”,
    32.                 User.class, userId).get(0);
    33.     }
    34.     public List<User> getUserList() {
    35.         return super.executeQuery(“select * from tbl_user”, User.class);
    36.     }
    37.     public long getUserCount(){
    38.         return super.getCount(“select count(*) from tbl_user”);
    39.     }
    40. }
    41. </span>
  5. 用于测试UserDao的测试类:
    Java代码  收藏代码
    1. <span style=”font-size: small;”>package test;
    2. import java.sql.Date;
    3. import java.util.List;
    4. import org.junit.Test;
    5. import dao.UserDao;
    6. import entity.User;
    7. public class UserDaoTest {
    8.     private UserDao userDao = new UserDao();
    9.     @Test
    10.     public void testUserDao() {
    11.         testAdd1();
    12.         testAdd2();
    13.         testDeleteById();
    14.         testModById();
    15.         System.out.println(testGetById().getUserName());
    16.         List<User> users = testGetList();
    17.         for (User user : users) {
    18.             System.out.println(user.getUserId() + ”==” + user.getUserName());
    19.         }
    20.         System.out.println(testGetCount());
    21.     }
    22.     public int testAdd1() {
    23.         User user = new User(“zs”, ”zs”, new Date(System.currentTimeMillis()));
    24.         return userDao.addUser1(user);
    25.     }
    26.     public int testAdd2() {
    27.         User user = new User(“zs”, ”zs”, new Date(System.currentTimeMillis()));
    28.         return userDao.addUser2(user);
    29.     }
    30.     public int testDeleteById() {
    31.         return userDao.deleteUserById(104);
    32.     }
    33.     public User testGetById() {
    34.         return userDao.getUser(104);
    35.     }
    36.     public int testModById() {
    37.         User user = new User(“ls”, ”ls”, new Date(System.currentTimeMillis()));
    38.         return userDao.modUserById(104, user);
    39.     }
    40.     public List<User> testGetList() {
    41.         return userDao.getUserList();
    42.     }
    43.     public long testGetCount() {
    44.         return userDao.getUserCount();
    45.     }
    46. }
    47. </span>
  6. 创建用于测试的数据库表:

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

Sql代码  收藏代码
  1. –创建测试表
  2. create table tbl_user
  3. (
  4.   userId   number(8) primary key not null,
  5.   userName varchar2(20),
  6.   userPass varchar2(20),
  7.   lastDate Date
  8. );
  9. create sequence seq_user;