JDBC数据库连接池

目录

一、什么是连接池

二、 连接池作用

三、连接池技术

 四、连接池的本质

五、 PreparedStatement和Statement的区别

 六、JDBC原生操作步骤

七、Druid连接池的操作步骤

1、提供druid.properties属性列表

2、封装工具类


一、什么是连接池

连接池:是一个容器,能够创建固定可重用数量连接对象,当着连接对象使用完毕,节省内存消耗归还到连接池中等待下一次利用!

二、 连接池作用

提供操作数据库性能
        当用户发送请求,需要连接数据库,频繁创建连接对象,还需要释放,这种情况耗时,消耗内存空间大
        启用连接池,用户发送请求,直接通过连接池操作里面已经创建好的连接对象,获取当前线程中的某个Connection,然后直接去操作数据库,使用完毕连接对象之后,从当线程中进行解绑,回到连接池中!

三、连接池技术

c3p0

dbcp

druid   德鲁伊--阿里开源项目

 四、连接池的本质

连接池本质就是需要实现sun公司提供的DataSource实现类(物理数据源代替 DriverManager)

五、 PreparedStatement和Statement的区别

1)是否能够防止sql注入
        PreparedStatement能够有效防止sql注入 (由于存在sql语句字符串拼接造成sql注入 不安全)
        Statement:执行静态sql语句,语句中就会在字符串拼接,造成sql注入(不推荐)
2)是否高效(提高执行效率)
        PreparedStatement 因为操作的参数化的sql语句,首先预编译---将sql语句存储在预编译对象中,根据占位符号类型进行赋值setXXX(int parameterIndex,实际参数(根据当前类型赋值))
直接通过预编译对执行sql语句,发送到数据库中进行操作   (执行sql效率高)

        Statement对象: 每次将拼接好的sql语句("硬编码") 进行执行    (执行sql效率低), 每次发送一个新的sql到数据库中进行执行
        executeUpdate(String sql) / executeQuery(String sql)

 六、JDBC原生操作步骤

1)导包 数据库的驱动jar包 mysql-connnector-java -版本号.jar
2)注册驱动
       Class.forName("com.mysql.cj.jdbc.Driver") ;
3)获取数据库的连接对象----目前---使用DataSource替代了DriverManager
       Connection conn = DriverManager.getConnection(
           "jdbc:msyql://localhost:3306/库名?参数....",
       "root",
       "123456") ;
4)准备sql语句 :参数化的sql
            String sql = "update account set name = ? where id = ?" ;//或者查询语句
5)获取预编译对象,并sql语句进行编译
            PreparedStatement  stmt = conn.prepareStatement(sql) ;
6)参数赋值 
            stmt.setString(1,"张三") ;
            stmt.setInt(2,2) ;
7)执行并释放资源    
   stmt.executeUpdate() ; //int结果       //ResultSet结果集   stmt.executeQuery();

   stmt.close(); 
   conn.close() ;

七、Druid连接池的操作步骤

1)导入连接池的第三方jar包 Druid-xxx(版本号).jar
2)编写连接池的配置文件(配置文件名称 任意即可 一般情况:jdbc.properties)
                    数据库的基本连接信息
                    driverClassName
                    url
                    username
                    password
                    initialSize 初始化数量
                    maxWait 最大等待时间
                    maxIdle:最大空闲数量
                    maxActive:最大激活数量
                    minIdle:最小空闲数量
3)通过DruidDataSourceFactory    工厂类---->创建DataSource(数据源)            
    静态方法:返回值就是DataSource
    public static DataSource createDataSource(Properties prop)
4)读取jdbc.properties配置文件,获取资源文件的输入流对象,将输入流对象加载到Properties属性列表中
5)创建数据源对象-----获取getConnection()

1、提供druid.properties属性列表

driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/ee_2106?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true
username=root
password=123456
initialSize=5
maxActive=10
maxWait=3000

2、封装工具类

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

/**
 * @author Kuke
 * @date 2021/8/18
 * 工具类---->DataSource----->获取数据库的连接对象 Connection以及后期管理事务
 *
 * 获取连接对象----静态方法
 * 关闭资源-----静态方法
 */
public class DruidJdbcUtils {

    //成员变量位置
    private  static DataSource ds ;
    //为了保证线程安全:每一线程使用自己的Connection (张三/李四)
    private static ThreadLocal<Connection>  t1 = new ThreadLocal<>() ; //提供线程的局部变量保存连接对象

