jdbc学习笔记02

数据库连接池

概念:

其实就是一个容器(集合),存放数据库连接的容器

  • 当系统初始化好后,容器被创建,容器会申请一些连接对象,当用户来访问数据库时,从容器中获取连接对象,用户访问完之后,会将连接对象归还给容器。

好处

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

实现:

  1. 标准接口:DataSource javax.sql包下的
    1. 方法;
      • 获取连接:getConnection()
      • 归还连接:Connection.close()。如果连接对象Connection是从连接池中获取的,那么调用Connection.close()方法,则不会关闭连接了,而是归还连接
  2. 一般我们不去实现它,由数据库厂商来实现
    1. C3P0:数据库连接池技术
    2. Druid:数据库连接池技术,由阿里巴巴提供的

C3P0:数据库连接池技术

  • 步骤:

    1. 导入jar包(三个) c3p0-0.9.5.5.jar, mchange-commons-java-0.2.19.jar

      • 不要忘记导入数据库jar包:mysql-connector-java-8.0.19.jar
    2. 定义配置文件:

      • 名称:c3p0.properties 或者 c3p0-config.xml
      • 路径:直接将文件放在src目录下即可

      示例:c3p0-config.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<c3p0-config>
<!--默认配置,无参数时使用该配置-->
<default-config>
<!--连接参数-->
<property name="driverClass">com.mysql.cj.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql:///learn?serverTimezone=Hongkong</property>
<property name="user">root</property>
<property name="password">4869</property>

<!--连接池参数-->
<!--初始化连接池中申请的连接数量-->
<property name="initialPoolSize">5</property>
<!--连接池中最大的的连接数量-->
<property name="maxPoolSize">10</property>
<!--超时时间:3s-->
<property name="checkoutTimeout">3000</property>

</default-config>

<!--自定义配置,传递参数为 otherc3p0 时使用该配置文件-->
<named-config name="otherc3p0">
<!--连接参数-->
<property name="driverClass">com.mysql.cj.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/learn?serverTimezone=UTC</property>
<property name="user">root</property>
<property name="password">4869</property>

<!--连接池参数-->
<property name="initialPoolSize">5</property>
<property name="maxPoolSize">8</property>
<property name="checkoutTimeout">1000</property>

</named-config>
</c3p0-config>
  1. 创建核心对象 数据库连接池对象 ComboPooledDataSource()

  2. 获取连接:getConnection()

  3. 代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public static void main(String[] args) throws SQLException {
//1. 创建数据库连接池对象
//DataSource ds = new ComboPooledDataSource();
DataSource ds = new ComboPooledDataSource("otherc3p0");

//2. 获取连接对象
for (int i = 1; i <= 11; i++) {
Connection conn = ds.getConnection();
//3. 输出
System.out.println(i + ":" + conn);
if(i == 5) //归还连接
conn.close();
}
}

Druid:数据库连接池技术,由阿里巴巴提供

  1. 步骤:

    1. 导入jar包 lib/druid-1.1.21.jar, lib/mysql-connector-java-8.0.19.jar

    2. 定义配置文件:

      • .properties形式的
      • 可以叫任意名称,可以放在任意目录下
    3. 加载配置文件:Properties

    4. 获取数据库连接池对象:通过工厂来获取 DruidDataSourceFactory()

    5. 获取连接:getConnection()

    6. 代码示例:

Druid.properties

1
2
3
4
5
6
7
8
9
10
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/learn?serverTimezone=Hongkong
username=root
password=4869
# 初始化连接数量
initialSize=5
# 最大连接数
maxActive=10
# 超时时间
maxWait=3000

.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class DruidTest {
public static void main(String[] args) throws Exception {
//1. 导入 jar 包
//2.导入配置文件
//3. 加载配置文件
Properties pro = new Properties();
//法1
//pro.load(new FileReader("src/druid.properties"));
//法2
InputStream inputStream = DruidTest.class.getClassLoader().getResourceAsStream("druid.properties");
pro.load(inputStream);
//4. 获取连接池对象
DataSource dataSource = DruidDataSourceFactory.createDataSource(pro);

//5. 获取连接
Connection connection = dataSource.getConnection();
System.out.println(connection);
}
}
  1. 定义工具类:

    1. 定义一个类 JDBCUtils

    2. 提供静态代码块加载配置文件,初始化连接池对象

      1. 获取连接方法:通过数据库连接池获取连接
      2. 释放资源
      3. 获取连接池的方法
    3. 代码示例:

