JDBC-DAO设计模式

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");

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值