【无标题】

PreparedStatement

SQL注入问题

SQL注入:用户输入的内容作为了SQL语句语法的一部分,改变了原有SQL真正的意义。 假设有登录案例SQL语句如下:

SELECT * FROM 用户表 WHERE NAME = 用户输入的用户名 AND PASSWORD = 用户输的密码;

此时,当用户输入正确的账号与密码后,查询到了信息则让用户登录。但是当用户输入的账号为XXX 密码为:XXX’ OR ‘a’=’a时,则真正执行的代码变为:

SELECT * FROM 用户表 WHERE NAME = ‘XXX’ AND PASSWORD =’ XXX’  OR ’a’=’a’;

此时,上述查询语句时永远可以查询出结果的。那么用户就直接登录成功了,显然我们不希望看到这样的结果,这便是SQL注入问题。 为此,我们使用PreparedStatement来解决对应的问题。

API详解:预处理对象

preparedStatement:预编译对象,是Statement对象的子类。

特点:

  • 性能高

  • 会把sql语句先编译

  • 能过滤掉用户输入的关键字。

PreparedStatement预处理对象,处理的每条sql语句中所有的实际参数,都必须使用占位符?替换。

String sql = "select * from user where username = ? and password = ?";

PreparedStatement使用,需要通过以下3步骤完成:

  1. PreparedStatement预处理对象代码:

// 获得预处理对象,需要提供已经使用占位符处理后的SQL语句
PreparedStatement psmt = conn.prepareStatement(sql)
  1. 设置实际参数

void setXxx(int index, Xxx xx) 将指定参数设置指定类型的值
    参数1:index 实际参数序列号,从1开始。
    参数2:xxx 实际参数值,xxx表示具体的类型。
例如:
setString(2, "1234") 把SQL语句中第2个位置的占位符?替换成实际参数 "1234"
  1. 执行SQL语句:

int executeUpdate(); --执行insert update delete语句.
ResultSet executeQuery(); --执行select语句.
boolean execute(); --执行select返回true 执行其他的语句返回false.

插入

@Test
public void demo01(){
    //添加:向分类表中添加数据
    Connection conn = null;
    PreparedStatement psmt = null;
    ResultSet rs = null;
    
    try {
        //1 获得连接
        conn = JdbcUtils.getConnection();
        //2 处理sql语句
        String sql = "insert into category(cname) values(? )";
        //3获得预处理对象
        psmt = conn.prepareStatement(sql);
        //4设置实际参数
        psmt.setString(1,"预处理");
        //5执行
        int r = psmt.executeUpdate();
        
        System.out.println(r);
        
    } catch (Exception e) {
        throw new RuntimeException(e);
    } finally{
        //6释放资源
        JdbcUtils.closeResource(conn, psmt, rs);
    }
}
​

更新

@Test
public void demo02(){
    //修改
    Connection conn = null;
    PreparedStatement psmt = null;
    ResultSet rs = null;
    
    try {
        conn = JdbcUtils.getConnection();
        
        //1 sql语句
        String sql = "update category set cname = ? where cid = ?";
        //2 获得预处理对象
        psmt = conn.prepareStatement(sql);
        //3设置实际参数
        psmt.setString(1, "测试数据");
        psmt.setInt(2, 4);
        //4执行
        int r = psmt.executeUpdate();
        System.out.println(r);
        
        
    } catch (Exception e) {
        throw new RuntimeException(e);
    } finally{
        JdbcUtils.closeResource(conn, psmt, rs);
    }   
}

通过id查询详情

@Test
public void demo05(){
    //通过id查询
    Connection conn = null;
    PreparedStatement psmt = null;
    ResultSet rs = null;
    
    try {
        conn = JdbcUtils.getConnection();
        
        String sql = "select * from category where cid = ?";
        psmt = conn.prepareStatement(sql);
        psmt.setInt(1, 2);
        rs = psmt.executeQuery();
        if(rs.next()){
            System.out.println("查询到");
        } else {
            System.out.println("查询不到");
        }
        
        
    } catch (Exception e) {
        throw new RuntimeException(e);
    } finally{
        JdbcUtils.closeResource(conn, psmt, rs);
    }
}

 使用连接池重写工具类

 连接池原理

连接池理解为存放多个连接的集合。

