文章目录
六:数据库连接池6.1 概念6.2 c3p06.3 Druid6.4 DBCP(Apache)6.5 DBUtils(快速创建对象,并以集合形式返回) 七、Spring JDBC _ JdbcTemplate0801更新:6.4 DBCP;6.5DBUtils
六:数据库连接池
6.1 概念
其实就是一个容器(集合),存放数据库连接的容器。
当系统初始化好后,容器被创建,容器中会申请一些连接对象,当用户来访问数据库时,从容器中获取连接对象,用户访问完之后,会将连接对象归还为容器。
好处:
节约资源用户访问高效实现: 标准接口:DataSource
javax.sql包下 方法: 获取连接:getConnection()
归还连接:如果连接对象Connection
是从连接池获取的,那么调用Connection.close()
,则不会再关闭连接了,而是归还连接。 一般我们不去实现它,由数据库厂商来实现。 c3p0:数据库连接池技术Druid:德鲁伊数据路连接池技术,由阿里巴巴提供
6.2 c3p0
步骤:
导入jar包(两个),c3p0-0.9.5.2.jar
和mchange-commons-java-0.2.12.jar
(mysql的驱动jar包也要导入,不要忘记,mysql-connector-java-5.1.37-bin.jar
),所以一共是3个
定义配置文件:
名称:c3p0.properties
orc3p0-config.xml
<c3p0-config><!-- 使用默认的配置读取连接池对象 --><default-config><!-- 连接参数 --><property name="driverClass">com.mysql.jdbc.Driver</property><property name="jdbcUrl">jdbc:mysql://localhost:3306/db4</property><property name="user">root</property><property name="password">root</property><!-- 连接池参数 --><!-- 初始化申请的连接数量 --><property name="initialPoolSize">5</property><!-- 最大的连接数量 --><property name="maxPoolSize">10</property><!-- 超时时间 --><property name="checkoutTimeout">3000</property></default-config><named-config name="otherc3p0"> <!-- 连接参数 --><property name="driverClass">com.mysql.jdbc.Driver</property><property name="jdbcUrl">jdbc:mysql://localhost:3306/day25</property><property name="user">root</property><property name="password">root</property><!-- 连接池参数 --><property name="initialPoolSize">5</property><property name="maxPoolSize">8</property><property name="checkoutTimeout">1000</property></named-config></c3p0-config>
路径:直接将文件放在src
目录下
创建核心对象:数据库连接对象ComboPooledDataSource
获取连接:getConnection()
package day03_JDBC;import com.mchange.boPooledDataSource;import javax.sql.DataSource;import java.sql.Connection;import java.sql.SQLException;/*** C3P0演示*/public class C3P0Demo01 {public static void main(String[] args) throws SQLException {//1. 创建数据库连接池对象DataSource ds = new ComboPooledDataSource();//2. 获取连接对象Connection conn = ds.getConnection();//3. 打印连接对象System.out.println(conn);}}
6.3 Druid
数据库连接池实现技术,由阿里巴巴提供
步骤
导入jar包:druid-1.0.9.jar
定义配置文件:
是properties
形式
driverClassName=com.mysql.jdbc.Driverurl=jdbc:mysql://127.0.0.1:3306/db3username=rootpassword=root# 初始化连接数量initialSize=5# 最大连接数maxActive=10# 最长等待时间maxWait=3000
可以叫任意名称,可以放在任意的目录下
加载配置文件。Properties
获取数据库连接池对象:通过工厂类来获取DruidDataSourceFctory
获取连接:getConnection()
package day03_JDBC;import com.alibaba.druid.pool.DruidDataSourceFactory;import javax.sql.DataSource;import java.io.IOException;import java.io.InputStream;import java.sql.Connection;import java.util.Properties;public class DruidDemo01 {public static void main(String[] args) throws Exception {//1. 导入jar包//2. 定义配置文件//3. 加载配置文件Properties pro = new Properties();InputStream rs = DruidDemo01.class.getClassLoader().getResourceAsStream("druid.properties");pro.load(rs);//4. 获取连接池对象DataSource ds = DruidDataSourceFactory.createDataSource(pro);//5. 获取连接Connection conn = ds.getConnection();System.out.println(conn);}}
定义工具类
定义一个类 JDBCUtils提供静态代码块加载配置文件,初始化连接池对象提供方法 获取连接方法:通过数据库连接池获取连接释放资源获取连接池的方法
package day03_JDBC.JDBCUtils;import com.alibaba.druid.pool.DruidDataSourceFactory;import javax.sql.DataSource;import java.io.IOException;import java.sql.Connection;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;import java.util.Properties;public class JDBCUtils_Druid {//1. 定义成员变量private static DataSource ds;static{try {//1. 加载配置文件Properties pro = new Properties();pro.load(JDBCUtils_Druid.class.getClassLoader().getResourceAsStream("druid.properties"));//2. 获取Datasourceds = 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 e) {e.printStackTrace();}}if(stmt != null){try {stmt.close();} catch (SQLException e) {e.printStackTrace();}}if(conn != null){try {conn.close();//归还连接} catch (SQLException e) {e.printStackTrace();}}}/*** 获取连接池的方法*/public static DataSource getDataSource(){return ds;}}
练习代码:一个添加操作
package day03_JDBC;import day03_JDBC.JDBCUtils.JDBCUtils_Druid;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.SQLException;/*** 使用新的工具类*/public class DruidDemo02 {public static void main(String[] args) {/*完成一个添加操作:给accout添加一条记录*/Connection conn = null;PreparedStatement pstmt = null;try {//1. 获取连接conn = JDBCUtils_Druid.getConnection();//2. 定义sqlString sql = "insert into account values(null,?,?)";//3. 获取pstmt对象pstmt = conn.prepareStatement(sql);//4. 给?赋值pstmt.setString(1,"王五");pstmt.setDouble(2, 3000);//5. 执行sqlint count = pstmt.executeUpdate();//执行成功的返回System.out.println(count);} catch (SQLException e) {e.printStackTrace();} finally {//6. 释放资源JDBCUtils_Druid.close(pstmt, conn);}}}
6.4 DBCP(Apache)
需要导入两个jar
包,分别为:commons-dbcp-1.4.jar
和commons-pool-1.5.6.jar
DBCP的连接池DataSource
的实现类为BasicDataSource
,可以使用此实现类或使用工厂方法BasicDataSourceFactory.createDataSource(pro)
实现,但需要引入配置文件,具体实现方式如下:
package day0801;import java.io.FileInputStream;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.util.Properties;import javax.sql.DataSource;import mons.dbcp.BasicDataSource;import mons.dbcp.BasicDataSourceFactory;public class DBCPDemo01 {public static void main(String[] args) throws Exception{Properties pro = new Properties();pro.load(new FileInputStream(DBCPDemo01.class.getResource("dbcp.properties").getFile()));DataSource ds = BasicDataSourceFactory.createDataSource(pro);Connection conn = ds.getConnection();String sql = "select * from account";PreparedStatement pstmt = conn.prepareStatement(sql);ResultSet rs = pstmt.executeQuery();while(rs.next()) {int id = rs.getInt(1);String name = rs.getString(2);int balance = rs.getInt(3);System.out.println(id + "---" + name + "---" + balance);}}}
6.5 DBUtils(快速创建对象,并以集合形式返回)
核心类:QueryRunner
使用:QueryRunner qr = new QueryRunner(连接池对象ds);
List<Person> list = qr.query(sql, new BeanListHandler<Person>(Person.class));
返回集合
核心参数:ResultSetHandler
(接口),创建对象所必须
注意事项: 实体类构造器必须是无参构造器,且不能省略
实际操作:
配置文件(C3P0
为例)
<?xml version="1.0" encoding="UTF-8"?><c3p0-config><default-config><property name="driverClass">com.mysql.jdbc.Driver</property><property name="jdbcUrl">jdbc:mysql://localhost/db2</property><property name="user">root</property><property name="password">root</property><property name="initialPoolSize">5</property><property name="maxPoolSize">20</property></default-config><named-config name="oracle"> <property name="driverClass">com.mysql.jdbc.Driver</property><property name="jdbcUrl">jdbc:mysql:///web_07</property><property name="user">root</property><property name="password">123</property></named-config></c3p0-config>
主程序
package day0801;import java.sql.SQLException;import java.util.ArrayList;import java.util.List;import mons.dbutils.QueryRunner;import mons.dbutils.handlers.BeanListHandler;import com.mchange.boPooledDataSource;public class DBuUtilsDemo {public static void main(String[] args) throws Exception {List<Person> persons = findAll();for(Person p : persons) {System.out.println(p);}}//1. 创建查询的方法,返回存Person的Listpublic static List<Person> findAll() throws Exception {ComboPooledDataSource ds = new ComboPooledDataSource();QueryRunner qr = new QueryRunner(ds);String sql = "select * from emp";List<Person> list = qr.query(sql, new BeanListHandler<Person>(Person.class));return list;}}
实体类
package day0801;import java.util.Date;public class Person {private int id;private String name;private String gender;private double salary;private Date join_date;private int dept_id;public Person() {//无参构造器十分重要,必须是无参构造器}public int getId() {return id;}public void setId(int 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 int getDept_id() {return dept_id;}public void setDept_id(int dept_id) {this.dept_id = dept_id;}@Overridepublic String toString() {return "Person [id=" + id + ", name=" + name + ", gender=" + gender + ", salary=" + salary + ", join_date="+ join_date + ", dept_id=" + dept_id + "]";}}
七、Spring JDBC _ JdbcTemplate
Spring框架对JDBC的简单封装。提供了JdbcTemplate
对象,简化JDBC的开发步骤 导入jar包(5个),并且依赖数据库连接池的jar包和驱动包。创建JDBCTemplate对象。依赖于数据源DataSource
JdbcTemplate template = new JdbcTemplate(ds);
调用JDBCTemplate的方法来完成CRUD的操作。update()
:执行DML语句。增删改语句queryForMap()
:查询结果,将结果集封装为map
集合,将列名作为key
,将值作为value
,将这条记录封装为一个Map
集合。 注意:这个方法查询的结果集长度只能是1queryForList()
:查询结果封装为list
集合。 将每一条记录封装为一个Map
集合,再将Map
集合装在到List
集合query()
:查询结果,将结果封装为JavaBean
对象。query
的参数:RowMapper 一般使用BeanPropertyRowMapper实现类。可以完成数据到JavaBean的自动封装new BeanPropertyRowMapper<Emp>(Emp.class)
queryForObject
:查询结果,将结果封装为对象。 一般用于聚合函数的查询。package day03_JDBC;import day03_JDBC.JDBCUtils.JDBCUtils_Druid;import org.springframework.jdbc.core.JdbcTemplate;public class JDBCTemplateDemo01 {public static void main(String[] args) {//1. 导入jar包//2. 创建JDBCJdbcTemplate template = new JdbcTemplate(JDBCUtils_Druid.getDataSource());//3. 调用方法String sql = "update account set balance = 500 where id = ?";int count = template.update(sql, 3);System.out.println(count);}}
练习: 需求 修改1号数据的salary 为10000添加一条记录删除刚才添加的记录查询id为1的记录,将其封装为Map
集合查询所有记录,将其封装为List
查询所有记录,将其封装为Emp
对象的List
查询总记录数
package day03_JDBC;import day03_JDBC.JDBCUtils.JDBCUtils_Druid;import org.junit.Test;import org.springframework.jdbc.core.BeanPropertyRowMapper;import org.springframework.jdbc.core.JdbcTemplate;import org.springframework.jdbc.core.RowMapper;import java.sql.Date;import java.sql.ResultSet;import java.sql.SQLException;import java.util.List;import java.util.Map;public class JdbcTemplateDemo02 {//Junit单元测试,可以让方法独立执行/*修改1号数据的salary 为10000*/private JdbcTemplate template = new JdbcTemplate(JDBCUtils_Druid.getDataSource());@Testpublic void test01(){JdbcTemplate template = new JdbcTemplate(JDBCUtils_Druid.getDataSource());String sql = "update emp set salary = 10000 where id = ?";int count = template.update(sql, 1);System.out.println(count);}/*添加一条记录*/@Testpublic void test02(){String sql = "insert into emp(id,name,dept_id) values(?,?,?)";int count = template.update(sql, 6, "文泽路", 1);System.out.println(count);}/*删除刚才添加的记录*/@Testpublic void test03(){String sql = "delete from emp where id = ?";int count = template.update(sql, 6);System.out.println(count);}/*查询id为1的记录,将其封装为`Map`集合注意:这个方法查询的结果集长度只能是1*/@Testpublic void test04(){String sql = "select * from emp where id = ? ";Map<String, Object> map = template.queryForMap(sql, 1);System.out.println(map);}/*查询所有记录,将其封装为`List*/@Testpublic void test05(){String sql = "select * from emp";List<Map<String, Object>> list = template.queryForList(sql);for(Map<String, Object> map : list){System.out.println(map);}}/*查询所有记录,将其封装为`Emp`对象的`List`*/@Testpublic void test06(){String sql = "select * from emp";List<Emp> list = template.query(sql, new RowMapper<Emp>() {@Overridepublic Emp mapRow(ResultSet resultSet, int i) throws SQLException {int id = resultSet.getInt("id");String name = resultSet.getString("name");String gender = resultSet.getString("gender");double salary = resultSet.getDouble("salary");Date join_date = resultSet.getDate("join_date");int dept_id = resultSet.getInt("dept_id");Emp emp = new Emp(id, name, gender, salary, join_date, dept_id);return emp;}});for(Emp emp : list){System.out.println(emp);}}/*简化操作!!!*/@Testpublic void test06_1(){String sql = "select * from emp";List<Emp> list = template.query(sql, new BeanPropertyRowMapper<Emp>(Emp.class));for(Emp emp : list){System.out.println(emp);}}/*查询总记录数*/@Testpublic void test07(){String sql = "select count(id) from emp";Long total = template.queryForObject(sql, Long.class);System.out.println(total);}}