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

jopen 10年前發布 | 15K 次閱讀 BsaeDao Java開發

本文介紹的是在不使用持久層框架的情況下,用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;
    }
    

    }</span> </pre></li>

  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();
        
        } }

    }</span> </pre></li>

  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; }

    }</span> </pre></li>

  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");
      

      } }</span> </pre></li>

    • 用于測試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();
    }
    

    }</span> </pre></li>

  5. 創建用于測試的數據庫表:
  6. </ol>

    這里用Oracle數據庫作測試,建表語句如下,

    --創建測試表
    create table tbl_user
    (
      userId   number(8) primary key not null,
      userName varchar2(20),
      userPass varchar2(20),
      lastDate Date
    );

    create sequence seq_user;</pre>

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

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!