JDBC(三)—— 使用PreparedStatement实现CRUD(增删改查)操作

使用PreparedStatement实现CRUD(增删改查)操作

操作和访问数据库

数据库连接被用于向数据库服务器发送命令和SQL语句,并接受数据库服务器返回的结果。其实一个数据库连接就是一个Socket连接。

Java.sql包中有三个接口分别定义了数据库的调用的不同方式:

  • Statement:用于执行静态SQL语句并返回它所产生的结果的对象

  • PrepatedStatement:SQL语句被预编译并存贮在此对象中,可使用此对象多次高效的执行该语句

  • CallableStatement:用于执行SQL存储过程

使用Statement操作数据表的弊端

通过调用Connection对象的creatStatemen()方法创建该对象

弊端:

  1. 存在拼串操作,繁琐

  2. 存在SQL注入问题

SQL注入是利用某些系统没有对用户输入的数据进行充分的检查,而在用户输入数据中注入非法的SQL语句段或命令,从而利用系统的SQL引擎完成恶意行为的做法。

利用PrepatedStatement实现表数据的添加

Connection conn = null;
PreparedStatement ps = null;
try {
   //获取配置文件信息
   InputStream is = ConnectionTest.class.getClassLoader().getResourceAsStream("jdbc.properties");

   Properties pros = new Properties();
   pros.load(is);

   String user = pros.getProperty("user");
   String password = pros.getProperty("password");
   String url = pros.getProperty("url");
   String driver = pros.getProperty("driver");

   //加载dirver
   Class.forName(driver);

   //获取连接
   conn = DriverManager.getConnection(url,user,password);
   System.out.println(conn);

   //预编译sql语句返回PreparedStatement实例
   String sql = "insert into user(username,password,phone_no,address,reg_date) values (?,?,?,?,?)";
   ps = conn.prepareStatement(sql);

   //填充占位符
   ps.setString(1,"wyq");
   ps.setString(2,"123");
   ps.setString(3,"145662566");
   ps.setString(4,"兰州");
   SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
   Date date1 = simpleDateFormat.parse("2020-01-01");
   ps.setDate(5, new java.sql.Date(date1.getTime()));

   //执行操作
   ps.execute();

   System.out.println("成功");
} catch (Exception e) {
   e.printStackTrace();
} finally {
   try {
       if (ps!=null){
           ps.close();
      }
       if (conn != null) {
           conn.close();
      }
  } catch (SQLException throwables) {
       throwables.printStackTrace();
  }
}

实现JdbcUtils工具类

package com.why.utils;

import com.why.connection.ConnectionTest;

import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties;

/**
* @Description TODO 操作数据库的工具类
* @Author why
* @Date 2020/10/10 16:54
* Version 1.0
**/
public class JdbcUtils {

   /**
    * 获取数据库连接
    * @return
    * @throws Exception
    */
   public static Connection getConnection() throws Exception {
       //获取配置文件信息
       InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties");

       Properties pros = new Properties();
       pros.load(is);

       String user = pros.getProperty("user");
       String password = pros.getProperty("password");
       String url = pros.getProperty("url");
       String driver = pros.getProperty("driver");

       //加载dirver
       Class.forName(driver);

       //获取连接
       Connection conn = DriverManager.getConnection(url,user,password);

       return conn;
  }

   public void closeResource(Connection conn, Statement ps){
       try {
           if (conn!=null){
               conn.close();
          }
           if (ps!=null){
               ps.close();
          }
      } catch (SQLException throwables) {
           throwables.printStackTrace();
      }
  }
   
    public static void closeResource(Connection conn,Statement ps,ResultSet rs){
       try {
           if (conn!=null){
               conn.close();
          }
           if (ps!=null) {
               ps.close();
          }
           if (rs!=null){
               rs.close();
          }
      } catch (SQLException throwables) {
           throwables.printStackTrace();
      }
  }
}

使用JdbcUtils修改表中的记录

/**
* 修改表的一条记录
*/
@Test
public void testUpdate() throws Exception {
   //1.获取数据库连接
   Connection conn = JdbcUtils.getConnection();
   //2.预编译sql语句,返回PreparedStatement实例
   String sql = "update user set username = ? where id = ?";
   PreparedStatement ps = conn.prepareStatement(sql);
   //3.填充占位符
   ps.setString(1,"wyq");
   ps.setObject(2,3);
   //4.执行
   ps.execute();
   //5.资源关闭
   JdbcUtils.closeResource(conn,ps);
   System.out.println("成功");
}

