Java回调机制,利用回调写的JDBC 访问例子

 

    首先说说为什么要用到回调这个方式,

    我们在日常生活和工作中,有一种情况是这样的,做一件事,但是这件事中有些步骤是不确定如何做的,但是可以先约定好怎么做.对于程序来说,就是有一段业务,其中有几段小逻辑不确定如何做,但是我们可以先定义好一些方法(统一的参数和返回值)对应这些逻辑, 具体这些逻辑的实现交给具体执行的代码去实现.

    下面举个例子,JDBC 访问,假设我们都用PreparedStatement来处理SQL, 我们都要初始化连接,初始化PreparedStatement,封装PreparedStatement插入SQL参数,执行SQL,获得ResultSet,封装ResultSet成我们要的对象,关闭连接,其中封装PreparedStatement插入SQL参数和封装ResultSet成我们要的对象是不确定的,我们就可以把这2步定义成回调函数,交给具体执行代码去做.

    根据上面说的,我们可以定一个JdbcCallback接口来定义这个回调函数,

 

package com.balance.easycalendar.dao.template;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import com.balance.easycalendar.to.BaseTO;

public interface JdbcCallback {
	
	public List<BaseTO> packResult(ResultSet rs) throws SQLException;
	public void packParams(PreparedStatement stmt) throws SQLException;
}

 

再定义一个JdbcCallbackTemplate来执行具体的方法,其中引用一个JdbcCallback来完成不确定的步骤,

package com.balance.easycalendar.dao.template;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.List;

import com.balance.easycalendar.dao.exception.DAOException;
import com.balance.easycalendar.to.BaseTO;
import com.balance.easycalendar.util.MessageProperties;

public class JdbcCallbackTemplate {

	private JdbcCallback temp;
	
	public void setTemp(JdbcCallback temp) {
		this.temp = temp;
	}

	protected String url;
	protected String username;
	protected String password;
	protected String driver;
	
	private PreparedStatement stmt = null;
	private Connection con = null;
	
	public JdbcCallbackTemplate(){
		MessageProperties pro = MessageProperties.getInstance("jdbc.properties");
		
		url = pro.getValue("db.url");
		driver = pro.getValue("db.driver");
		username = pro.getValue("db.username");
		password = pro.getValue("db.password");	
	}
	
	public List<BaseTO> query(String sql) throws DAOException{
		try{
			Class.forName(driver);
			con = DriverManager.getConnection(url, username, password);
	
			stmt = con.prepareStatement(sql);
			temp.packParams(stmt);
			
			ResultSet rs = stmt.executeQuery();
			
			return temp.packResult(rs);
			
		}catch(Exception e){
			throw new DAOException(e);
		}finally{
			try{
				stmt.close();
				con.close();
			}catch(Exception e){
				e.printStackTrace();
			}
		}
	}
	
	public boolean excute(String sql) throws DAOException{
		try{
			Class.forName(driver);
			con = DriverManager.getConnection(url, username, password);
	
			stmt = con.prepareStatement(sql);
			temp.packParams(stmt);
			
			return stmt.execute();
			
		}catch(Exception e){
			throw new DAOException(e);
		}finally{
			try{
				stmt.close();
				con.close();
			}catch(Exception e){
				e.printStackTrace();
			}
		}
	}
	
}

    这个Template定义了2个方法, excute用来执行增加,修改,删除等,query用来执行查询,在这2个方法里,封装参数,封装result都不确定,所以用了上面定义的回调函数来实行,具体实现交给具体的实现类去做.(MessageProperties 是我写的一个资源引用类,可以参考我的另一篇blog:利用多例模式编写配置文件读取器 )

 

   下面我们看看具体的实现,

    BaseDAO里实例化一个jdbcCallbackTemplate

package com.balance.easycalendar.dao;

import com.balance.easycalendar.dao.template.JdbcCallbackTemplate;
import com.balance.easycalendar.util.MessageProperties;


public abstract class BaseDAO {
	
		
	protected JdbcCallbackTemplate jdbcCallbackTemplate = new JdbcCallbackTemplate();
	
	public String getSql(String sqlId){
		MessageProperties pro = MessageProperties.getInstance("sqls.properties");	
		return pro.getValue(sqlId);
	}
}
 

定义一个TaskDAO,用来执行具体的数据库访问.首先给jdbcCallbackTemplate注入实例化的JdbcCallback(实现具体的回调函数),然后就可以调用Template里的query和excute方法了.

package com.balance.easycalendar.dao;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.balance.easycalendar.dao.exception.DAOException;
import com.balance.easycalendar.dao.template.JdbcCallback;
import com.balance.easycalendar.dao.template.JdbcCallbackAdapter;
import com.balance.easycalendar.to.BaseTO;
import com.balance.easycalendar.to.TaskTO;

public class TaskDAO extends BaseDAO{

	public TaskTO getTask(final String taskId) throws DAOException {
		jdbcCallbackTemplate.setTemp(new JdbcCallback(){
			@Override
			public void packParams(PreparedStatement stmt) throws SQLException {
				stmt.setString(1, taskId);		
			}

			@Override
			public List<BaseTO> packResult(ResultSet rs) throws SQLException {
				List<BaseTO> tasks = new ArrayList<BaseTO>();		
				while (rs.next()) {
					TaskTO taskTO = new TaskTO();
					taskTO.setTaskId(rs.getString("TASK_ID"));
					taskTO.setTaskName(rs.getString("TASK_NAME"));
					taskTO.setTaskDesc(rs.getString("TASK_DESC"));
					
					tasks.add(taskTO);
				}
				
				return tasks;
			}
		});
	
		List<BaseTO> tasks = jdbcCallbackTemplate.query(getSql("task.search.bytaskid"));
		return (TaskTO)tasks.get(0);
	}
	
	public boolean insertTask(final String taskId, final String taskName, final String taskDesc) throws DAOException {
		jdbcCallbackTemplate.setTemp(new JdbcCallbackAdapter(){

			@Override
			public void packParams(PreparedStatement stmt) throws SQLException {
				stmt.setString(1, taskId);
				stmt.setString(2, taskName);
				stmt.setString(3, taskDesc);
			}			
		});
		
		return jdbcCallbackTemplate.excute(getSql("task.insert"));
	}
	
	public boolean delTask(final String taskId) throws DAOException {
		jdbcCallbackTemplate.setTemp(new JdbcCallbackAdapter(){

			@Override
			public void packParams(PreparedStatement stmt) throws SQLException {
				stmt.setString(1, taskId);
			}			
		});
		
		return jdbcCallbackTemplate.excute(getSql("task.delete.bytaskid"));
	}

}

 

sql我也用MessageProperties来读取了,定义在一个单独的properties文件里,

task.search.bytaskid = select TASK_ID,TASK_NAME,TASK_DESC from TB_TASKS where TASK_ID = ?
task.insert = insert into TB_TASKS (TASK_ID,TASK_NAME,TASK_DESC) values (?,?,?)
task.delete.bytaskid = Delete from TB_TASKS where TASK_ID = ?

 

JdbcCallbackAdapte是JdbcCallback的一个默认适配器,提供了packResult一个空实现,因为excute不需要封装result对象。

 

好了,这个例子就是这样了.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值