首页 > 代码库 > 脱离持久化框架下的BsaeDao示例

脱离持久化框架下的BsaeDao示例

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

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

脱离持久化框架下的BsaeDao示例