jdbc、PreparedStatement预处理对象、连接池详解

jdbc

概念

操作数据库有三种方式

  1. cmd 操作
  2. 工具操作(sqlYog ,navicate )
  3. 通过java的方式操作 数据库

jdbc :java中用来操作数据库的 一种技术 Java DataBase Connectivity (java的数据库连接)

JDBC由来

在这里插入图片描述
jdbc的含义 :接口概念
1.jdbc的接口中api是什么
2.导入驱动jar包
在这里插入图片描述
在这里插入图片描述

jdbc快速入门

1.数据库

CREATE DATABASE  day06;
USE day06;
CREATE TABLE `user`(
 id INT PRIMARY KEY AUTO_INCREMENT,
 username VARCHAR(32) , 
 nickname VARCHAR(32) , 
 money INT
);

2.java代码

public static void main(String[] args) throws Exception {
        //1.注册驱动
        Class.forName("com.mysql.jdbc.Driver");
        //2.获得连接 Exception in thread "main" java.sql.SQLException: No database selected
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/day06", "root", "root");
        //3.获得语句执行者
        Statement statement = connection.createStatement();
        //4.执行语句
        String sql = " insert into user values(null , 'jack' , 'tom' , 1000)";
        int count = statement.executeUpdate(sql);
        //5.处理结果
        System.out.println(count);
        //6.释放资源
        statement.close();
        connection.close();
    }

PreparedStatement预处理对象

登录的问题

#登录
#select * from t_user where username = 'jack' and password = '1234' 
#select * from t_user where username = 'xxxx' and password = '1234' 

# 在数据库有三种注释  #  --  /**/
SELECT * FROM t_user WHERE username = '输入值' AND PASSWORD = '输入值'; 
#语法 or 条件只需要满足一个即可
# 1=1 恒等条件
SELECT * FROM t_user WHERE username='zhangsan' OR 1=1 ;

#当作用户名: ' or 1=1 -- 
SELECT * FROM t_user WHERE username = '' OR 1=1 -- ' AND PASSWORD = '输入值'; 
#当输入某些特殊值的时候 sql语句 发生了变化 源于 值和sql语句的语法组成新的内容 
# 该过程我们称之为sql注入问题

当输入某些特殊值的时候,这些特殊值和 原本的sql语句一结合,修改了原sql的具体含义,这个过程就是sql语句注入问题。
问题的产生:
在这里插入图片描述
问题的解决:
在这里插入图片描述
在jdbc中 有一个新的对象来解决sql注入的问题 , 此对象叫预处理(预先处理sql)对象

PreparedStatement好处

  1. 解决了sql注入的问题
  2. 提高了sql语句的可读性 , 通过问号的方式 替代 参数(变量)
  3. PreparedStatement 会引用着预编译后的结果。可以多次传入不同的参数给PreparedStatement 对象并执行。减少SQL编译次数(编译一次 多次使用),提高效率(减少编译次数-> 提高效率)。
    api部分:

PreparedStatement preparedStatement = connection.prepareStatement(sql); 获得预处理对象
executeUpdate() 增删改 此处不需要传入sql 因为 sql在之前就已经传入过了 (发送参数 通知数据库执行)
executeQuery() 查询 (发送参数 通知数据库执行)
execute() DDL 没用

/**
     * 增
     */
    @Test
    public void testInsert() throws Exception {
        //1.获得连接
        Connection connection = JDBCUtils.getConnection();
        //2.获得语句执行者  -> 预处理对象
        String sql = " INSERT INTO USER VALUES(NULL , ? , ? , ?) ";
        // 将sql语句发送给数据库进行预编译处理
        PreparedStatement preparedStatement = connection.prepareStatement(sql);  //发送sql

        //添加数据(还没有发送数据)  preparedStatement.set数据类型(sql语句中?所在的位置 ,  传入的值);
        preparedStatement.setString(1 , "张三");
        preparedStatement.setString(2 , "zhangsan");
        preparedStatement.setInt(3 , 1500);
        
        /**
         * preparedStatement
         *  executeUpdate() 增删改  此处不需要传入sql 因为 sql在之前就已经传入过了  (发送参数 通知数据库执行)
         *  executeQuery()  查询  (发送参数 通知数据库执行)
         *  execute() DDL 没用
         */
        //3.执行语句
        int count = preparedStatement.executeUpdate();
        
        //4.处理结果
        System.out.print(count);
        //5.释放资源
        JDBCUtils.close(preparedStatement , connection);
    }

