JDBC学习笔记-03-用PreparedStatement实现数据增删改查操做

为什么使用PreparedStatement

  • 最重要的是避免Statement的sql注入问题
  • 其次解决了拼串的繁琐,
  • 还有很重要的一点因为PreparedStatement实现了预编译操做,在批量操做时,其效率原高于Statement.
  • 并且可以操做Blob数据

通用的增删改操做

@Test
	public void testCommonUpdate() {
//		String sql = "delete from customers where id = ?";
//		updataTest(sql,19);
		
		String sql = "update `order` set order_name = ? where order_id = ?";
		updataTest(sql,"Anna",4);
	}
	
	
	//通用的增删改操做
	public void updataTest(String sql,Object ...args){//sql语句中占位符个数与可变形参个数必须相同
		Connection conn = null;
		PreparedStatement ps = null;
		try {
			//1.加载并注册驱动获取数据库的连接
			conn = JdbcUtils.getConnection();
			//2.预编译SQL语句返回PrepareStatement的实例
			ps = conn.prepareStatement(sql);
			//3.填充占位符
			for (int i = 0; i < args.length; i++) {
				ps.setObject(i + 1, args[i]);
			}
			
			//4.执行
			ps.execute();
		}  catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			//5.关闭资源
			JdbcUtils.closeResource(conn, ps);
		}
	}

通用的返回一条记录

@Test
	public void testGetInstance() {
		String sql = "SELECT `order_id` orderId,`order_name` orderName,`order_date` orderDate FROM `order` WHERE order_id = ?";
		Order instance = getInstance(Order.class, sql, 1);
		System.out.println(instance);
		
		sql = "select id,name,email,birth from customers where id = ?";
		Customer instance2 = getInstance(Customer.class, sql,18 );
		System.out.println(instance2);
	}
	
	/**
	 *  针对于不同表的通用的查询操做,返回表中的一条记录
	 * @param clazz
	 * @param sql
	 * @param args
	 * @return
	 */
	public <T> T getInstance(Class<T> clazz,String sql,Object ...args) {
		Connection conn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		try {
			//获取连接
			conn = JdbcUtils.getConnection();
			//获取PreparedStatement
			ps = conn.prepareStatement(sql);
			//填充占位符
			for(int i = 0;i < args.length;i++) {//填充占位符从1开始
				ps.setObject(i+1, args[i]);
			}
			
			//执行SQL语句
			rs = ps.executeQuery();
			ResultSetMetaData metaData = rs.getMetaData();
			int columnCount = metaData.getColumnCount();
			
			//类似于迭代器指针
			if(rs.next()) {
//				Order order = new Order();
				T t = clazz.newInstance();
				//遍历一条记录里的各个字段
				for(int i = 0;i < columnCount;i++) {
					//遍历每一个字段的名字为反射提供属性名和
//					String columnName = metaData.getColumnName(i+1);
					String columnLabel = metaData.getColumnLabel(i + 1);
					Object columnValue = rs.getObject(i+1);
					
					//为order指定的columnName赋值columnValue,通过反射
					Field field = clazz.getDeclaredField(columnLabel);
					field.setAccessible(true);
					field.set(t, columnValue);
				}
				return t;
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			//关闭资源
			JdbcUtils.closeResource(conn, ps, rs);
		}
		return null;
	}

通用的返回多条记录

@Test
	public void testGetListInstance() {
		String sql = "SELECT `order_id` orderId,`order_name` orderName,`order_date` orderDate FROM `order` ";
		List<Order> listInstance = getListInstance(Order.class, sql);
		Iterator<Order> iterator = listInstance.iterator();
		while(iterator.hasNext()) {
			Order next = iterator.next();
			System.out.println(next);
		}
		listInstance.forEach(System.out::println);
		
		sql = "SELECT `id`,`name`,`email`,`birth` FROM `customers`";
		List<Customer> list = getListInstance(Customer.class, sql);
		list.forEach(System.out::println);
		
	}
	
	
	public <T> List<T> getListInstance(Class<T> clazz,String sql,Object ...args){
		Connection conn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		ArrayList<T> alist = null;
		try {
			conn = JdbcUtils.getConnection();
			ps = conn.prepareStatement(sql);
			for (int i = 0; i < args.length; i++) {
				ps.setObject(i + 1, args[i]);
			}
			
			rs = ps.executeQuery();
			//获取结果集元数据
			ResultSetMetaData rsmd = rs.getMetaData();
			int columnCount = rsmd.getColumnCount();
			alist = new ArrayList<T>();
			
			while(rs.next()) {
				T t = clazz.newInstance();
				for(int i = 0;i < columnCount;i++) {
					//获取列别名
					String columnLabel = rsmd.getColumnLabel(i + 1);
					//获取列值
					Object columnValue = rs.getObject(i + 1);
					
					//为列名为columnLabel的赋值,通过反射
					Field field = clazz.getDeclaredField(columnLabel);
					//防止field为私有权限
					field.setAccessible(true);
					field.set(t, columnValue);
				}
				alist.add(t);
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			JdbcUtils.closeResource(conn, ps, rs);
		}
		
		return alist;
		
	}

ResultSet

       查询需要调用PreparedStatement 的 executeQuery() 方法,查询结果是一个ResultSet 对象
       ResultSet 对象以逻辑表格的形式封装了执行数据库操作的结果集,ResultSet 接口由数据库厂商提供实现
       ResultSet 返回的实际上就是一张数据表。有一个指针指向数据表的第一条记录的前面。
       ResultSet 对象维护了一个指向当前数据行的游标,初始的时候,游标在第一行之前,可以通过 ResultSet 对象的 next() 方法移动到下一行。调用 next()方法检测下一行是否有效。若有效,该方法返回 true,且指针下移。相当于Iterator对象的 hasNext() 和 next() 方法的结合体。
       当指针指向一行时, 可以通过调用 getXxx(int index) 或 getXxx(int columnName) 获取每一列的值。

  • 例如: getInt(1), getString(“name”)
  • 注意:Java与数据库交互涉及到的相关Java API中的索引都从1开始。

在这里插入图片描述

ResultSetMetaData

可用于获取关于 ResultSet 对象中列的类型和属性信息的对象

ResultSetMetaData meta = rs.getMetaData();
  • getColumnName(int column):获取指定列的名称

  • getColumnLabel(int column):获取指定列的别名

  • getColumnCount():返回当前 ResultSet 对象中的列数。

  • getColumnTypeName(int column):检索指定列的数据库特定的类型名称。

  • getColumnDisplaySize(int column):指示指定列的最大标准宽度,以字符为单位。

  • isNullable(int column):指示指定列中的值是否可以为 null。

  • isAutoIncrement(int column):指示是否自动为指定列进行编号,这样这些列仍然是只读的。

获取 ResultSet 中有多少列
调用 ResultSetMetaData 的 getColumnCount() 方法
获取 ResultSet 每一列的列的别名
调用 ResultSetMetaData 的getColumnLabel() 方法

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页