zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    与众不同 windows phone (50)
    与众不同 windows phone (49)
    重新想象 Windows 8.1 Store Apps (93)
    重新想象 Windows 8.1 Store Apps 系列文章索引
    重新想象 Windows 8.1 Store Apps (92)
    重新想象 Windows 8.1 Store Apps (91)
    重新想象 Windows 8.1 Store Apps (90)
    重新想象 Windows 8.1 Store Apps (89)
    重新想象 Windows 8.1 Store Apps (88)
    重新想象 Windows 8.1 Store Apps (87)
  • 原文地址:https://www.cnblogs.com/yif0118/p/12232721.html
Copyright © 2011-2022 走看看