JDBC技术(三)工具的封装

为了改善之前的增删改查操作,故做了一个小工具。只展示个别方法,道理都是一样的。

 

这个BaseDao是通用的底层,将其写成抽象方法的原因是只想让他被继承(该类中没有抽象方法)。其实核心原因是想在构造方法中能成功获取到泛型的实体类型。

对下面代码的构造方法中内容引出来的一些基础知识点:

关于this:若存在继承关系,则不管是子类还是父类,this指的都是那个new出来的对象实例。

关于this.成员  和  this.方法  先在本类中找有没有,如果没有则沿着继承关系往上找。故BaseDao中的this.klass指的是自己的klass成员。

还有就是getGenericSuperclass()这个方法要区别于getSuperclass()方法。
二者都是获取直接继承的父类,只是前者能获取到父类泛型的实体类型。后者则不行。

如果不写成抽象类,你直接来个new BaseDao操作那么这里的外层判断就失去意义了。因为这种情况下this代表的就是该类(BaseDao类)本身。该类默认只是Object的子类,显然Object是不带泛型参数的。所以klass成员会是null。那之后的操作肯定不能成功。下面的取值操作就是要利用反射机制来将数据库一条一条记录存储进java对象中。如果你连klass都是null,那就拉了。

ParameterizedType表示的是参数化类型(我觉得可以理解成带泛型实体的类)。比如BaseDao中是带有泛型实体的---User类。

public abstract class BaseDao {
	private Class klass = null;
	
	public BaseDao() {
		//获取子类对象直接继承的父类(包含泛型参数)  此处的this是new出来的对象实例
		Type superClass = this.getClass().getGenericSuperclass();
		//检测该类是否带参
		if(superClass instanceof ParameterizedType) {
			ParameterizedType paraType = (ParameterizedType) superClass;
			//获取泛型表示的真实的实体类型
			Type[] args = paraType.getActualTypeArguments();
			if(args != null && args.length > 0 && (args[0] instanceof Class)) {
				this.klass = (Class) args[0];
			}
		}
	}
	
	//通用的增删改操作
	protected int updata(String sql, Object...args) {
		Connection conn = null;
		PreparedStatement state = null;
		try {
			conn = JdbcUtils.getConnection();
			state = conn.prepareStatement(sql);
			for(int index = 0; index < args.length; index++) {
				state.setObject(index + 1, args[index]);
			}
			return state.executeUpdate();
		} catch (SQLException e) {
			e.printStackTrace();
		}finally {
			JdbcUtils.close(conn, state, null);
		}
		
		return -1;
	}
	
	
	//获取对象集合
	protected List getList(String sql, Object...args){
		Connection conn = null;
		PreparedStatement state = null;
		ResultSet rs = null;
		List dataList = new ArrayList<>();
		try {
			conn = JdbcUtils.getConnection();
			state = conn.prepareStatement(sql);
			for(int index = 0; index < args.length; index++) {
				state.setObject(index + 1, args[index]);
			}
			state.executeQuery();
			
			rs = state.getResultSet();
			//获取结果集的一些元数据
			ResultSetMetaData metaData = rs.getMetaData();
			while(rs.next()) {
				Object obj = this.klass.newInstance();
				int count = metaData.getColumnCount();
				for(int index = 1; index <= count; index++) {
					//获取别名  注意别名就是JavaBean中的成员名
					String fieldName = metaData.getColumnLabel(index);
					Object value = rs.getObject(fieldName);
					//传入对象  成员名  成员值  反射设置值
					setValue(obj, fieldName, value);
				}
				dataList.add((T) obj);
			}
			return dataList;
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			JdbcUtils.close(conn, state, rs);
		}
		return null;
	}
	
