欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java JDBC入门之八 : DAO设计模式重构查询方法 AND 使用BeanUtils工具类操作JavaBean

程序员文章站 2023-12-22 20:05:52
...

Java JDBC入门之七 : DAO设计模式重构查询方法 AND 使用BeanUtils工具类操作JavaBean

1. DAO 设计思想 Data Access Object

为什么要存在这样的思想?

  1. 实现功能的模块化. 更有利于代码的维护和升级.
  2. DAO 可以被子类继承或直接使用

DAO是什么?

  1. 访问数据信息的类。包含了数据的CRUD (create,read.,update,delete).
  2. 不包含任何业务相关的信息的类.

使用JDBC 编写 DAO 可能会包含的方法?

//INSERT, UPDATE,DELETE 操作都可以包含在其中
void update(String sql, Object ... args )

//查询一条记录,返回对应的对象
<T> T get(Class<T> clazz, String sql, Object...args);

//查询多条记录,返回对应的对象的集合
<T> List<T> getForList(Class<T> clazz , String sql, Object...args )

//返回某条记录的某一个字段的值 或一个统计的值(一共有多少条记录等。)
<E> E getForValue(String sql,Object ... args);

2. Java 类的属性:

  1. 在JavaEE 中,Java 类的属性通过 getter,setter来定义 , 也就是说get(或 set)方法,去除get(或set)后,后字母小写即为Java 类的属性。 因为我们有单独操作getter和setter的技术。
  2. 而以前叫的那个属性,即成员变量,称之为字段。
  3. 一般情况下,字段名和属性名都一致。
  4. 操作Java 类的属性有一个工具包: beanUtils
    1. BeanUtils主要是用于将对象的属性封装到对象中
    2. 搭建环境:需要同时加入: commons-beanutils-1.x.x.jar 和 commons-logging-1.x.x.jar
    3. ①.setProperty(bean, name, value) : 其中bean是指你将要设置的对象,name指的是将要设置的属性(写成”属性名”),value(属性的值)
      1. BeanUtils设置属性的时候也是依赖于底层的getter和setter方法
      2. BeanUtils设置属性值,如果属性是基本数据类型,BeanUtils会自动帮我们进行数据类型的转换
      3. 注意:如果设置的属性值是其他的引用数据类型,此时必须要注册一个类型转换器才能实现自动的转换
    4. ②.getProperty(bean,name) :获取Bean对象属性名为name的值

3.Demo

  1. DAO.java类运行前,需要JDBCTools.java,而这个类可在之前博客找到。
  2. 测试代码
public class DAOTest {
	
	DAO dao = new DAO();
	
	@Test
	public void testUpdate() {
		String sql = "INSERT INTO customers(name, "
				+ " email,birth) VALUES(?,?,?);";
		dao.update(sql, "xiaoming","[email protected]",new Date(new java.util.Date().getTime()));
	}

	@Test
	public void testGet() {
		String sql = "SELECT flow_id flowId, type,exam_card examCard, "
				+ "id_card idCard,student_name studentName, location, "
				+ "grade FROM examstudent WHERE flow_id = ?";
		Student student = dao.get(Student.class, sql, 5);
		System.out.println(student);
	}

	@Test
	public void testGetForList() {
		String sql = "SELECT flow_id flowId, type,exam_card examCard, "
				+ "id_card idCard,student_name studentName, location, "
				+ "grade FROM examstudent";
		List<Student> students = dao.getForList(Student.class, sql);
		System.out.println(students);
	}

	@Test
	public void testGetForValue() {
		String sql = "SELECT exam_card FROM examstudent "
				+ "WHERE flow_id = ?";
		String str = dao.getForValue(sql,1);
		System.out.println(str);
	}

}

import org.apache.commons.beanutils.BeanUtils;

public class DAO {
	
	//INSERT, UPDATE,DELETE 操作都可以包含在其中
	public void update(String sql, Object ... args ){
		Connection connection = null;
		PreparedStatement preparedStatement = null;
		
		try {
			connection = JDBCTools.getConnection();
			preparedStatement = connection.prepareStatement(sql);
			
			for (int i = 0; i < args.length; i++) {
				preparedStatement.setObject(i+1, args[i]);
			}
			
			preparedStatement.executeUpdate();
		}catch (Exception e) {
			e.printStackTrace();
		}finally {
			JDBCTools.releaseDB(null, preparedStatement, connection);
		}
	}

	//查询一条记录,返回对应的对象
	public <T> T get(Class<T> clazz, String sql, Object...args) {
		
		List<T>  result = getForList(clazz, sql, args);
		if( 0 < result.size()) {
			return result.get(0);
		}
		return null;
		
	}

