说到连接池,我们会先想起JDBC,传统JDBC的使用大概分为几个步骤:
- 注册驱动
- 创建连接对象
- 编写sql语句
- 创建执行sql语句的对象
- 执行sql语句
- 释放资源
其中,因为每次要调用的时候我们都要去创建连接对象,比较麻烦还有就是影响运行,内存啥的,所以再下一步就产生了许多连接池,我们要用的时候只要调用连接池里面的对象,用完再还回去即可,不用每次都创建,在java前期都会学到三种开源免费的数据库连接池,其中包括DBCP,c3p0,Druid等,今天我就是来记录一下还没学到mybatis之前使用的c3p0和Druid的使用(DBCP性能不是很好)。
我们也可以理解成如果使用传统JDBC,就像洗衣服,用手洗,比较麻烦
然后就有了洗衣机,也就是SpringJDBC,那么我们先来记录一下两个连接池的使用然后再来讲讲
c3p0:
- 使用步骤:
-
导入数据库连接池jar包, 也不要忘记导入数据库驱动包
c3p0-0.9.5.2.jar和mchange-commons-java-0.2.12.jar,mysql的驱动jar包 -
创建c3p0连接池对象
方式一:ComboPooledDataSources ds = new ComboPooledDataSources()方式二:ComboPooledDataSources ds = new ComboPooledDataSources(String configname)
-
使用配置文件,配置连接池的参数
- 如果没有配置文件,也可以使用c3p0数据库连接池
-
public class Demo1_c3p0_noconfig {
public static void main(String[] args) throws Exception{
//1.创建连接池对象
ComboPooledDataSource ds = new ComboPooledDataSource();
// DataSource ds2 = new ComboPooledDataSource();
//2.设置连接池的配置参数
ds.setDriverClass("com.mysql.jdbc.Driver");
ds.setJdbcUrl("jdbc:mysql:///test");
ds.setUser("root");
ds.setPassword("root666");
//下面三个看自己需要
ds.setMaxPoolSize(100);//最大连接个数:100
ds.setInitialPoolSize(6);//初始个数:6
ds.setAcquireIncrement(6);//每次新增6个
//3.获取连接对象
Connection con = ds.getConnection();
System.out.println(con);
con.close();
}
}
- 有配置文件的c3p0
在使用这个连接池之前我们要记得c3p0的配置文件的名称和位置有一定的要求:- 配置文件名必须是:c3p0.properties或c3p0-config.xml
- 配置文件的位置必须在src根目录下(使用的是类加载器)
配置文件:
<c3p0-config>
<!-- 使用默认的配置读取连接池对象 -->
<default-config>
<!-- 连接参数 -->
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/test</property>//test为要使用的database名
<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/test</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>
- 简单演示
public class Demo1_c3p0_withconfig {
public static void main(String[] args) throws Exception{
//1.创建连接池对象
// ComboPooledDataSource ds = new ComboPooledDataSource();//默认使用类加载器读取c3p0-config.xml
ComboPooledDataSource ds = new ComboPooledDataSource("otherc3p0");//默认使用类加载器读取c3p0-config.xml
//3.获取连接对象
for (int i = 1; i <=9; i++) {
Connection con = ds.getConnection();
System.out.println(i+":"+ con);
}
}
}
Druid数据库连接池
- 概述:Druid由阿里的“温少"开发的数据库连接池产品,后期他开发的json解析的工具fastJson
- 使用步骤
-
导入druid连接池的jar包,如果有需要,导入mysql的驱动包
jar的说明:druid-1.0.9.jar:需要导入项目的jar包(里面都是class文件,不能直接查看 ,导这个就行)
druid-1.0.9-javadoc.jar:jar包里面的api对应的帮助文档(html网页的形式)
druid-1.0.9-sources.jar: 源码(里面都是java文件,可以直接查看)
-
导入配置文件(druid.properties),对配置文件的位置以及名称没有任何要求
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql:///test
username=root
password=root
initialSize=5
maxActive=10
maxWait=3000
- 使用Druid数据库连接池对象
方式一:
DruidDataSource ds = new DruidDataSource();//需要手动设置连接池参数
方式二: (推荐方式二)
DruidDataSource ds = DruidDataSourceFactory.createDataSource(Properties properties);
public class Demo1_druid {
public static void main(String[] args)throws Exception {
//1.加载druid.properties配置文件
Properties properties = new Properties();
InputStream in = Demo1_druid.class.getClassLoader().getResourceAsStream("druid.properties");
properties.load(in);
//2.根据工厂对象,获取连接池
DataSource ds = DruidDataSourceFactory.createDataSource(properties);
Connection connection = ds.getConnection();
System.out.println(connection);
}
}
- 改造后的代码演示 增删改查
package lession4;
import org.junit.Test;
import utils.JDBCUtilsByDataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
public class Demo2_crud {
@Test
public void test1(){//演示查询一条记录,封装到对象
//1.注册驱动,获取连接
Connection con =null;
ResultSet rs = null;
PreparedStatement pstmt = null;
try{
con = JDBCUtilsByDataSource.getConnection();
//2.编写sql
String sql = "select * from tab_user where uid=?";
//3.执行sql的对象
pstmt = con.prepareStatement(sql);
//4.给?赋值
pstmt.setInt(1,100);
//5.执行sql,处理结果
rs = pstmt.executeQuery();
User user = null;
while (rs.next()){
int uid = rs.getInt("uid");
String name = rs.getString(2);
String psw = rs.getString("password");
user = new User(uid,name,psw);
}
System.out.println(user);
}catch (Exception e){
e.printStackTrace();
}finally {
JDBCUtilsByDataSource.closeSource(rs,pstmt,con);
}
}
@Test
public void test2(){//演示查询多条记录,封装到List集合里面
Connection con =null;
ResultSet rs = null;
PreparedStatement pstmt = null;
try{
con = JDBCUtilsByDataSource.getConnection();
//2.编写sql
String sql = "select * from tab_user";
//3.执行sql的对象
pstmt = con.prepareStatement(sql);
//4.给?赋值
//5.执行sql,处理结果
rs = pstmt.executeQuery();
List<User> list = new ArrayList<>();
User user = null;
while (rs.next()){
int uid = rs.getInt("uid");
String name = rs.getString(2);
String psw = rs.getString("password");
user = new User(uid,name,psw);
list.add(user);
}
System.out.println(list);
}catch (Exception e){
e.printStackTrace();
}finally {
JDBCUtilsByDataSource.closeSource(rs,pstmt,con);
}
}
@Test
public void test3(){//演示:修改一条记录,删除,添加
Connection con = null;
PreparedStatement pstmt=null;
try{
con = JDBCUtilsByDataSource.getConnection();
//String sql ="update tab_user set username=?,password=? where uid=?";
// String sql = "insert into tab_user(username,password,uid) values(?,?,?)";
String sql= "delete from tab_user where username=? and password=? and uid=?";
pstmt = con.prepareStatement(sql);
pstmt.setString(1,"杰克123");
pstmt.setString(2,"666");
pstmt.setInt(3,4);
pstmt.executeUpdate();
}catch (Exception e){
e.printStackTrace();
}finally {
JDBCUtilsByDataSource.closeSource(null,pstmt,con);
}
}
}
class User{
private Integer uid;
private String username;
private String password;
public User() {
}
public User(Integer uid, String username, String password) {
this.uid = uid;
this.username = username;
this.password = password;
}
public Integer getUid() {
return uid;
}
public void setUid(Integer uid) {
this.uid = uid;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User{" +
"uid=" + uid +
", username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
洗衣机Spring JDBC
-
概述:Spring Jdbc是对传统jdbc操作的封装,简化数据库操作。
-
操作步骤:
步骤一:导入spring jdbc的jar包
步骤二:创建spring jdbc提供的模板类对象步骤三:编写sql,执行sql,接收结果
-
常用方法
-
queryForObject(): 将一条记录封装成一个对象,或者将查询的表记录数封装成数字对象
比如:封装成一个bean对象
User user = jt.queryForObject(sql,new BeanPropertyRowMapper(User.class),100);
BeanPropertyRowMapper:将表中的字段和类的属性一一映射。
比如:封装一个数字对象
int num = jt.queryForObject(sql,Integer.class);
-
query(): 将多条记录封装成List
比如: List users = jt.query(sql, new BeanPropertyRowMapper(User.class));
-
queryForMap(): 将一条记录封装成一个Map(key是字段名称,value就是字段对应的值)
-
queryForList(); 将多条记录封装成一个List
-
update(DML的sql): 执行添加,删除,修改这些sql,返回影响的行数
-
-
Spring jdbc封装的缺点:
- 如果类型不一致,也能进行数据的封装(结果:封装的数据不正确)
- 如果查询不到数据,封装不进去,报异常。
(还有一种是DBUtils ,他的优点是:如果类型不一致,不会进行数据的封装,报异常
;如果查询不到数据,不封装,返回null 今天不讲先)
-
代码演示
package com.itheima.lession4;
import com.itheima.lession1.User;
import com.itheima.utils.JDBCUtilsByDataSource;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import java.util.List;
import java.util.Map;
/**
* 使用springjdbc封装一条记录到bean对象
*/
public class Demo1 {
public static void main(String[] args) throws Exception{
//5.查询多条记录,封装到List<Map>
//1.创建模板类对象(括号中间要得到一个连接池对象,所以我们可以在自己写的工具类中写一个获得对象的方法)
JdbcTemplate jt = new JdbcTemplate(JDBCUtilsByDataSource.getDs());
//2.编写sql,执行sql,接收结果
String sql = "select * from tab_user";
List<Map<String, Object>> maps = jt.queryForList(sql);
for (Map<String, Object> map : maps) {
System.out.println(map);
}
}
//4.查询一条记录:封装到Map
public static void test4() throws Exception {
//1.创建模板类对象
JdbcTemplate jt = new JdbcTemplate(JDBCUtilsByDataSource.getDs());
//2.编写sql,执行sql,接收结果
String sql = "select * from tab_user where uid=?";
Map<String, Object> map = jt.queryForMap(sql,1);
for (String key : map.keySet()) {
System.out.println(key+":"+ map.get(key));
}
}
//3.查询表中的记录数:int
public static void test3() throws Exception {
JdbcTemplate jt = new JdbcTemplate(JDBCUtilsByDataSource.getDs());
String sql ="select count(uid) from tab_user";// 表中的记录数:3
int num = jt.queryForObject(sql,Integer.class);
System.out.println(num);
}
//2.查询多条记录----》List<User>
public static void test2() throws Exception {
JdbcTemplate jt = new JdbcTemplate(JDBCUtilsByDataSource.getDs());
String sql = "select * from tab_user";
List<User> users = jt.query(sql, new BeanPropertyRowMapper<User>(User.class));
System.out.println(users);
}
//1.查询一条记录---》User
public static void test1() throws Exception {
//1.创建模板类对象
JdbcTemplate jt = new JdbcTemplate(JDBCUtilsByDataSource.getDs());
//2.编写sql,执行sql,接收结果
String sql = "select * from tab_user where uid=?";
User user = jt.queryForObject(sql,new BeanPropertyRowMapper<User>(User.class),100);
System.out.println(user);
}
}
- 因为配置和部分代码容易造成代码冗余,我们可以自己写一个工具类方便调用,再记录一下我在使用德鲁伊(Druid)的工具类(里面有加载配置文件方法,获得连接池对象方法,获得连接对象方法,释放资源方法)
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
public class JDBCUtilsByDataSource {
//1.DruidDatasource改造工具类
//1.加载配置文件:加载一次,静态代码块
private static DruidDataSource ds = null;
static {
try {
Properties properties = new Properties();
InputStream in = JDBCUtilsByDataSource.class.getClassLoader().getResourceAsStream("druid.properties");
properties.load(in);
ds = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
e.printStackTrace();
}
}
//3.提供一个方法:返回连接池对象
public static DataSource getDs() throws Exception{
return ds;
}
//2.提供一个方法,获取连接对象: 从连接池获取
public static Connection getConnection() throws Exception{
Connection con = ds.getConnection();
return con;
}
//3.提供一个释放资源的方法:
public static void closeSource(ResultSet rs , Statement stmt, Connection con){
//倒着关
if(rs!=null){
try {
rs.close();
} catch (SQLException e) {
rs = null;
}
}
if(stmt!=null){
try {
stmt.close();
} catch (SQLException e) {
stmt = null;
}
}
if(con!=null){
try {
con.close();
} catch (SQLException e) {
con = null;
}
}
}
}