最近因爲公司要開發個報表系統,因爲涉及到超大數據量的統計,頻繁的sql語句,就沒有在用hibernate,又重拾起了jdbc,在寫jdbc助手類時自我感受有個不錯的建議和你們分享下: java
上面的代碼是個查詢單個實例方法中的片斷,能夠看到除了填充bean(Admin類)外其餘代碼都是公用代碼,能夠放到jdbc助手類中,這就要解決不一樣bean的填充問題。 web
採用回調函數代替上面填充bean的部分是個可行的選擇。 sql
下面是具體的實現: 數據庫
數據庫中有個簡單的users表,用於存放客戶信息: 函數
com.persist.User類是個實體類對應Users表: 大數據
package com.persist; import java.io.Serializable; import java.util.Date; public class User{ private int dbid; private String userName;//暱稱 private String password;//登陸密碼 private String email;//郵箱 public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public int getDbid() { return dbid; } public void setDbid(int dbid) { this.dbid = dbid; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } }
com.dao.GenericDao類是數據訪問層(dao)定義的jdbc助手類,用於完成數據訪問的基本操做。find方法是得到單個實例的查詢方法,其中會調用回調函數call()。代碼最底端定義了內部接口PopulateCallable,用於完成回調操做,call是回調函數。 this
package com.dao; import java.io.Serializable; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.List; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.sql.DataSource; public class GenericDao<T> { /** * 查詢單個實例 * @param sql * @param params * @param callback * @return * @throws SQLException * @throws NamingException */ protected T find(String sql, Object[] params, PopulateCallable<T> callback) throws SQLException, NamingException{ T entity = null; Connection con = null; PreparedStatement stmt = null; ResultSet rs = null; try { con = this.getConnection(); stmt = con.prepareStatement(sql); setParams(stmt, params); rs = stmt.executeQuery(); while(rs.next()){ entity = callback.call(rs); } }finally{ closeResultSet(rs); closeStatement(stmt); closeConnection(con); } return entity; } /** * 得到數據庫connection * @return * @throws SQLException * @throws NamingException */ protected Connection getConnection() throws SQLException, NamingException{ Context initContext = new InitialContext(); Context envContext = (Context)initContext.lookup("java:/comp/env"); DataSource ds = (DataSource)envContext.lookup("jdbc/myweb"); Connection con = ds.getConnection(); return con; } /** * 關閉ResultSet * @param rs */ public void closeResultSet(ResultSet rs){ try { if(rs != null){ rs.close(); } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * 關閉Statement * @param stmt */ public void closeStatement(Statement stmt){ try { if(stmt != null){ stmt.close(); } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * 歸還鏈接到鏈接池 * @param con */ public void closeConnection(Connection con){ try { if(con != null && !con.isClosed()){ con.close(); } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * 設置參數 * @param stmt * @param params * @throws SQLException */ public void setParams(PreparedStatement stmt, Object[] params) throws SQLException{ for(int i = 0; i<params.length;){//int, short, long, float, double, boolean, byte, char, List stmt.setObject(i+1, params[i]); i++; } } protected interface PopulateCallable<T> extends Serializable { T call(ResultSet rs)throws SQLException, NamingException; } }
com.dao.UserDao類負責User的的數據訪問,繼承自助手類com.dao.GenericDao: spa
package com.dao; import java.sql.ResultSet; import java.sql.SQLException; import javax.naming.NamingException; import com.persist.User; public class UserDao extends GenericDao<User>{ public User find(int dbid) throws SQLException, NamingException{ String sql = "select * from users t where t.dbid=?"; Object[] params = new Object[]{dbid}; User entity = super.find(sql, params, new GenericDao.PopulateCallable<User>(){ public User call(ResultSet rs) throws SQLException, NamingException{ User item = new User(); item.setDbid(rs.getInt("dbid")); item.setUserName(rs.getString("username")); item.setPassword(rs.getString("password")); item.setEmail(rs.getString("email")); return item; } }); return entity; } }
find方法負責從數據庫中得到單個實例。這個方法是核心方法。其中在調用super.find()方法時,生成了PopulateCallable接口的匿名類,做爲參數傳入。回調函數call負責具體的封裝bean的操做,由助手類com.dao.GenericDao類調用。 hibernate
package com.service; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import javax.naming.NamingException; import com.dao.GenericDao; import com.dao.UserDao; import com.persist.User; public class UserService { public User get(int dbid) throws SQLException, NamingException{ User entity = null; UserDao dao = new UserDao(); entity = dao.find(dbid); return entity; } }com.service.UserService類是個簡單的業務類。
除了回調函數外,也能夠使用反射,利用java.beans.BeanInfo類得到bean的全部屬性,而後利用寫屬性進行填充。相比於採用回調而言,反射很難控制讀取的數據庫字段的數量,因此靈活性不如回調。 code