	//查询多条记录,返回对应的对象的集合
	public <T> List<T> getForList(Class<T> clazz , String sql, Object...args ){
		
		List<T> list = new ArrayList<>();
		
		Connection connection = null;
		PreparedStatement preparedStatement = null;
		ResultSet resultSet = null;
		try {
			//1. 得到结果集
			connection = JDBCTools.getConnection();
			preparedStatement = connection.prepareStatement(sql);
			
			for (int i = 0; i < args.length; i++) {
				preparedStatement.setObject(i+1, args[i]);
			}
			
			resultSet  = preparedStatement.executeQuery();
			
			// 2. 处理结果集,得到Map 的List,其中一个Map对象
			//就是一条记录,Map 的 key 为 resultSet 中的别名, Map 的 value 为列的值
			List<Map<String, Object>> values = handleResultSetToMapList(resultSet);
			
			// 3.把 Map 的 List 转化为 clazz 对应的 List
			// 其中Map 的 key 即为 clazz 对应的对象的propertyName
			// 而 Map 的 value 即为 clazz 对应的对象的 propertyValue
			list = transferMapListToBeanList(clazz, values);
			
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			JDBCTools.releaseDB(resultSet, preparedStatement, connection);
		}
		
		return list;
	}
	
	/**
	 *转换MapList为BeanList 
	 * @param clazz
	 * @param values
	 * @return
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 * @throws InvocationTargetException
	 */
	private <T> List<T> transferMapListToBeanList(Class<T> clazz, List<Map<String, Object>> values)
			throws InstantiationException, IllegalAccessException, InvocationTargetException {
		
		//12. 判断List 是否为空集合, 若不为空,则遍历List,得到一个一个的Map的对象,
		// 在把一个Map对象转为一个Class参数对应的Object对象
		List<T> result = new ArrayList<>();
		
		T bean = null;
		if (0 < values.size()) {
			for(Map<String,Object> m : values) {
				
				bean = clazz.newInstance();
				for (Map.Entry<String,  Object> entry: m.entrySet()) {
					String propertyName = entry.getKey();
					Object propertyValue = entry.getValue();
					
					//BeanUtils.工具类的使用,为封装的对象的属性赋值
					BeanUtils.setProperty(bean, propertyName, propertyValue);
				}
				//13. 把Object 对象放入到List<T> list 中。
				result.add(bean);
			}
		}
		
		return result;
	}
	
	/**
	 * 处理结果集,得到Map的一个List,其中一个Map对应一条记录。
	 * @param resultSet
	 * @return
	 * @throws Exception
	 * @throws SQLException
	 */
	private List<Map<String, Object>> handleResultSetToMapList(ResultSet resultSet) throws Exception, SQLException {
		//5. 若ResultSet 中有记录 ,准备 一个List<Map<String,Object>>:
		//建:存放列的别名 , 值: 存放列的值.其实一个Map 对象对应一条记录
		List<Map<String, Object>> values = new ArrayList<Map<String,Object>>();
		
		List<String> columnLabels = getColumnLabels(resultSet);
		Map<String,Object> map = null;
		
		//7. 处理ResultSet,使用while循环
		while(resultSet.next()) {
			
			map =  new HashMap<>();
			
			for(String columnLabel : columnLabels ) {
				
				Object value = resultSet.getObject(columnLabel);
				map.put(columnLabel, value);
			}
			
			//11. 把一条记录的一个Map对象 放入 5 准备的List中
			values.add(map);
		}
		return values;
	}
	/**
	 * 获取结果集的ColumnLabel 对应的List
	 * @param rs
	 * @return
	 * @throws Exception
	 */
	private List<String> getColumnLabels(ResultSet rs) throws Exception{
		List<String> labels = new ArrayList<>();
		
		ResultSetMetaData rsmd = rs.getMetaData();
		for(int i = 0; i < rsmd.getColumnCount(); i ++) {
			labels.add(rsmd.getColumnLabel( i + 1 ));
		}
		return labels;
	}

	//返回某条记录的某一个字段的值 或一个统计的值(一共有多少条记录等。)
	public <E> E getForValue(String sql,Object ... args) {
		
		//1. 得到结果集 : 该结果集应该只有一行,且只有一列
		Connection connection = null;
		PreparedStatement preparedStatement = null;
		ResultSet resultSet = null;
		try {
			//1. 得到结果集
			connection = JDBCTools.getConnection();
			preparedStatement = connection.prepareStatement(sql);
			
			for (int i = 0; i < args.length; i++) {
				preparedStatement.setObject(i+1, args[i]);
			}
			
			resultSet  = preparedStatement.executeQuery();
			
			//2. 取得结果
			if (resultSet.next()) {
				return (E) resultSet.getObject(1);
			}
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			JDBCTools.releaseDB(resultSet, preparedStatement, connection);
		}
		return null;
	}
}

上一篇:

下一篇: