JDBC之使用策略模式和模板方法模式优化代码

在处理ResultSet时,不同的方法处理的方式是不一样的,但在继承的时候,rowMapper方法只能以一种方式实现,因此可以将对ResultSet处理的部分单独提取成一个抽象的部分,在不同的方法需要处理的时候,各自以自己的方式进行定义。

1、定义一个策略接口RowMapper

package cn.itcast.jdbc.dao.refactor;

import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * 策略接口
 */
public interface RowMapper {
	
	/**
	 * 策略方法
	 * @param rs
	 * @return
	 * @throws SQLException
	 */
	public Object mapRow(ResultSet rs) throws SQLException;
	
}
2、定义Dao模板类
package cn.itcast.jdbc.dao.refactor;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import cn.itcast.jdbc.JdbcUtils;
import cn.itcast.jdbc.dao.DaoException;

/**
 * 自定义Dao处理结果集的模板方法
 */
public class MyDaoTemplate {
	
	/**
	 * 执行查询操作的模板方法
	 * @param sql
	 * @param args
	 * @param rowMapper
	 * @return
	 */
	public Object find(String sql, Object[] args, RowMapper rowMapper) {
		Connection conn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		
		try {
			conn = JdbcUtils.getConnection();
			ps = conn.prepareStatement(sql);
			for(int i = 0; i < args.length; i ++) {
				ps.setObject(i + 1, args[i]);
			}
			rs = ps.executeQuery();
			Object obj = null;
			if(rs.next()) {
				//这里的执行交给具体的执行方法去处理
				obj = rowMapper.mapRow(rs);
			}
			return obj;
		} catch (SQLException e) {
			throw new DaoException(e.getMessage(), e);
		} finally {
			JdbcUtils.free(rs, ps, conn);
		}
		
	}
}
3、编写Dao的实现类
package cn.itcast.jdbc.dao.refactor;

import java.sql.ResultSet;
import java.sql.SQLException;

import cn.itcast.jdbc.domain.User;

/**
 * 使用模板方法模式和策略模式进行优化代码
 */
public class UserDaoImpl2 {
	
	private MyDaoTemplate template = new MyDaoTemplate();
	
	/**
	 * 根据姓名查询用户
	 * @param loginName
	 * @return
	 */
	public User findUser(String loginName) {
		String sql = "select id, name, money, birthday"
				+ " from user where name = ?";
		Object[] args = new Object[]{loginName};
		//显式创建一个行映射器
		RowMapper mapper = new UserRowMapper();
		Object user =this.template.find(sql, args, mapper);
		return (User) user;
	}
	
	/**
	 * 根据id查询用户姓名
	 * @param id
	 * @return
	 */
	public String findUserName(int id) {
		String sql = "select name from user where id = ?";
		Object[] args = new Object[]{id};
		//通过匿名内部类的方式创建一个行映射器
		Object name = this.template.find(sql, args, new RowMapper(){

			public Object mapRow(ResultSet rs) throws SQLException {
				return rs.getString("name");
			}
			
		});
		return (String) name;
	}
	
}

class UserRowMapper implements RowMapper {

	/**
	 * 具体的方法
	 */
	public Object mapRow(ResultSet rs) throws SQLException {
		User user = new User();
		user.setId(rs.getInt("id"));
		user.setName(rs.getString("name"));
		user.setMoney(rs.getFloat("money"));
		user.setBirthday(rs.getDate("birthday"));
		return user;
	}
	
}
4、编写测试类进行测试
package cn.itcast.jdbc.dao.refactor;

import org.junit.Test;

import cn.itcast.jdbc.domain.User;

public class TestUserDaoImpl2 {
	
	private UserDaoImpl2 impl2 = new UserDaoImpl2();
	
	/**
	 * 测试根据姓名查询用户
	 */
	@Test
	public void testFindUser() {
		User user = impl2.findUser("lisi");
		System.out.println(user);
	}
	
	/**
	 * 测试根据id查询用户姓名
	 */
	@Test
	public void testFindUserName() {
		String username = impl2.findUserName(2);
		System.out.println(username);
	}
}


你可能感兴趣的:(JDBC)