通用的更新操作(增删改)

/**
* 通用的更新操作,增删改
* @param sql
* @param args
*/
public void Update(String sql,Object ...args) {
   Connection conn = null;
   PreparedStatement ps = null;
   try {
       //1.获取连接
       conn = JdbcUtils.getConnection();
       //2.预编译sql语句,返回preparedStatement实例
       ps = conn.prepareStatement(sql);
       //3.填充占位符
       //sql占位符的个数与可变形参的长度相同,可变形参相当于一个数组
       for (int i = 0; i < args.length ; i++) {
           ps.setObject(i+1,args[i]);
      }
       //4.执行
       ps.execute();
  } catch (Exception e) {
       e.printStackTrace();
  } finally {
       //5.资源关闭
       JdbcUtils.closeResource(conn,ps);
  }
}

ORM编程思想

Object relation mapping

  • 一个数据表对应一个Java类

  • 表中的一条记录对于一个Java对象

  • 表中的一个字段对应Java类的一个属性

对于同一个表的通用查询

查询不同字段

/**
* @Description TODO 实现对数据表的增删改查操作
* @Author why
* @Date 2020/10/10 16:23
* Version 1.0
**/
public class PreparedStatementUpdateTest {

   @Test
   public void testQuery() throws Exception {
       //属性名与字段名不同时,用属性名给字段名做别名
       String sql = "select phone_no phoneNo,reg_date regDate from user where id = ?";
       User user = queryForUser(sql, 1);
       System.out.println(user);
  }

   public User queryForUser(String sql,Object ...args) throws Exception {
       Connection conn = null;
       PreparedStatement ps = null;
       ResultSet rs = 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();
           if (rs.next()){
               User user = new User();
               //处理结果集一行数据中的字段
               for (int i = 0; i < columnCount ; i++) {

                   //获取字段值,通过结果集
                   Object value = rs.getObject(i + 1);

                   //获取结果集中的字段名,通过元数据
                   //获取列的别名
                   String columnName = rsmd.getColumnLabel(i+1);

                   //给user对象指定的指定属性赋值为value,通过反射
                   //**注意属性名和字段名不同
                   Field field = User.class.getDeclaredField(columnName);
                   field.setAccessible(true);
                   field.set(user,value);
              }
               return user;
          }
      } catch (Exception e) {
           e.printStackTrace();
      } finally {
           JdbcUtils.closeResource(conn,ps,rs);
      }
       return null;
  }
}

User.java

package com.why.entity;

import java.util.Date;

/**
* @Description TODO ORM
* @Author why
* @Date 2020/10/10 16:16
* Version 1.0
**/
public class User {
   private int id;
   private String username;
   private String password;
   private String phoneNo;
   private String address;
   private Date regDate;

   public User(int id, String username, String password, String phoneNo, String address, Date regDate) {
       this.id = id;
       this.username = username;
       this.password = password;
       this.phoneNo = phoneNo;
       this.address = address;
       this.regDate = regDate;
  }

   public User() {
  }

   @Override
   public String toString() {
       return "User{" +
               "id=" + id +
               ", username='" + username + '\'' +
               ", password='" + password + '\'' +
               ", phoneNo='" + phoneNo + '\'' +
               ", address='" + address + '\'' +
               ", regDate=" + regDate +
               '}';
  }

   public int getId() {
       return id;
  }

   public void setId(int id) {
       this.id = id;
  }

   public String getUsername() {
       return username;
  }

   public void setUsername(String username) {
       this.username = username;
  }

   public String getPassword() {
       return password;
  }

   public void setPassword(String password) {
       this.password = password;
  }

   public String getPhoneNo() {
       return phoneNo;
  }

   public void setPhoneNo(String phoneNo) {
       this.phoneNo = phoneNo;
  }

   public String getAddress() {
       return address;
  }

   public void setAddress(String address) {
       this.address = address;
  }

   public Date getRegDate() {
       return regDate;
  }

   public void setRegDate(Date regDate) {
       this.regDate = regDate;
  }
}

查询流程

image-20201011115654583

对于不同数据表进行数据操作

对于不同表的一个对象的通用查询操作

package com.why.connection;

import com.sun.source.tree.ParenthesizedTree;
import com.why.entity.User;
import com.why.utils.JdbcUtils;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.sql.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties;

