最近因为公司要开发个报表系统,因为涉及到超大数据量的统计,频繁的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