JDBC连接池&JDBCTemplate(五)

数据库连接池

1. 概念:其实就是一个容器(集合)存放数据库连接(Connection对象) 的容器。
    当系统初始化好后,容器被创建,容器中会申请一些连接对象,当用户来访问数据库
    从容器中获取连接对象;用户访问完之后,会将连接对象归还给容器

2. 好处:
  1. 节约资源
  2. 用户访问高效

3.弊端
  第一次创建的时候会略微多消耗一点时间,第二次开始就会快很多

4. 实现:
  在Java中怎么表示数据库连接池?
    接口:DataSource 链接池又叫数据(Data)源(Source)
      1. 标准接口:DataSource java.sql包下的
        1. 方法:
          * 获取连接:getConnection()
          * 归还连接:Connection.close()。 如果连接对象Connection是从连接池获取的,那么调用Connection.close()方法,则 理解为:不是关闭连接。而是归还连接。

      2. 一般我们不去实现它,有数据库厂商来实现。有两种数据库连接池(C3P0、Druid)
        1. C3P0: 数据库连接池技术 //了解
          以前框架:ssh(spring、structs2、hibernate)

后来框架:ssm(spring、springMVC、mybatis)

        2. Druid:数据库连接池实现技术,由阿里巴巴(Made in China)提供的 (重点掌握)

  面试题:普通的连接(Connection对象)的close方法和数据库连接池中的连接(Connection对象)的close方法有什么区别?
    1.普通的连接:释放、销毁
    2.数据库连接池的连接:将连接归还到数据库连接池中 (动态代理)

5. C3P0:数据库连接池技术
 * 步骤:
   1. 导入jar包 (两个) c3p0-0.9.5.5.jar mchange-commons-java-0.2.19.jar ,
    外加配置文件(一个):c3p0-config.xml
     * 不要忘记导入数据库驱动jar包
   2. 定义配置文件:
     * 名称: c3p0.properties 或者 c3p0-config.xml (其他名字不行)
     * 路径: 直接将文件放在src目录下即可。 (其他目录也不行)
      如果使用C3P0连接池一定要注意放在src下,名字也是固定的 c3p0.properties 或者 c3p0-config.xml

   3. 创建核心对象 数据库连接池对象 ComboPooledDataSource
   4. 获取连接: getConnection

代码:

     //1.创建数据库连接池对象
       DataSource ds  = new ComboPooledDataSource();
    //2. 获取连接对象
       Connection conn = ds.getConnection();

    (1)为什么要导入jar包?
      因为JDK自带的jar包中没有吗,而我现在又要使用,这个时候就必须要导入jar包名

6.Druid:数据库连接池实现技术,由阿里巴巴提供的 //掌握
 1. 步骤:
   1. 导入jar包 druid-1.0.9.jar
   2. 定义配置文件:
     * 是properties形式的
     * 可以叫任意名称,可以放在任意目录下 //注意和C3p0对比
   3. 加载配置文件 使用方式: Properties
   4. 获取数据库连接池对象: 通过工厂类来获取 DruidDataSourceFactory
   5. 获取连接:getConnection

配置文件:
   代码:

# druid.properties文件的配置
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/db1
username=root
password=123456
# 初始化连接数量
initialSize=5
# 最大连接数
maxActive=10
# 最大超时时间
maxWait=3000

加载配置文件
   代码:

    Properties pro = new Properties();
	InputStream is = DruidDemo1.class.getClassLoader().getResourceAsStream("druid.properties");
	pro.load(is);
	//4.获取连接池对象
	DataSource ds = DruidDataSourceFactory.createDataSource(pro);
	//5.获取连接
	Connection conn = ds.getConnection();

 2. 定义工具类:
   1.定义一个类 JDBCutils
   2.提供静态代码块加载配置文件,初始化连接池对象
   3.提供方法
     1.获取连接方法:通过数据库连接池获取连接
     2.释放资源
     3.获取连接池的方法