/**
     * 修改
     */
    @Test
    public void testUpdate() throws Exception {
        //1.获得连接
        Connection connection = JDBCUtils.getConnection();
        //2.获得预处理对象-发送sql
        String sql = " update user set username =?,nickname = ? , money = ? where id = ? ";
        PreparedStatement pst = connection.prepareStatement(sql);
        //3.设置数据
        pst.setObject(1 , "李四");
        pst.setObject(2 , "lisi");
        pst.setObject(3 , 5000);
        pst.setObject(4 , 6);

        //4.执行sql  pst.executeUpdate(sql) 携带sql 使用的是statement对象(不支持问号的形式)
        int count = pst.executeUpdate();//不能够有sql

        //5.处理结果
        System.out.println(count);
        //6.释放资源
        JDBCUtils.close(pst , connection);
    }

    /**
     * 删除
     */
    @Test
    public void testDelete() throws Exception {
        //1.获得连接
        Connection connection = JDBCUtils.getConnection();
        //2.获得预处理对象
        String sql = " delete from user where id= ? ";
        PreparedStatement pst = connection.prepareStatement(sql);
        //3. 设置参数
        pst.setObject(1 , 6);
        //4.执行sql
        int count = pst.executeUpdate();
        //5.处理结果
        System.out.println(count);
        //6.释放资源
        JDBCUtils.close(pst, connection);
    }

连接池

定义:一个存放连接的位置
在这里插入图片描述

没有连接池遇到的问题

每一次操作CURD的时候 都要创建一个新的连接, 每一次使用完都关闭连接
创建之后 立马关闭-> 创建会消耗大量的资源, 销毁后 资源没了

连接池原理

操作连接池 : 核心动作

  1. 从池中获得连接
  2. 操作完以后归还连接
    在这里插入图片描述

常见连接池

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Druid连接池

在这里插入图片描述

/**
 * 方式一
 * 1.数据源是DataSource接口  别人提供jar(实现类)
 * 2.new实现类
 * 3.DataSource接口  提供获得连接的方法  getConnection()
 */
public class TestDemo1 {
    public static void main(String[] args) throws SQLException {
        //1.数据源的核心类 DruidDataSource
        DruidDataSource dataSource = new DruidDataSource();
        //1.1 基本四项设置: 连接任何数据库都需要基本四项
        //设置 set
        //1.1.1 驱动串  Driver 驱动   ClassName 全限定名称
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        //1.1.2 url连接地址
        dataSource.setUrl("jdbc:mysql:///day06");
        //1.1.3 用户名
        dataSource.setUsername("root");
        //1.1.4 密码
        dataSource.setPassword("root");
        //2.获得连接
        Connection connection = dataSource.getConnection();

        //是否有connection  NullPointerException 此时没有connection 因为别人提供的数据 至少也需要知道用户名...
        System.out.println(connection);
    }
}
/**
 * 方式二
 * 测试Druid 数据源使用
 */
public class TestDemo3 {
    public static void main(String[] args) throws Exception {
        //定义map
        Map map= new HashMap();

        //ctrl + F12   查看当前类 及其父类中的方法  setDriverClassName   setUrl ...
        //在java中 取名 去掉set首字母小写
       //dataSource.setDriverClassName("com.mysql.jdbc.Driver");  ->  driverClassName
        //dataSource.setUrl("jdbc:mysql:///day06");                ->  url
        //dataSource.setUsername("root");                          -> username
        //dataSource.setPassword("root");                          -> password
        //map用来放置参数 : 基本四项 或者其他设置
        map.put( "driverClassName" , "com.mysql.jdbc.Driver");
        map.put( "url" , "jdbc:mysql:///day06");
        map.put( "username" , "root");
        map.put( "password" , "root");
        //需要核心类  数据源工厂对象 :  也可以帮助我们生产 数据源对象
        DataSource dataSource = DruidDataSourceFactory.createDataSource(map);
        //打印连接
        System.out.println(dataSource.getConnection());
    }
}

简化操作:
在这里插入图片描述

public static void main(String[] args) throws Exception {
        //properties 必须有基本四项设置
        //ClassLoader() 类加载器 : 目的 加载文件 读取到内存中
        //getResourceAsStream("只从src下开始读取数据") 加载文件的方法
        //当前类名称.class.getClassLoader()
        //加载properties即可
        InputStream is = TestDemo4Important.class.getClassLoader().getResourceAsStream("db.properties");
        //加载流 获得properties对象
        Properties properties = new Properties();
        //加载流
        properties.load( is );
        //1.核心类
        DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
        //2.拿到连接
        System.out.println(dataSource.getConnection());
    }

db.properties文件

#db.properties 必须在src的根目录下
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql:///day06
username=root
password=root

#其他设置 查看底层
#初始化个数
initialSize=3
#最大个数
maxActive=10
#最大等待时间
maxWait=2000
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值