DAO设计模式
DAO
Data Access Object
-
why:实现功能的模块化,更有利于代码的维护和升级 DAO可以被子类继承或直接使用
-
what:访问数据信息的类,包括了对数据的CRUD(create,read,update,delete)
而不包含任何业务相关信息 -
how: 使用JDBC编写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> 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=transfterMapListToBeanList(clazz, values); }catch(Exception e) { e.printStackTrace(); } return null; }
-
上述方法里包含的方法
/** * 获取结果集的ColumnLabel 对应的List * @param rs * @return * @throws SQLException */ private List<String> getColumnLabels(ResultSet rs) throws SQLException{ List<String> labels=new ArrayList<>(); ResultSetMetaData rsmd=(ResultSetMetaData) rs.getMetaData(); for(int i=0;i<rsmd.getColumnCount();i++) { labels.add(rsmd.getColumnLabel(i+1)); } return labels; }
/** * 处理结果集, 得到 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; }
public <T> List<T> transfterMapListToBeanList(Class<T> clazz, List<Map<String, Object>> values) throws InstantiationException, IllegalAccessException, InvocationTargetException { List<T> result = new ArrayList<>(); //12.判断List是否为空集合 若不为空 //则遍历List,得到一个一个的Map对象,再把一个Map独享转换为一个Class //参数对应的Object对象 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; }
-
-
//查询一条记录,返回对应的对象
-
详细的方法
//查询一条记录,返回对应的对象 public <T> T get(Class<T> clazz,String sql,Object...args){ T entity=null; Connection connection=null; PreparedStatement preparedStatement=null; ResultSet resultSet=null; try{ //1.获取Connection connection =JDBCTools.getConnection(); //2.获取PreparedStatement preparedStatement=connection.prepareStatement(sql); //3.填充占位符 for(int i=0;i<args.length;i++){ preparedStatement.setObject(i+1,args[i]); } //4.进行查询,得到ResultSet resultSet=preparedStatement.executeQuery(); //5.若ResultSet中有记录,准备一个Map<String,Object>: 键:存放列的别名,值:存放列的值 if(resultSet.next()){ Map<String,Object> values=new HashMap<String,Object>(); //6.得到ResultSetMetaData对象 ResultSetMetaData rsmd=resultSet.getMetaData(); //7.处理ResultSet,把指针向下移动一个单位 //8.由ResultSetMetaData对象得到结果集中有多少列 int columnCount=rsmd.getColumnCount(); //9.由ResultSetMetaData得到每一列的别名,由ResultSet得到具体每一列的值 for(int i=0;i<columnCount;i++){ String columnLabel=rsmd.getColumnLabel(i+1); Object columnValue=resultSet.getObject(i+1); //10.填充Map对象 values.put(columnLabel,columnValue); } //11.用反射创建Class对应的对象 entity =clazz.newInstance(); //12.遍历Map 对象,用反射填充对象的属性值:属性名为Map中的key,属性值为Map中的value for(Map.Entry<String,Object> entry:values.entrySet()){ String propertyName=entry.getKey(); Object value=entry.getValue(); //通过反射赋值 ReflectionUtils.setFieldValue(entity,propertyName,value); BeanUtils.setProperty(entity,propertyName,value); } } }catch(Exception e){ e.printStackTrace(); }finally{ JDBCTools.raleaseDB(resultSet,preparedstatement,connection); } return entity; }
-
重用了查询多条记录方法的代码的简洁方法
//查询一条记录,返回对应的对象 因为这是查询一条记录所以可以重用下面的查询多条记录的代码 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; }
-
//返回某条记录的某个字段的值或一个统计的值(一共有多少条记录等)
public <E> E getForValue(String sql,Object...args) { //1.得到结果集:该结果集应该只有一行,且只有一列 Connection connection=null; PreparedStatement preparedStatement=null; ResultSet resultSet=null; try { 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 e) { e.printStackTrace(); }finally { JDBCTools.releaseDB(resultSet, preparedStatement, connection); } //2.取得结果集的 return null; }
-
-
上述方法中用到的工具类
-
获取数据库连接
-
public static Connection getConnection() throws Exception { Properties properties = new Properties(); InputStream inStream = JDBCTools.class.getClassLoader() .getResourceAsStream("jdbc.properties"); properties.load(inStream); // 1. 准备获取连接的 4 个字符串: user, password, jdbcUrl, driverClass String user = properties.getProperty("user"); String password = properties.getProperty("password"); String jdbcUrl = properties.getProperty("jdbcUrl"); String driverClass = properties.getProperty("driverClass"); // 2. 加载驱动: Class.forName(driverClass) Class.forName(driverClass); // 3. 调用 // DriverManager.getConnection(jdbcUrl, user, password) // 获取数据库连接 Connection connection = DriverManager.getConnection(jdbcUrl, user, password); return connection; }
-
-
关闭数据库资源
-
public static void releaseDB(ResultSet resultSet, Statement statement, Connection connection) { if (resultSet != null) { try { resultSet.close(); } catch (SQLException e) { e.printStackTrace(); } } if (statement != null) { try { statement.close(); } catch (SQLException e) { e.printStackTrace(); } } if (connection != null) { try { connection.close(); } catch (SQLException e) { e.printStackTrace(); } } }
-
-
-
properties文件中
-
user=xuefeng password=1234 driverClass=com.mysql.jdbc.Driver jdbcUrl=jdbc:mysql://localhost:3306/xuefeng?useUnicode=true&characterEncoding=utf8
-
Java类的属性
-
在JavaEE中,Java类的属性通过getter,setter来定义:get(或set)方法,去除get(或set)后,后字母小写即为Java类的属性
-
而以前叫的那个属性,即成员变量,称之为字段 一般情况下,字段名和属性名都一致
-
操作Java类的属性有一个工具包:beanutils
搭建环境需要同时加入commons-logging-1.2.jar和commons-beanutils-1.8.0.jar
-
①setProperty()
BeanUtils.setProperty(object, "idCard", "211121196509091876");
-
②getProperty()
Object val = BeanUtils.getProperty(object, "idCard");
-