JDBCUtils.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
/**
* Druid连接池的工具类
*/
public class JDBCUtils {
private static DataSource ds;

static {
try {
//1. 加载配置文件
Properties pro = new Properties();
pro.load(Objects.requireNonNull(JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties")));
//2. 获取DataSource
ds = DruidDataSourceFactory.createDataSource(pro);
} catch (Exception e) {
e.printStackTrace();
}
}

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

/**
* 归还连接
*
* @param statement
* @param connection
*/
public static void close(Statement statement, Connection connection) {
close(null, statement, connection);
}

/**
* 归还连接
*
* @param resultSet
* @param statement
* @param connection
*/
public static void close(ResultSet resultSet, Statement statement, Connection connection) {
try {
if (resultSet != null) {
resultSet.close();
}
if (statement != null) {
statement.close();
}
if (connection != null) {
connection.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}

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

.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
 public static void main(String[] args) {
Connection conn = null;
PreparedStatement pstmt = null;

try {
//1. 获取连接
conn = JDBCUtils.getConnection();
//2. 定义sql
String sql = "insert into user (id, username, sex) values(?, ?, ?)";
//3. 获取pstmt对象
pstmt = conn.prepareStatement(sql);
//4. 给 ? 赋值
pstmt.setInt(1, 50);
pstmt.setString(2,"老黄");
pstmt.setString(3, "男");
//5. 执行sql
int count = pstmt.executeUpdate();
System.out.println(count);

} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtils.close(pstmt, conn);
}
}

Spring JDBC : JDBC Template

  • Spring 框架对 JDBC 的简单封装。提供了一个JDBCTemplate对象简化JDBC的开发

  • 步骤:

    1. 导入jar包

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

      • JdbcTemplate template = new JdbcTemplate(ds);
    3. 调用JdbcTemplate的方法来完成CRUD的操作

      • update():执行DML语句。增、删、改语句
      • queryForMap():查询结果将结果封装为map集合:将列名作为key,将值作为value,将这条记录封装为一个map集合
        • 注意:这个方法查询的结果集长度只能是1,即只能有一条记录
      • queryForList():查询结果将结果封装为list集合
        • 注意:这个方法是将每一条记录封装为Map集合,再将Map集合装载到List集合中
    • query():查询结果将结果封装为JavaBean对象
      • query的参数:RowMapper
      • 一般我们使用BeanPropertyRowMapper实现类,可以完成数据到JavaBean的自动封装
        • new BeanPropertyRowMapper<类型>(类型.class)
      • queryForObject():查询结果将结果封装为基本数据类型的集合
        • 一般用于聚合函数的查询
    1. 代码示例:
1
2
3
4
5
6
7
8
9
10
public static void main(String[] args) {
//1. 导入jar包
//2. 创建JDBCTemplate对象
JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
//3. 调用方法
String sql = "update account set money = 1000 where id < ?";
int count = template.update(sql,3);
System.out.println(count);
//无需关心归还连接池的问题
}
  1. 代码示例 2(maven项目):

pom.xml(部分)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<dependencies>
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.21</version>
</dependency>

<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.19</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.3.RELEASE</version>
</dependency>


<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<scope>test</scope>
</dependency>

</dependencies>

Emp.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
package com.conv.domain;

import java.util.Date;

public class Emp {
// 最好写引用数据类型而不是基本数据类型,这样便于接收 null
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;

public Integer getId() {
return id;
}

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

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public Date getBirthday() {
return birthday;
}

public void setBirthday(Date birthday) {
this.birthday = birthday;
}

public String getSex() {
return sex;
}

public void setSex(String sex) {
this.sex = sex;
}

public String getAddress() {
return address;
}

public void setAddress(String address) {
this.address = address;
}

@Override
public String toString() {
return "Emp{" +
"id=" + id +
", username='" + username + '\'' +
", birthday=" + birthday +
", sex='" + sex + '\'' +
", address='" + address + '\'' +
'}';
}
}

AppTest.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
package com.conv;

import com.conv.domain.Emp;
import com.conv.utils.JDBCUtils;
import org.junit.Test;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;

import java.util.List;
import java.util.Map;

/**
* Unit test for simple App.
*/
public class AppTest {

private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());

/**
* 1. 修改数据
*/
@Test
public void Test1() {
String sql = "update user set sex = '女' where id = 41";
int count = template.update(sql);
System.out.println(count);
}

/**
* 2. 添加一条记录
*/
@Test
public void test2() {
String sql = "insert into user values(?,?,?,?,?)";
int count = template.update(sql, null, "梁非凡", "2019-12-30 23:59:59", "女", "湖北武汉");
System.out.println(count);
}

/**
* 3. 删除记录
*/
@Test
public void test3() {
String sql = "delete from user where username = ?";
int count = template.update(sql, "梁非凡");
System.out.println(count);
}

/**
* 4. 查询id为41的记录,并将其封装为Map集合
* 注意:这个方法查询的结果集长度只能是1
*/
@Test
public void test4() {
String sql = "select * from user where id = ?";
Map<String, Object> map = template.queryForMap(sql, 41);
System.out.println(map);
//{id=41, username=老王, birthday=2018-02-28 01:47:08.0, sex=女, address=北京}
}

/**
* 5. 查询所有记录,并将其封装为List集合
* 注意:这个方法是将每一条记录封装为Map集合,再将Map集合装载到List集合中
*/
@Test
public void test5() {
String sql = "select * from user";
List<Map<String, Object>> list = template.queryForList(sql);
for (Map<String, Object> stringObjectMap : list) {
System.out.println(stringObjectMap);
}
}

/**
* 6. 查询所有记录,并将其封装为Emp对象的List集合
* 注意:这个方法是将每一条记录封装为Map集合,再将Map集合装载到List集合中
*/
@Test
public void test6() {
String sql = "select * from user";
List<Emp> list = template.query(sql, new BeanPropertyRowMapper<Emp>(Emp.class));
for (Emp emp : list) {
System.out.println(emp);
}
}

/**
* 7. 查询总记录数
*/
@Test
public void test7(){
String sql = "select count(id) from user";
Long total = template.queryForObject(sql, Long.class);
System.out.println(total);
}
}

坚持原创技术分享,感谢您的支持和鼓励!