	protected  E getValue(String sql, Object...args) {
		Connection conn = null;
		PreparedStatement state = null;
		ResultSet rs = null;
		try {
			conn = JdbcUtils.getConnection();
			state = conn.prepareStatement(sql);
			for(int index = 0; index < args.length; index++) {
				state.setObject(index + 1, args[index]);
			}
			state.executeQuery();
			
			rs = state.getResultSet();
			if(rs.next()) {
				return (E) rs.getObject(1);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			JdbcUtils.close(conn, state, rs);
		}
		return null;
	}
	
	private void setValue(Object obj, String fieldName, Object value) {
		try {
			Field field = this.klass.getDeclaredField(fieldName);
			field.setAccessible(true);
			field.set(obj, value);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

需要注意的一点是数据库中的字段名称和java的成员名称可能会不同。所以在制造sql语句的时候一定要利用别名。

dbutils工具的使用:

首先需要导入jar包:我用的是commons-dbutils-1.3.jar

代码示例:

public abstract class DataBase {
	private Class klass = null;
	private QueryRunner queryRunner = null;
	
	public DataBase() {
		Type superClass = this.getClass().getGenericSuperclass();
		if(superClass instanceof ParameterizedType) {
			ParameterizedType paraType = (ParameterizedType) superClass;
			Type[] args = paraType.getActualTypeArguments();
			if(args != null && args.length > 0 && (args[0] instanceof Class)) {
				this.klass = (Class) args[0];
			}
		}
		this.queryRunner = new QueryRunner();
	}
	
	//获取对象集合 BeanListHandler
	protected List getList(String sql, Object...args){
		Connection conn = JdbcUtils.getConnection();
		try {
			return this.queryRunner.query(conn, sql, 
					new BeanListHandler(klass), args);
		} catch (SQLException e) {
			e.printStackTrace();
		}finally{
			JdbcUtils.close(conn, null, null);
		}
		
		return null;
	}
	
	//查询特殊值new ScalarHandler()
	protected  E getValue(String sql, Object...args) {
		Connection conn = JdbcUtils.getConnection();
		try {
			return (E) this.queryRunner.query(conn, sql, new ScalarHandler(), args);
		} catch (SQLException e) {
			e.printStackTrace();
		}finally{
			JdbcUtils.close(conn, null, null);
		}
		return null;
	}
	
	//批量操作
	protected void batch(String sql, Object[]...args) {
		Connection conn = JdbcUtils.getConnection();
		try {
			this.queryRunner.batch(conn, sql, args);
		} catch (SQLException e) {
			e.printStackTrace();
		}finally{
			JdbcUtils.close(conn, null, null);
		}
	}
}

基于此工具的一个测试:

定义IUserDao接口:

public interface IUserDao {
	public List getUserListByMoney(double money);
	public long getUserCount();
	public void batchUpdateMoney(List userList);
}

 实现类:

public class UserDaoImpl extends DataBase implements IUserDao{
	
	public UserDaoImpl() {
		JdbcUtils.scanf("/druid.properties");
	}

	@Override
	public List getUserListByMoney(double money) {
		String sql = "select id, username userName, password, email, money from t_user where money=?";
		return getList(sql, new Object[]{money});
	}
	
	@Override
	public long getUserCount() {
		String sql = "select count(*) from t_user";
		return getValue(sql, new Object[]{});
	}

	//批量操作   以批量更新余额为例
	@Override
	public void batchUpdateMoney(List userList) {
		String sql = "update t_user set money=? where username=?";
		//总共更新的记录数
		int size = userList.size();
		
		Object[][] args = new Object[size][2];
		//填充数组
		for(int index = 0; index < size; index++) {
			Object[] arg = new Object[2];
			arg[0] = userList.get(index).getMoney();
			arg[1] = userList.get(index).getUserName();
			args[index] = arg;
		}
		
		batch(sql, args);
	}
}

测试类: 

public class Test {

	public static void main(String[] args) {
		UserDaoImpl userDao = new UserDaoImpl();
		System.out.println("总用户个数: " + userDao.getUserCount());;
		System.out.println("--------------获取余额为10000元的用户---------------------------------");
		List userList = userDao.getUserListByMoney(10000.0);
		for(User user : userList) {
			System.out.println(user);
		}
	
		userList = new ArrayList();
		userList.add(new User("san", "", "", 3333.0));
		userList.add(new User("feng", "", "", 3333.0));
		System.out.println("修改san和feng的余额为3333");
		userDao.batchUpdateMoney(userList);
		System.out.println("修改成功");
		
		System.out.println("--------------获取余额为3333元的用户---------------------------------");
		userList = userDao.getUserListByMoney(3333.0);
		for(User user : userList) {
			System.out.println(user);
		}
	}
	
}

测试结果:

JDBC技术(三)工具的封装_第1张图片

你可能感兴趣的:(java基础)