• JDBC(2) -- JDBC使用PreparedStatement完成CRUD


    1.   PreparedStatement预编译的语句对象

    预编译语句PreparedStatement 是java.sql中的一个接口,它是Statement的子接口。通过Statement对象执行SQL语句时,需要将SQL语句发送给DBMS,由 DBMS首先进行编译后再执行。预编译语句和Statement不同,在创建PreparedStatement 对象时就指定了SQL语句,该语句立即发送给DBMS进行编译。当该编译语句被执行时,DBMS直接运行编译后的SQL语句,而不需要像其他SQL语句那样首先将其编译,在执行

    2.PreparedStatement和Statement的区别

    在用法上不一样:

    ①    Statement是普通的语句对象,PreparedStatement是预编译的语句对象;

    Statement创建对象时不传入SQL,PreparedStatement创建对象是需要传入SQL;

    Statement在执行时需传入SQL,PreparedStatement执行时不需传入SQL。

    ②    Statement是拼接字符串效果,PreparedStatement不用拼接字符串;

    ③    PreparedStatement执行效率高于Statement;

    ④    PreparedStatement不是拼接字符串可以防止SQL注入问题;

    具体实现代码如下:

      1 package cn.yif.dao.impl;
      2 
      3 import cn.yif.domain.Student;
      4 import cn.yif.dao.IStudentDao;
      5 import cn.yif.domain.User;
      6 import cn.yif.utils.DBCPUtil;
      7 import cn.yif.utils.JDBCUtil;
      8 
      9 import java.sql.*;
     10 import java.util.ArrayList;
     11 import java.util.List;
     12 
     13 /**
     14  * @author Administrator
     15  * @create 2019-09-13-20:33
     16  */
     17 public class StudentDaoImpl implements IStudentDao {
     18     @Override
     19     public void insert(Student student) {
     20         Connection conn = null;
     21         PreparedStatement preStatement = null;
     22         try {
     23             //①加载(注册)驱动,这部分硬编码可以写也可以不写,jdbc4.0版本自带了
     24             //Class.forName("com.mysql.jdbc.Driver");
     25             //②获取连接
     26             //conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbctest01", "root", "admin");
     27             conn = JDBCUtil.getInstance().getConnection();
     28             //③预编译的语句对象:提前编译好SQL语句
     29             String insertSql = "insert into jdbcdemo02 (name, age) values (?, ?)";
     30             preStatement = conn.prepareStatement(insertSql);
     31             preStatement.setString(1, student.getName());
     32             preStatement.setInt(2, student.getAge());
     33             //④执行SQL语句:执行时无需代入SQL
     34             preStatement.execute();
     35         }catch (Exception ex){
     36             ex.printStackTrace();
     37         }finally {
     38             //⑤释放资源
     39             JDBCUtil.getInstance().close(null, preStatement, conn);
     40         }
     41     }
     42 
     43     @Override
     44     public void update(Student student) {
     45         Connection conn = null;
     46         PreparedStatement preStatement = null;
     47         try {
     48             //①加载(注册)驱动
     49             //Class.forName("com.mysql.jdbc.Driver");
     50             //②获取连接
     51             //conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbctest01", "root", "admin");
     52             conn = JDBCUtil.getInstance().getConnection();
     53             //③预编译的语句对象:提前编译好SQL语句
     54             String updateSql = "update jdbcdemo02 set name = ?, age = ? where id = ?";
     55             preStatement = conn.prepareStatement(updateSql);
     56             preStatement.setString(1, student.getName());
     57             preStatement.setInt(2, student.getAge());
     58             preStatement.setInt(3, student.getId());
     59             //④执行SQL语句:执行时无需代入SQL
     60             preStatement.execute();
     61         }catch (Exception ex){
     62             ex.printStackTrace();
     63         }finally {
     64             //⑤释放资源
     65             JDBCUtil.getInstance().close(null, preStatement, conn);
     66         }
     67     }
     68 
     69     @Override
     70     public void delete(Integer id) {
     71         Connection conn = null;
     72         PreparedStatement preStatement = null;
     73         try {
     74             //①加载(注册)驱动
     75             //Class.forName("com.mysql.jdbc.Driver");
     76             //②获取连接
     77             //conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbctest01", "root", "admin");
     78             conn = JDBCUtil.getInstance().getConnection();
     79             //③预编译的语句对象:提前编译好SQL语句
     80             String deleteSql = "delete from jdbcdemo02 where id = ?";
     81             preStatement = conn.prepareStatement(deleteSql);
     82             preStatement.setInt(1, id);
     83             //④执行SQL语句:执行时无需代入SQL
     84             preStatement.execute();
     85         }catch (Exception ex){
     86             ex.printStackTrace();
     87         }finally {
     88             //⑤释放资源
     89             JDBCUtil.getInstance().close(null, preStatement, conn);
     90         }
     91     }
     92 
     93     @Override
     94     public Student queryOne(Integer id) {
     95         Connection conn = null;
     96         PreparedStatement preStatement = null;
     97         ResultSet resultSet = null;
     98         Student student = null;
     99         try {
    100             //①加载(注册)驱动
    101             //Class.forName("com.mysql.jdbc.Driver");
    102             //②获取连接
    103             //conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbctest01", "root", "admin");
    104             conn = JDBCUtil.getInstance().getConnection();
    105             //③预编译的语句对象:提前编译好SQL语句
    106             String queryOneSql = "select * from jdbcdemo02 where id = ?";
    107             preStatement = conn.prepareStatement(queryOneSql);
    108             preStatement.setInt(1, id);
    109             //④执行SQL语句:执行时无需代入SQL
    110             resultSet = preStatement.executeQuery();
    111             if(resultSet.next())
    112             {
    113                 student = new Student();
    114                 student.setId(resultSet.getInt("id"));
    115                 student.setName(resultSet.getString("name"));
    116                 student.setAge(resultSet.getInt("age"));
    117             }
    118         }catch (Exception ex){
    119 
    120         }finally {
    121             //⑤释放资源
    122             JDBCUtil.getInstance().close(resultSet, preStatement, conn);
    123         }
    124         return student;
    125     }
    126 
    127     @Override
    128     public List<Student> queryAll() {
    129         Connection conn = null;
    130         PreparedStatement preStatement = null;
    131         ResultSet resultSet = null;
    132         Student student = null;
    133         List<Student> list = new ArrayList<Student>();
    134         try {
    135             //①加载(注册)驱动
    136             //Class.forName("com.mysql.jdbc.Driver");
    137             //②获取连接
    138             //conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbctest01", "root", "admin");
    139             conn = JDBCUtil.getInstance().getConnection();
    140             //③获取语句对象:用来执行SQL语句
    141             String queryAllSql = "select * from jdbcdemo02";
    142             preStatement = conn.prepareStatement(queryAllSql);
    143             //④执行SQL语句
    144             resultSet = preStatement.executeQuery(queryAllSql);
    145             while (resultSet.next())
    146             {
    147                 student = new Student();
    148                 student.setId(resultSet.getInt("id"));
    149                 student.setName(resultSet.getString("name"));
    150                 student.setAge(resultSet.getInt("age"));
    151                 list.add(student);
    152             }
    153         }catch (Exception ex){
    154             ex.printStackTrace();
    155         }finally {
    156             //⑤释放资源
    157             JDBCUtil.getInstance().close(resultSet, preStatement, conn);
    158         }
    159         return list;
    160     }

    3.登录方式实现

    这里采用简单模拟的方式,比较Statement与PreparedStatement的不同,以及SQL注入问题带来的影响:

    登录实现代码:

     1  @Override
     2     public User Login1_PreparedSt(String userName, String passWord) {
     3         Connection conn = null;
     4         PreparedStatement preStatement = null;
     5         ResultSet resultSet = null;
     6         User user = null;
     7         try {
     8             conn = JDBCUtil.getInstance().getConnection();
     9             String queryOneSql = "select * from jdbcdemo02_user where username = ? and password = ?";
    10             preStatement = conn.prepareStatement(queryOneSql);
    11             preStatement.setString(1, userName);
    12             preStatement.setString(2, passWord);
    13             resultSet = preStatement.executeQuery();
    14             if(resultSet.next())
    15             {
    16                 user = new User();
    17                 user.setId(resultSet.getInt("id"));
    18                 user.setUsername(resultSet.getString("username"));
    19                 user.setPassword(resultSet.getString("password"));
    20                 user.setAge(resultSet.getInt("age"));
    21                 user.setSex(resultSet.getInt("sex"));
    22             }
    23         }catch (Exception ex){
    24 
    25         }finally {
    26             //⑤释放资源
    27             JDBCUtil.getInstance().close(resultSet, preStatement, conn);
    28         }
    29         return user;
    30     }
    31 
    32     @Override
    33     public User Login2_PreparedSt(String userName) {
    34         Connection conn = null;
    35         PreparedStatement preStatement = null;
    36         ResultSet resultSet = null;
    37         User user = null;
    38         try {
    39             conn = JDBCUtil.getInstance().getConnection();
    40             String queryOneSql = "select * from jdbcdemo02_user where username = ?";
    41             preStatement = conn.prepareStatement(queryOneSql);
    42             preStatement.setString(1, userName);
    43             resultSet = preStatement.executeQuery();
    44             if(resultSet.next())
    45             {
    46                 user = new User();
    47                 user.setId(resultSet.getInt("id"));
    48                 user.setUsername(resultSet.getString("username"));
    49                 user.setPassword(resultSet.getString("password"));
    50                 user.setAge(resultSet.getInt("age"));
    51                 user.setSex(resultSet.getInt("sex"));
    52             }
    53         }catch (Exception ex){
    54 
    55         }finally {
    56             //⑤释放资源
    57             JDBCUtil.getInstance().close(resultSet, preStatement, conn);
    58         }
    59         return user;
    60     }
    61 
    62     @Override
    63     public User Login1_St(String userName, String passWord) {
    64         Connection conn = null;
    65         Statement statement = null;
    66         ResultSet resultSet = null;
    67         User user = null;
    68         try {
    69             conn = JDBCUtil.getInstance().getConnection();
    70             statement = conn.createStatement();
    71             String queryOneSql = "select * from jdbcdemo02_user where username = '"+userName+"' and password = '"+passWord+"'";
    72             resultSet = statement.executeQuery(queryOneSql);
    73             if(resultSet.next())
    74             {
    75                 user = new User();
    76                 user.setId(resultSet.getInt("id"));
    77                 user.setUsername(resultSet.getString("username"));
    78                 user.setPassword(resultSet.getString("password"));
    79                 user.setAge(resultSet.getInt("age"));
    80                 user.setSex(resultSet.getInt("sex"));
    81             }
    82         }catch (Exception ex){
    83 
    84         }finally {
    85             //⑤释放资源
    86             JDBCUtil.getInstance().close(resultSet, statement, conn);
    87         }
    88         return user;
    89     }

    后台使用SQL注入测试代码:

     1 @org.junit.Test
     2     public void Login1_PreparedSt() {
     3         User test1 = new User();
     4         //正常情况:未有SQL注入
     5         test1.setUsername("李华");
     6         test1.setPassword("123456");
     7         test1.setSex(2);
     8         //异常情况:有SQL注入
     9 //        test1.setUsername(" 'or 1=1 or' ");
    10 //        test1.setPassword("456");
    11 //        test1.setSex(2);
    12         IStudentDao userDao = new StudentDaoImpl();
    13         User user = userDao.Login1_PreparedSt(test1.getUsername(), test1.getPassword());
    14         if(user != null){
    15             System.out.println(String.format("恭喜%s登录成功!", user.getUsername()));
    16         }
    17         else {
    18             System.out.println("用户名或密码错误,登录失败!");
    19         }
    20     }
    21 
    22     @org.junit.Test
    23     public void Login2_PreparedSt() {
    24         User test1 = new User();
    25         test1.setUsername("李华");
    26         test1.setPassword("123456");
    27         test1.setSex(2);
    28         IStudentDao userDao = new StudentDaoImpl();
    29         User user = userDao.Login2_PreparedSt(test1.getUsername());
    30         if(user != null){
    31             if(user.getPassword().equals(test1.getPassword())){
    32                 System.out.println(String.format("恭喜%s登录成功!", user.getUsername()));
    33             }
    34             else {
    35                 System.out.println("密码错误,登录失败!");
    36             }
    37         }
    38         else {
    39             System.out.println("用户名错误,登录失败!");
    40         }
    41     }
    42 
    43     @org.junit.Test
    44     public void Login1_St() {
    45         User test1 = new User();
    46         //正常情况:未有SQL注入
    47         //test1.setUsername("李华");
    48         //test1.setPassword("123456");
    49         //test1.setSex(2);
    50         //异常情况:有SQL注入
    51         test1.setUsername(" 'or 1=1 or' ");
    52         //这里就是一条拼接的SQL -- select * from jdbcdemo02_user where username = ''or 1=1 or'' and password = 12344
    53         test1.setPassword("145");
    54         test1.setSex(2);
    55         IStudentDao userDao = new StudentDaoImpl();
    56         User user = userDao.Login1_St(test1.getUsername(), test1.getPassword());
    57         if(user != null){
    58             System.out.println(String.format("恭喜%s登录成功!", user.getUsername()));
    59         }
    60         else {
    61             System.out.println("用户名或密码错误,登录失败!");
    62         }
    63     }

    4.连接池

    4.1.连接池介绍

    连接池:简单地说,就是用来装连接对象的容器。

    背景:在高并发访问的网页上,每次请求都会创建一个connection,因此会非常浪费资源(内存),当同时1000人访问的时候,那就会占用很多资源,因此浪费很多时间并且导致容器操作系统崩溃。

    而连接池里面取connection则只需要从连接池里面拿到,不需要用户名和密码,用完之后,还回到连接池。

    在Java中,在Java中,连接池使用javax.sql.DataSource接口来表示连接池. 这里的DataSource就是连接池。连接池就是DataSource。DataSource是接口,和JDBC一样,是Sun公司开发的一套接口,需要各大厂商去实现:导入各大厂商对应的jar包;

    常用的DataSource的实现有下面两种方式:

      DBCP:  Spring推荐的(Spring框架已经集成DBCP)

      C3P0:  Hibernate推荐的(早期)(Hibernate框架已经集成C3P0)

    DBCP连接池配置文件

    dbcp.properties
    
    #连接字符串
    
    url=jdbc:mysql://localhost:3306/jdbcdemo
    
    #用户名
    
    username=root
    
    #密码
    
    password=admin
    
    #驱动的类路径
    
    driverClassName=com.mysql.jdbc.Driver
    
    #连接池启动时的初始值
    
    initialSize=1
    
    #连接池的最大值
    
    maxActive=50
    
    #连接池的最大空闲数
    
    maxIdle=20

    具体代码实现如下:

     1  @Override
     2     public Student queryOneByDBCP(Integer id) {
     3         Connection conn = null;
     4         PreparedStatement preStatement = null;
     5         ResultSet resultSet = null;
     6         Student student = null;
     7         try {
     8             //①加载(注册)驱动
     9             //Class.forName("com.mysql.jdbc.Driver");
    10             //②获取连接
    11             //conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbctest01", "root", "admin");
    12             conn = DBCPUtil.getInstance().getConnection();
    13             //③预编译的语句对象:提前编译好SQL语句
    14             String queryOneSql = "select * from jdbcdemo02 where id = ?";
    15             preStatement = conn.prepareStatement(queryOneSql);
    16             preStatement.setInt(1, id);
    17             //④执行SQL语句:执行时无需代入SQL
    18             resultSet = preStatement.executeQuery();
    19             if(resultSet.next())
    20             {
    21                 student = new Student();
    22                 student.setId(resultSet.getInt("id"));
    23                 student.setName(resultSet.getString("name"));
    24                 student.setAge(resultSet.getInt("age"));
    25             }
    26         }catch (Exception ex){
    27 
    28         }finally {
    29             //⑤释放资源
    30             DBCPUtil.getInstance().close(resultSet, preStatement, conn);
    31         }
    32         return student;
    33     }

    DBCPUtil.java文件:

     1 package cn.yif.utils;
     2 
     3 import org.apache.commons.dbcp.BasicDataSource;
     4 import org.apache.commons.dbcp.BasicDataSourceFactory;
     5 
     6 import javax.sql.DataSource;
     7 import java.io.IOException;
     8 import java.sql.*;
     9 import java.util.Properties;
    10 
    11 public class DBCPUtil {
    12     //使用静态static类构造单例模式
    13     private DBCPUtil(){ }
    14     //在静态代码块中创建instance的实例,这里使用static静态变量来保存
    15     private static DBCPUtil instance = null;
    16     //每次都要加载驱动,这里定义一个Properties,把资源文件里面的内容读到Properties里面
    17     private static Properties properties = null;
    18     //定义一个连接池对象
    19     //private static BasicDataSource ds = null;
    20     private static DataSource ds = null;
    21     //JDBCUtil类加载的时候,就加载注册驱动
    22     static {
    23         properties = new Properties();
    24         try {
    25             //当前线程类加载器加载获取properties文件
    26             properties.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("jdbc.properties"));
    27             //方式一:创建一个BasicDataSource对象来读取配置文件
    28 //            ds = new BasicDataSource();
    29 //            ds.setDriverClassName(properties.getProperty("driverClassName"));
    30 //            ds.setUrl(properties.getProperty("url"));
    31 //            ds.setUsername(properties.getProperty("username"));
    32 //            ds.setPassword(properties.getProperty("password"));
    33             //方式二:使用工厂DataSourceFactory来加载配置文件
    34             try {
    35                 ds = BasicDataSourceFactory.createDataSource(properties);
    36             } catch (Exception e) {
    37                 e.printStackTrace();
    38             }
    39         } catch (IOException e) {
    40             e.printStackTrace();
    41         }
    42         instance = new DBCPUtil();
    43     }
    44 
    45     public static DBCPUtil getInstance(){
    46         return instance;
    47     }
    48 
    49     //抽取获取连接Connection的方法
    50     public Connection getConnection() throws SQLException {
    51         //这里不再使用DriverManager,而应该使用BasicDataSource,从连接池中拿到这个连接
    52         return ds.getConnection();
    53     }
    54 
    55     //抽取JDBC关闭资源的close方法
    56     public void close(ResultSet resultSet, Statement statement, Connection conn){
    57         try {
    58             if(resultSet != null){
    59                 resultSet.close();
    60             }
    61         } catch (SQLException e) {
    62             e.printStackTrace();
    63         }
    64         try {
    65             if(statement != null){
    66                 statement.close();
    67             }
    68         } catch (SQLException e) {
    69             e.printStackTrace();
    70         }
    71         try {
    72             if(conn != null){
    73                 conn.close();
    74             }
    75         } catch (SQLException e) {
    76             e.printStackTrace();
    77         }
    78     }
    79 }
  • 相关阅读:
    9月9
    JavaScript语法(三)
    JavaScript语法(二)
    实现AJAX的基本步骤 。。转
    Ajax 完整教程。。转载
    Struts2中的Action类(解耦方式,耦合方式)
    web应用中使用JavaMail发送邮件 。。转载
    Struts2下的<result>中的type整理
    Struts2整理+课堂代码+注意事项
    一对多,多对一,注意事项总结
  • 原文地址:https://www.cnblogs.com/yif0118/p/12232721.html
Copyright © 2020-2023  润新知