代码实现:

 private  static DataSource ds;

    static {
        try {
            //1、创建Properties对象
            Properties pro = new Properties();
            //2、连接配置文件
            InputStream in = JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties");
            pro.load(in);

            //3、获取DataSource对象
            ds = DruidDataSourceFactory.createDataSource(pro);


        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /***
     *  获取连接
     */
    public static Connection getConnection() throws SQLException {
        return ds.getConnection();
    }

    /**
     *   释放连接
     */
    public static void close(Statement stmt,Connection conn) {

        close(null,stmt,conn);
    }

        public static void close(ResultSet rs,Statement stmt, Connection conn){

            if (rs != null) {
                try {
                    rs.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }

            if (stmt != null) {
                try {
                    stmt.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }

            if (conn != null) {
                try {
                    conn.close();     //归还连接
                } catch (SQLException throwables) {
                    throwables.printStackTrace();

            }
        }
    }

    /**
     * 获取连接池的方法
     */
    public static DataSource getDataSource(){
        return ds;
    }

}

工具类的测试:向account添加一条记录
代码实现:

/*
    使用新的工具类
 */
public class DruidDemo2 {
    public static void main(String[] args) throws Exception {
          /**
           * 完成添加朝操作,给account添加一条记录
           */

          Connection conn = null;
        PreparedStatement pstmt =null;
        try {
              //1、获取连接
              conn = JDBCUtils.getConnection();
              //2、定义sql
              String sql ="insert into account values (null ,?,?)";
              //3、获取sql对象
              pstmt = conn.prepareStatement(sql);
              //4、给 ? 赋值
              pstmt.setString(1,"王五");
              pstmt.setInt(2,3000);
              //5、执行sql
              int i = pstmt.executeUpdate();
              System.out.println(i);

          } catch (SQLException throwables) {
              throwables.printStackTrace();
          }finally {
                 //释放资源
                JDBCUtils.close(pstmt,conn);
          }
    }
}


Spring JDBCTemplate

三层结构:控制层(Controller层)、业务层(service层)、持久层(dao层)

JDBCTemplate是我们spring框架的一个组成部分,是持久层的一个实现方式

  1. Spring框架对JDBC的简单封装。 提供了一个JDBCTemplate对象简化JDBC的开发就是对JDBC的一个封装
    *步骤:

    1. 导入jar包

    2. 创建JdbcTemplate对象依赖于数据源DataSource

       JdbcTemplate template = new JdbcTemplate(ds);
       参数:ds是数据库连接池对象(druid连接池)
      
  2. 调用JdbcTemplate的方法来完成CRUD的操作
    * update():执行DML语句。增、删、改语句
    注意:使用前需要导入jar包 方法名不要写成excuteUpdate

    * queryForMap():查询结果将结果集封装为map集合,将列名作为key,将值作为value 将这条记录封装为一个map集合//了解
    	  * 注意:这个方法查询的结果集长度只能是1  (说白了就是一次性只能查询一条记录)
    * queryForList():查询结果将结果集封装为list集合  //了解
    	  * 注意:将每一条记录封装为一个Map集合,再将Map集合装载到List集合中
    * query():查询结果,将结果封装为JavaBean对象   //最重要
    	   前提:必须先有一个"标准的"JavaBean对象
    		因为我们传入的字节码文件对象,底层使用反射的方式创建对象,使用反射的调用set方法进行赋值
    	* query的参数:RowMapper
    		* 一般我们使用BeanPropertyRowMapper实现类。可以完成数据到JavaBean的自动封装
    		* new BeanPropertyRowMapper<类型>(类型.class)
    * queryForObject:查询结果,将结果封装为对象  //熟悉
    		特点:查询的结果需要是单行单列的
    	* 一般用于聚合函数的查询(比如:查询总数)
    

    4.JDBCTemplate快速入门

代码实现:

public class Template01 {
    public static void main(String[] args) {
        //1、导入jar包
        //2、创建JDBCTemplate对象
        JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
        //3、调用方法
        String sql = "update account set balance = 5000 where id = ?";
        int update = template.update(sql,3);
        System.out.println(update);

       /**
		 *	短短几行足以。       
         *     JDBCTemplate: 
         *          不需要再申请连接了
         *          不需要再释放资源了
         *          JdbcTemplate自己内部解决了
         *
         *          只关心:如何定义sql语句、执行、处理
         */

    }
}

1、练习
需求:

  1. 修改1号数据的 salary 为 1000
  2. 添加一条记录
  3. 删除刚才添加的记录
  4. 查询 id 为1的记录,将其封装为Map集合
  5. 查询所有记录,将其封装为List
  6. 查询所有记录,将其封装为Emp对象的List集合
  7. 查询总的记录数

Emp代码的实现:

	public class Emp {
    private  Integer     id ;
    private  String  name;
    private  String  gender;
    private  Double  salary;
    private  Date join_date;
    private  Integer     dept_id;


    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public Double getSalary() {
        return salary;
    }

    public void setSalary(Double salary) {
        this.salary = salary;
    }

    public Date getJoin_date() {
        return join_date;
    }

    public void setJoin_date(Date join_date) {
        this.join_date = join_date;
    }

    public Integer getDept_id() {
        return dept_id;
    }

    public void setDept_id(Integer dept_id) {
        this.dept_id = dept_id;
    }

    @Override
    public String toString() {
        return "Emp{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", gender='" + gender + '\'' +
                ", salary=" + salary +
                ", join_date=" + join_date +
                ", dept_id=" + dept_id +
                '}';
    }
}

练习代码:

public class Template02 {

    //每一个@Test都要写一次如下代码,所以直接提升作用域,使其template的作用域为成员变量
    private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());

    /**
     * 1、修改1号数据的 salary 为 1000
     */
    @Test
    public void test1() {
        String sql1 = "update emp00 set salary = ? where id = ?";
        int i = template.update(sql1,1000,1);
        System.out.println(i);
    }

    /**
     * 2、添加一条记录
     */
    @Test
    public void tset02() {
        String sql = "insert into emp00(id,name,gender) values (?,?,?)";
        int i = template.update(sql,6,"沙悟净","男");
        System.out.println(i);
    }

    /**
     * 3、删除刚才添加的记录
     */
    @Test
    public void test03() {
        String sql = "delete from emp00 where id in (?,?)";
        int update = template.update(sql, 6, 7);
        System.out.println(update);
    }

    /**
     * 4、查询 id 为1的记录,将其封装为Map集合
     * queryForMap方法的代码实现
     *  注意:这个方法查询的结果集长度只能是 :1  (说白了就是一次性只能查询一条记录)
     */
    @Test
    public void test04() {
        String sql = "select * from emp00 where id =?";
        Map<String, Object> map = template.queryForMap(sql, 1);

        System.out.println(map);
        //{id=1, name=孙悟空, gender=男, salary=1000.0, join_date=2013-02-24, dept_id=1}
    }

    /**
     * 5、查询所有记录,将其封装为List
     * queryForList方法的代码实现
     * 将每一条记录封装为一个Map集合,再将Map集合装载到List集合中  (说白了就是重复多次test04)
     */
    @Test
    public void test05() {
        String sql = "select * from emp00";
        List<Map<String, Object>> list = template.queryForList(sql);

        //遍历 使得输出结果换行。
        for (Map<String, Object> map : list) {
            System.out.println(list);
        }


    }

   /**
    *  6、查询所有记录,将其封装为Emp对象(JavaBean对象)的List集合
    *  和package domain下的Emp 组队
    */
    @Test
    public void test06() {
        String sql = "select * from emp00 ";
        List<Emp> list = template.query(sql, new RowMapper<Emp>() {

            @Override
            public Emp mapRow(ResultSet rs, int i) throws SQLException {
                Emp emp = new Emp();

                int id = rs.getInt("id");
                String name = rs.getString("name");
                String gender = rs.getString("gender");
                double salary = rs.getDouble("salary");
                Date join_date = rs.getDate("join_date");
                int dept_id = rs.getInt("dept_id");

                emp.setId(id);
                emp.setName(name);
                emp.setGender(gender);
                emp.setSalary(salary);
                emp.setJoin_date(join_date);
                emp.setDept_id(dept_id);


                return emp;
            }
        });
        for (Emp emp : list) {
            System.out.println(emp);
        }
    }

    /**
     *  6、查询所有记录,将其封装为Emp对象(JavaBean对象)的List集合
     *  简化上述代码
     */
    @Test
    public void test07() {
        String sql = "select * from emp00 ";
        List<Emp> list = template.query(sql, new BeanPropertyRowMapper<Emp>(Emp.class));

        for (Emp emp : list) {
            System.out.println(emp);
        }

    }

    /**
     * 7、查询总的记录数
     */
    @Test
    public void test08() {
        String sql = "select count(*) from emp00 ";
        Long total = template.queryForObject(sql, Long.class);

        System.out.println(total);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值