java day30——JDBC连接池

JDBC连接池

连接池–存储连接

连接池是一种常用的技术,为什么需要连接池呢?这个需要从TCP说起。假如我们的服务器跟数据库没有部署在同一台机器,那么,服务器每次查询数据库都要先建立连接,一般都是TCP链接,建立连接就需要3次握手了,假设后台服务跟数据库的单程的访问时间需要10ms,那么光是建立连接就花了30ms,并且TCP还有慢启动的机制,实际上一次查询可能还不止1次TCP来回,查询效率就会大大降低。
在这里插入图片描述

好处

  1. 在连接池中的连接, 在连接池初始化时就已经创建好
    在使用连接的时候, 就可以快速获得连接对象
  2. 连接使用完成后, 可以将连接归还给连接池, 让连接重复使用

JDBC连接池规范

JDBC提供的连接池规范 DataSource

市面常见3种连接池

  1. Apache - dbcp
  2. c3p0
  3. alibaba - druid

c3p0连接池

  1. 导入jar包
  2. 编写配置文件 c3p0-config.xml/c3p0.properties
    位置: 必须在类路径的根目录中 -> src
  3. 创建连接池对象 ComboPooledDataSource
		ComboPooledDataSource dataSource = new ComboPooledDataSource();
        // 使用配置文件 c3p0-config.xml 来指定连接池的参数/属性配置
        // 在使用ComboPooledDataSource无参构造器创建这个连接池对象时, 会自动去读取c3p0-config.xml文件内容
        // 读取完c3p0-config.xml 后, 使用的是default-config里的配置信息

        // 有参构造器, 传入一个name, 使用的就是named-config="otherc3p0"
        //DataSource dataSource = new ComboPooledDataSource("otherc3p0");

        Connection conn = dataSource.getConnection();
        System.out.println(conn);

druid连接池

  1. 导入jar包
  2. 编写配置文件
    位置和名字都随意
  3. 通过工厂创建连接池对象
    DruidDataSourceFactory.createDataSource(Properties)
		// 创建一个属性集 Properties
        Properties pros = new Properties();
        pros.load(Demo01.class.getResourceAsStream("druid.properties"));
        // Druid连接池提供了一个获得DataSource的工厂类
        DataSource dataSource = DruidDataSourceFactory.createDataSource(pros);
        Connection conn = dataSource.getConnection();
        System.out.println(conn);
public void test05SelectAll() throws Exception {
        String sql = "select * from emp";
        Connection conn = DruidUtils.getConnection();
        PreparedStatement stmt = conn.prepareStatement(sql);

        ResultSet rs = stmt.executeQuery();
        List<Emp> list = new ArrayList<>();
        while (rs.next()) {
            // 对象的封装很繁琐
            Emp emp = new Emp();
            emp.setEmpno(rs.getInt("empno"));
            emp.setEname(rs.getString("ename"));
            emp.setSal(rs.getDouble("sal"));
            emp.setJob(rs.getString("job"));
            emp.setComm(rs.getDouble("comm"));
            emp.setHiredate(rs.getDate("hiredate"));
            System.out.println(emp);
            list.add(emp);
        }
        System.out.println(list.size());
    }

DruidUtils工具类

DataSource数据源是一个实现了datasource接口的类,它实现了连接和连接池的功能