/**
* @Description TODO 实现对数据表的增删改查操作
* @Author why
* @Date 2020/10/10 16:23
* Version 1.0
**/
public class PreparedStatementUpdateTest {

   @Test
   public void testQuery() {
       //记得写别名
       String sql = "select id,username,password,phone_no phoneNo,address,reg_date regDate from user where id = ?";
       User user = queryForDifference(User.class, sql, 1);
       System.out.println(user);
  }

   public <T>T queryForDifference(Class<T> clazz, String sql, Object ...args) {
       Connection conn = null;
       PreparedStatement ps = null;
       ResultSet rs = null;
       try {
           //1.获取链接
           conn = JdbcUtils.getConnection();

           //2.预编译sql语句,获取preparedStatement实例
           ps = conn.prepareStatement(sql);
           //3.填充占位符
           for (int i = 0; i < args.length; i++) {
               ps.setObject(i+1,args[i]);
          }
           //4.执行,获取结果集
           rs = ps.executeQuery();
           //4.1获取结果集元数据
           ResultSetMetaData rsmd = rs.getMetaData();
           //4.2通过元数据获取列数
           int columnCount = rsmd.getColumnCount();
           //4.3判断是否有数据
           if (rs.next()){
               //4.3.1实例化一个对象,反射
               T t = clazz.getDeclaredConstructor().newInstance();
               //4.3.2处理结果集一行数据的每一列
               for (int i = 0; i < columnCount; i++) {
                   //获取列值
                   Object columnValue = rs.getObject(i + 1);
                   //获取列的别名
                   String columnName = rsmd.getColumnLabel(i+1);
                   //给对象指定的属性赋值为columnValue
                   Field field = clazz.getDeclaredField(columnName);
                   field.setAccessible(true);
                   field.set(t,columnValue);
              }
               return t;
          }
      } catch (Exception e) {
           e.printStackTrace();
      } finally {
           //5.关闭资源
           JdbcUtils.closeResource(conn,ps,rs);
      }
       return null;
  }
}

对于不同表的多个对象的通用查询操作

package com.why.connection;

import com.sun.source.tree.ParenthesizedTree;
import com.why.entity.User;
import com.why.utils.JdbcUtils;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.sql.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Properties;

/**
* @Description TODO 实现对数据表的增删改查操作
* @Author why
* @Date 2020/10/10 16:23
* Version 1.0
**/
public class PreparedStatementUpdateTest {

   @Test
   public void testQuery() throws Exception {
       //记得写别名
       String sql = "select id,username,password,phone_no phoneNo,address,reg_date regDate from user where id < ?";
       List<User> users = queryForDifference(User.class, sql, 3);
       users.forEach(System.out::println);
  }

   public <T> List<T> queryForDifference(Class<T> clazz, String sql, Object ...args) throws Exception {
       Connection conn = null;
       PreparedStatement ps = null;
       ResultSet rs = null;
       try {
           //1.获取数据库连接对象
           conn = JdbcUtils.getConnection();
           //2.预编译sql语句,得到preparedStatement实例
           ps = conn.prepareStatement(sql);
           //3.填充占位符
           for (int i = 0; i < args.length; i++) {
               ps.setObject(i+1,args[i]);
          }
           //4.执行返回结果集
           rs = ps.executeQuery();
           //4.1获取结果集元数据
           ResultSetMetaData rsmd = rs.getMetaData();
           //4.2获取元数据列数
           int columnCount = rsmd.getColumnCount();
           //创建集合
           List<T> list = new ArrayList<>();
           //4.3判断是否有数据
           while (rs.next()){
               //4.3.1实例化对象
               T t = clazz.getDeclaredConstructor().newInstance();
               //处理结果集一行数据的每一列,给T对象赋值
               for (int i = 0; i < columnCount; i++) {
                   //获取列值
                   Object columnValue = rs.getObject(i + 1);
                   //获取列别名
                   String columnLabel = rsmd.getColumnLabel(i + 1);
                   //给指定对象赋值
                   Field field = t.getClass().getDeclaredField(columnLabel);
                   field.setAccessible(true);
                   field.set(t,columnValue);
              }
               list.add(t);
          }
           return list;
      } catch (Exception e) {
           e.printStackTrace();
      } finally {
           //5.关闭资源
           JdbcUtils.closeResource(conn,ps,rs);
      }

       return null;
  }
}

 

posted @ 2020-12-11 20:13  笔落惊风  阅读(377)  评论(0编辑  收藏  举报