DAO:Date Access Object
实现代码模块化,更加有利于代码的维护和升级。
DAO 可以被子类继承或者直接使用。
访问数据信息的类,包含对数据的CRUD(create read update delete),而不包含任何业务相关信息。
使用JDBC编写DAO可能包含的方法:
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);
Java类的属性:
在J2ee中,Java类的属性通过getter,setter来定义:get(或者set)方法,去除get(或者set)后,后字母小写即为Java类的属性。
一般情况下,字段名和属性名称一致。
操作Java类的属性工具包:beanutils
搭建环境:
common_beanutils_1.8.0.jar和common_logging_1.1.1.jar
beanutils的使用Demo:
public class BeanUtilsTest { @Test public void testGetProperty() throws IllegalAccessException, InvocationTargetException, NoSuchMethodException{ Object object = new Student(); System.out.println(object); BeanUtils.setProperty(object, "idCard", "211121196509091876"); System.out.println(object); Object val = BeanUtils.getProperty(object, "idCard"); System.out.println(val); } @Test public void testSetProperty() throws IllegalAccessException, InvocationTargetException { Object object = new Student(); System.out.println(object); BeanUtils.setProperty(object, "idCard2", "211121196509091876"); System.out.println(object); } }
Dao类封装:
import java.lang.reflect.InvocationTargetException; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; 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(result.size() > 0){ return result.get(0); } return null; } /** * 传入 SQL 语句和 Class 对象, 返回 SQL 语句查询到的记录对应的 Class 类的对象的集合 * @param clazz: 对象的类型 * @param sql: SQL 语句 * @param args: 填充 SQL 语句的占位符的可变参数. * @return */ 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 为 reusltSet 中列的别名, Map 的 value //为列的值. List<Map<String, Object>> values = handleResultSetToMapList(resultSet); //3. 把 Map 的 List 转为 clazz 对应的 List //其中 Map 的 key 即为 clazz 对应的对象的 propertyName, //而 Map 的 value 即为 clazz 对应的对象的 propertyValue list = transfterMapListToBeanList(clazz, values); } catch (Exception e) { e.printStackTrace(); } finally { JDBCTools.releaseDB(resultSet, preparedStatement, connection); } return list; } public <T> List<T> transfterMapListToBeanList(Class<T> clazz, List<Map<String, Object>> values) throws InstantiationException, IllegalAccessException, InvocationTargetException { List<T> result = new ArrayList<>(); T bean = null; if (values.size() > 0) { for (Map<String, Object> m : values) { bean = clazz.newInstance(); for (Map.Entry<String, Object> entry : m.entrySet()) { String propertyName = entry.getKey(); Object value = entry.getValue(); BeanUtils.setProperty(bean, propertyName, value); } // 13. 把 Object 对象放入到 list 中. result.add(bean); } } return result; } /** * 处理结果集, 得到 Map 的一个 List, 其中一个 Map 对象对应一条记录 * * @param resultSet * @return * @throws SQLException */ public List<Map<String, Object>> handleResultSetToMapList( ResultSet resultSet) throws SQLException { // 5. 准备一个 List<Map<String, Object>>: // 键: 存放列的别名, 值: 存放列的值. 其中一个 Map 对象对应着一条记录 List<Map<String, Object>> values = new ArrayList<>(); 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 SQLException */ private List<String> getColumnLabels(ResultSet rs) throws SQLException { 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(); if(resultSet.next()){ return (E) resultSet.getObject(1); } } catch(Exception ex){ ex.printStackTrace(); } finally{ JDBCTools.releaseDB(resultSet, preparedStatement, connection); } //2. 取得结果 return null; } }