public class DruidUtils {
    private static DataSource dataSource;
    static {
        Properties pro = new Properties();
        try {
            pro.load(DruidUtils.class.getResourceAsStream("druid.properties"));
            dataSource = DruidDataSourceFactory.createDataSource(pro);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static DataSource getDataSource() {
        return dataSource;
    }
    public static Connection getConnection() {
        try {
            return dataSource.getConnection();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return null;
    }

连接池关闭

  • 通过连接池获得的连接关闭后, 连接对象返回给连接池, 并且引用设置为null。重新createStatement报错NullPointerException
  • 通过JDBC获得的连接关闭后, 连接对象还在, 但是状态是"已关闭", 不能再使用。重新createStatement报错ConnectionIsClosedException

JdbcTemplate

Spring框架 简化操作,冗余代码
不需要释放资源,自动执行

API

update(sql)——DML

	JdbcTemplate template = new JdbcTemplate(DruidUtils.getDataSource());
    @Test
    public void insertTest()  {
        // 执行DML的方法
        String sql = "insert into emp(empno,ename,job,sal,comm,hiredate) values(?,?,?,?,?,?)";
        template.update(sql,8000,"jack","CLERK",800,0,"2020-08-14");
    }
    @Test
    public void updateTest()  {
        // 执行DML的方法
        String sql = "update emp set ename=?,sal=?,job=?,comm=?,hiredate=? where empno=?";
        template.update(sql,"jack james",800,"CLERK",100,"2020-08-14",8000);
    }
    @Test
    public void deleteTest()  {
        // 执行DML的方法
        String sql = "delete from emp where empno = ?";
        template.update(sql,8000);
    }

queryforMap(sql)——DQL

只能处理一条结果集,生成一个map,将列名作为key, 列中的数据作为value封装到map中
map -> JavaBean, 工具可以使用

public void findTest()  {
        // 执行DQL的方法
        String sql = "select * from emp where empno=?";
        Map<String, Object> map = template.queryForMap(sql, 7369);
        // {empno=7369, ename=SMITH, job=CLERK, mgr=7902, hiredate=1980-12-17, sal=800, comm=null, deptno=20}
        System.out.println(map);
    }

queryforList(sql)——DQL

将查询出来的结果集,每一行封装为一个map, 再将这个map封装到list中

public void findTest1()  {
        // 执行DQL的方法
        String sql = "select * from emp";
        List<Map<String, Object>> list = template.queryForList(sql);
        list.stream().forEach(System.out::println);
    }
{empno=7369, ename=SMITH, job=CLERK, mgr=7902, hiredate=1980-12-17, sal=800, comm=null, deptno=20}
{empno=7499, ename=ALLEN, job=SALESMAN, mgr=7698, hiredate=1981-02-20, sal=1600, comm=300, deptno=30}
{empno=7521, ename=WARD, job=SALESMAN, mgr=7698, hiredate=1981-02-22, sal=1250, comm=500, deptno=30}  
......  

queryforObject(sql,class)——DQL

查询单列数据,并且将这一列数据, 转换成Class对应的类型对象

@Test
    public void findTest2()  {
        // 执行DQL的方法
        String sql = "select count(*) from emp";
        Long count = template.queryForObject(sql, Long.class);
        System.out.println(count);
    }
//14

query(sql, RowMapper)——DQL

提供的实现类BeanPropertyRomMapper(class)
使用前提:自定义实体类中属性名与表中字段名一致,否则都是null

   public void findTest3()  {
        // 执行DQL的方法
        String sql = "select * from emp";
        /**
         * RowMapper: 将结果集进行封装处理, 通过mapRow进行处理
         * query 得到的结果集ResultSet, 并且遍历结果集, 
         *  然后调用RowMapper中的mapRow方法对每一行结果进行封装处理
         */
        List<Emp> list = template.query(sql, new RowMapper<Emp>() {
            @Override
            /**
             * rs: 当前指向的那一行结果数据 rs.getString/Int..
             * i: 当前遍历的次数 - 了解
             * @return 将一行数据封装得到的对象
             */
            public Emp mapRow(ResultSet rs, int i) throws SQLException {
                Emp emp = new Emp();
                emp.setEmpno(rs.getInt("empno"));
//                emp.setEname(rs.getString("ename"));
                emp.setSal(rs.getDouble("sal"));
                emp.setJob(rs.getString("job"));
                emp.setComm(rs.getDouble("comm"));
                emp.setHiredate(rs.getDate("hiredate"));
                return emp;
            }
        });
        list.stream().forEach(System.out::println);
    }

简化

public void findTest4()  {
        // 执行DQL的方法
        String sql = "select * from emp";
        /**
         * RowMapper: 将结果集进行封装处理, 通过mapRow进行处理
         * query 得到的结果集ResultSet, 并且遍历结果集,
         *  然后调用RowMapper中的mapRow方法对每一行结果进行封装处理
         */
        List<Emp> list = template.query(sql, new BeanPropertyRowMapper<Emp>(Emp.class));
        list.stream().forEach(System.out::println);

MVC对于数据库的规范

M: Module - 业务模块 -> 操作数据库 DAO
Data Access Object
一张表emp, 对应一个实体类Emp, 再对应一个DAO-EmpDao
EmpDao中的方法, 就是操作数据库基本功能
再对应一个测试类, 测试Dao中的所有方法

public class EmpDao {
    // 后期 template 的创建 交给 Spring框架来做
    private JdbcTemplate template = new JdbcTemplate(DruidUtils.getDataSource());

    public void insertEmp(Emp emp) {
        // 执行DML的方法
        String sql = "insert into emp(empno,ename,job,sal,comm,hiredate) values(?,?,?,?,?,?)";
//        stmt.setDate(date);
        template.update(sql, emp.getEmpno(), emp.getEmpno(), emp.getJob(), emp.getSal(), emp.getComm(), emp.getHiredate());
    }

    public void updateEmp(Emp e) {
        // 执行DML的方法
        String sql = "update emp set ename=?,sal=?,job=?,comm=?,hiredate=? where empno=?";
        template.update(sql, e.getEname(), e.getSal(), e.getJob(), e.getComm(), e.getHiredate(), e.getEmpno());
    }

    public void deleteEmpById(int id) {
        // 执行DML的方法
        String sql = "delete from emp where empno = ?";
        template.update(sql, id);
    }

    public Emp findEmpById(int id) {
        // 执行DQL的方法
        String sql = "select * from emp where empno=?";
        List<Emp> list = template.query(sql, new BeanPropertyRowMapper<>(Emp.class), id);
        // 如果id查不出来, 结果会不会有影响
        if (list == null || list.size() == 0) {
            return null;
        }
        return list.get(0);
    }

    public List<Emp> findAllEmp() {
        // 执行DQL的方法
        String sql = "select * from emp";
        List<Emp> list = template.query(sql, new BeanPropertyRowMapper<>(Emp.class));
        return list;
    }

    public long findCount() {
        // 执行DQL的方法
        String sql = "select count(*) from emp";
        Long count = template.queryForObject(sql, Long.class);
        return count;
    }
测试
public class EmpDaoTest {
    // 测试EmpDao中的方法
    EmpDao ed = new EmpDao();
    @Test
    public void testFindById() {
        Emp emp = ed.findEmpById(736);
        System.out.println(emp);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值