利用回调函数+匿名类解决jdbc数据封装问题

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

相关文章
相关标签/搜索