使用连接池技术的目的:解决建立数据库连接耗费资源和时间很多的问题,提高性能。

编写标准的数据源(规范)

Java为数据库连接池提供了公共的接口:javax.sql.DataSource,各个厂商需要让自己的连接池实现这个接口。这样应用程序可以方便的切换不同厂商的连接池!

常见的连接池:C3P0、DRUID。

 C3P0连接池

C3P0连接池工具类编写

C3P0开源免费的连接池!目前使用它的开源项目有:Spring、Hibernate等。使用C3P0连接池需要导入jar包,c3p0使用时还需要添加配置文件“c3p0-config.xml”

使用步骤

  1. 添加jar包

  2. 编写配置文件 c3p0-config.xml,放在src中(注:文件名一定不要写错)

  3. 编写工具类

  • 编写配置文件 c3p0-config.xml

 <c3p0-config>
   <!-- 使用默认的配置读取连接池对象 -->
   <default-config>
     <!--  连接参数 -->
     <property name="driverClass">com.mysql.jdbc.Driver</property>
     <property name="jdbcUrl">jdbc:mysql://localhost:3306/day03</property>
     <property name="user">root</property>
     <property name="password">root</property>
​
     <!-- 连接池参数 -->
     <property name="initialPoolSize">5</property>
     <property name="maxPoolSize">10</property>
     <property name="checkoutTimeout">2000</property>
     <property name="maxIdleTime">1000</property>
   </default-config>
 </c3p0-config>

c3p0连接池常用的配置参数:

参数说明
initialPoolSize初始连接数
maxPoolSize最大连接数
checkoutTimeout最大等待时间
maxIdleTime最大空闲回收时间

初始连接数:刚创建好连接池的时候准备的连接数量 最大连接数:连接池中最多可以放多少个连接 最大等待时间:连接池中没有连接时最长等待时间 最大空闲回收时间:连接池中的空闲连接多久没有使用就会回收

  • 编写C3P0工具类

package com.doit.utils;
​
import com.mchange.v2.c3p0.ComboPooledDataSource;
​
import javax.management.relation.RoleUnresolved;
import java.beans.PropertyVetoException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
​
/*
     javax.sql.DataSource  连接池接口
           方法
              Connection getConnection()
              只要使用连接池对象 调用getConnection方法 就是从连接池中 获取了连接对象
              要想获取连接 必须找到DataSource接口的实现类对象  C3P0实现类这个接口
              对应的实现类是ComboPooledDataSource ,我们只要创建这个类的对象
              调用getConnection方法 就 从连接池中 获取到了连接对象
​
​
​
 */
public class C3P0Utils {
​
    private static ComboPooledDataSource ds ;
​
    static{
​
        try{
             ds = new ComboPooledDataSource();
            //配置连接池的信息
            ds.setDriverClass("com.mysql.jdbc.Driver");
            ds.setJdbcUrl("jdbc:mysql://localhost:3306/day04");
            ds.setUser("root");
            ds.setPassword("root");
​
        }catch (Exception e){
            throw new RuntimeException(e);
        }
​
​
    }
​
    public static Connection getConnection() throws SQLException, PropertyVetoException {
​
        Connection con = ds.getConnection();
​
        return con;
​
    }
​
​
    public static void close(Connection con, Statement stat, ResultSet rs) {
        try {
            if (con != null)
                con.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
​
        try {
            if (stat != null)
                stat.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
​
        try {
            if (rs != null)
                rs.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
​
}
​

C3P0连接池工具类的使用

public class Demo {
    public static void main(String[] args) throws Exception {
        // 拿到连接
        Connection conn = JdbcUtils.getConnection();
​
        // 执行sql语句
        String sql = "INSERT INTO student VALUES (NULL, ?, ?, ?);";
        PreparedStatement pstmt = conn.prepareStatement(sql);
        pstmt.setString(1, "李四");
        pstmt.setInt(2, 30);
        pstmt.setDouble(3, 50);
        int i = pstmt.executeUpdate();
        System.out.println("影响的函数: " + i);
​
        // 关闭资源
        JdbcUtils.close(conn, pstmt);
    }
}

别董大二首·其一

【唐】高适

千里黄云白日曛,北风吹雁雪纷纷。

莫愁前路无知己,天下谁人不识君?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值