    //构造方法私有化
    private DruidJdbcUtils(){}

    //静态代码块
    static{
        try {
            //读取数据库连接池的配置文件----->通过DruidDataSourceFactory工厂类创建DataSource
            //创建一个属性集合列表
            Properties prop = new Properties() ;
            //读取druid.properties
            InputStream inputStream = DruidJdbcUtils.class.getClassLoader().
                    getResourceAsStream("druid.properties");

            //将资源文件所在的输入流加载列表中
            prop.load(inputStream);
            ds = DruidDataSourceFactory.createDataSource(prop);
            //底层子实现类:DruidDataSource
            System.out.println("数据源获取成功");

        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //提供静态方法:单独获取数据源
    public static DataSource getDataSource(){
        return ds ;
    }

    //获取连接对象Connection静态功能

    public static Connection getConnection(){
        //从ThreadLocal中获取局部变量的副本:Connection
        /**
         *   public T get()  :从线程中获取局部变量的副本!
         */
        Connection conn =  null ;
        try {
            conn  =  t1.get();
            if(conn==null){
                //如果空,需要从数据库的连接池中获取连接对象
                 conn  = ds.getConnection();
                //获取到之后,每一线程执行自己的Connection
                //将获取到的连接对象 绑定到当前线程中
                t1.set(conn);
            }
            //如果不为空,说明ThreadLocal线程中已经存在Connection
            return conn ; //
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null ;

    }

    //关闭(释放资源)资源
    public static void close(ResultSet rs, Statement stmt,Connection conn)  {
        if(rs!=null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(stmt!=null){
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(conn!=null){
            try {
                conn.close();
                //关闭之后,归还到连接池中,需要从当前线程中解绑
                t1.remove();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    public static void close( Statement stmt,Connection conn)  {
        close(null,stmt,conn);
    }
    //事务管理代码 --- 加入

    public static void main(String[] args) {
        DataSource ds = DruidJdbcUtils.getDataSource();
        System.out.println(ds);
        Connection connection = DruidJdbcUtils.getConnection();
        System.out.println(connection);
    }
}

八、单元测试

1、什么是单元测试

     提供junit的内置注解@Test
@Before标记的方法
        在执行@Test单元测试方法之前先执行  (初始化的操作)
@After标记的方法
        在执行@Test单元测试方法之后执行(一般:资源的关闭) 

2、 junit中的@Test和@Before,@After分别什么意思

junit:提供一种单元测试  需要针对业务功能进行测试:Service  
service层:创建Service层对象  调用功能,传入实际参数----出现异常
首先应该判断:Dao层 是否能够正常操作数据----如果没有问题--->然后在service层中
        这些注解:junit提供的内置注解
@Test:提供单元测试方法(编写的测试用例,测试某个模块的功能(查询/添加/删除/修改))
@Before:在执行单元测试方法之前先执行 (一些相关初始化操作:读配置文件) 
@After:在执行单元测试方法之后执行(一些相关的释放资源的代码)

3、 本质

 注解本质---->接口
 
      1)编写一个类
      2)编写一个单元测试方法,不需要参数,也不需要返回值类型
               public void testFindAll()
      3)方法上加入注解@TestDemo
      4)编写测试代码-----  调用serivce 业务代码,获取数据

4、例计算器类

public class Calculator {

    public int sum(int a,int b){
        return a + b ;
    }

    public int sub(int a, int b){//减法
        return a + b ;
    }
}

 测试类

public class TestDemo {

    //测试查询功能
    @Test
    public void testFindAll(){

        //调用service
        AdminService adminService = new AdminServiceImpl() ;
        List<Admin> list = adminService.getAllAdmin();
        if(list!=null){
            for (Admin admin : list) {
                System.out.println(admin);
            }
        }
    }

    @Before
    public void init(){
        System.out.println("初始化操作...");
    }

    @After
    public void close(){
        System.out.println("释放相关的系统资源");
    }


    @Test
    public void testSub(){

        //创建计算器类
        Calculator calculator = new Calculator() ;
        int result = calculator.sub(10, 5);
        //断言进行测试
        //assertArrayEquals:测试数组相关(操作多个数据)
        //assertEquals(预期结果,功能性测试结果)
        Assert.assertEquals(5,result);

    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

彦登的登

动力来源

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值