今日内容
-
数据库连接池
-
Spring JDBC : JDBC Template
数据库连接池
-
概念:其实就是一个容器(集合),存放数据库连接的容器。
当系统初始化好后,容器被创建,容器中会申请一些连接对象,当用户来访问数据库时,从容器中获取连接对象,用户访问完之后,会将连接对象归还给容器。-
好处:
1)节约资源
2)用户访问高效 -
实现:
标准接口:DataSource javax.sql
包下的
(1). 方法:
* 获取连接:getConnection()
* 归还连接:Connection.close()。如果连接对象Connection是从连接池中获取的,那么调用Connection.close()方法,则不会再关闭连接了。而是归还连接一般我们不去实现它,有数据库厂商来实现
(1). C3P0:数据库连接池技术
(2). Druid:数据库连接池实现技术,由阿里巴巴提供的 -
C3P0:数据库连接池技术
步骤:
(1). 导入jar包 (两个) c3p0-0.9.5.2.jar
mchange-commons-java-0.2.12.jar ,
* 不要忘记导入数据库驱动jar包
(2) 定义配置文件:
* 名称: c3p0.properties 或者 c3p0-config.xml
* 路径:直接将文件放在src目录下即可。
-
c3p0-config.xml
//初始化申请的连接对象数量
<property name = "initialPoolSize">5</property>
//最大连接数
<property name = "maxPoolSize">10</property>
//超时时间
<property name = "checkoutTimcout">3000</property>
(3). 创建核心对象 数据库连接池对象 ComboPooledDataSource
(4). 获取连接: getConnection
* 代码:
//1.创建数据库连接池对象
DataSource ds = NEW ComboPooledDataSource();
//2. 获取连接对象
CONNECTION conn = ds.getConnection();
5. Druid:数据库连接池实现技术,由阿里巴巴提供的
一. 步骤:
(1) 导入jar包 druid-1.0.9.jar
(2) 定义配置文件:是properties形式的
* 可以叫任意名称,可以放在任意目录下,需要给路径加载
(3) 加载配置文件。Properties
(4)获取数据库连接池对象:通过工厂类来获取 DruidDataSourceFactory
(5)获取连接:getConnection
代码:
public class DruidDemo{
public static void main(String[] args){
//1.导入jar 包
//2.定义配置文件
//3.加载配置文件(pro为配置文件对象)
Properties pro = NEW Properties();
InputStream IS = DruidDemo.class.getClassLoader().getResourceAsStream("druid.properties");//返回字节输入流
pro.load(IS);//加载文件,同时文件中的属性加载进pro对象中
//4.获取连接池对象(连接池对象需要jar包来实现)
DataSource ds = DruidDataSourceFactory.createDataSource(pro);
//5.获取连接
CONNECTION conn = ds.getConnection();
}
二. 定义工具类
1. 定义一个类 JDBCUtils
2. 提供静态代码块加载配置文件,初始化连接池对象
3. 提供方法
(1) 获取连接方法:通过数据库连接池获取连接
(2)释放资源
(3) 获取连接池的方法
- 代码:
public class JDBCUtils {
//1.定义成员变量 DataSource
private static DataSource ds ;
static{
try {
//1.加载配置文件
Properties pro = NEW Properties();
pro.load(JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties"));
//2.获取DataSource
ds = DruidDataSourceFactory.createDataSource(pro);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
// 方法一:获取连接池
public static DataSource getDataSource(){
RETURN ds;
}
// 方法二: 获取连接对象
public static CONNECTION getConnection() throws SQLEXCEPTION {
RETURN ds.getConnection();
}
// 方法三 :释放资源
public static void CLOSE(Statement stmt,CONNECTION conn){
/* if(stmt != null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn != null){
try {
conn.close();//归还连接
} catch (SQLException e) {
e.printStackTrace();
}
}*/
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();
}
}
}
}
Spring JDBCTemplate
- Spring框架对JDBC的简单封装。提供了一个JDBCTemplate对象简化JDBC的开发
将繁杂的数组库操作,简化成短短几句代码- 步骤:
-
导入jar包
-
创建JdbcTemplate对象。依赖于数据源DataSource(数据库连接池)
* JdbcTemplate template = NEW JdbcTemplate(ds);// ds 就是数据库连接池对象 -
调用JdbcTemplate的方法来完成CRUD的操作
*UPDATE():
执行DML语句。增、删、改语句
*queryForMap()
:查询结果将结果集封装为map集合,将列名作为key,将值作为value 将这条记录封装为一个map集合
* 注意:这个方法查询的结果集长度只能是1
*queryForList()
:查询结果将结果集封装为list集合
* 注意:将每一条记录封装为一个Map集合,再将Map集合装载到List集合中
一、将手动封装和自动封装的区别(封装从数据库查询的数据成map 和 list 集合)
QUERY()
:查询结果,将结果封装为JavaBean对象
参数:RowMapper
(是接口)
一般我们使用BeanPropertyRowMapper
实现类。可以完成数据到JavaBean的自动封装
NEW BeanPropertyRowMapper<类型>(类型.class)
二、封装成数据类型类
queryForObject
:查询结果,将结果封装为对象
* 一般用于聚合函数的查询
- 练习:
* 需求:
1) 修改1号数据的 salary 为 10000
2) 添加一条记录
3) 删除刚才添加的记录
4)查询id为1的记录,将其封装为Map集合
5)查询所有记录,将其封装为List
6)查询所有记录,将其封装为Emp对象的List集合
7)查询总记录数
- 代码:
IMPORT cn.itcast.domain.Emp;
IMPORT cn.itcast.utils.JDBCUtils;
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 JdbcTemplateDemo2 {
//Junit单元测试,可以让方法独立执行
//1. 获取JDBCTemplate对象
private JdbcTemplate template = NEW JdbcTemplate(JDBCUtils.getDataSource());
/**
* 1. 修改1号数据的 salary 为 10000
*/
@Test
public void test1(){
//2. 定义sql
STRING SQL = "update emp set salary = 10000 where id = 1001";
//3. 执行sql
INT COUNT = template.update(SQL);
System.out.println(COUNT);
}
/**
* 2. 添加一条记录
*/
@Test
public void test2(){
STRING SQL = "insert into emp(id,ename,dept_id) values(?,?,?)";
INT COUNT = template.update(SQL, 1015, "郭靖", 10);
System.out.println(COUNT);
}
/**
* 3.删除刚才添加的记录
*/
@Test
public void test3(){
STRING SQL = "delete from emp where id = ?";
INT COUNT = template.update(SQL, 1015);
System.out.println(COUNT);
}
/**
* 4.查询id为1001的记录,将其封装为Map集合
* 注意:这个方法查询的结果集长度只能是1
*/
@Test
public void test4(){
STRING SQL = "select * from emp where id = ? or id = ?";
Map<STRING, Object> map = template.queryForMap(SQL, 1001,1002);
System.out.println(map);
//{id=1001, ename=孙悟空, job_id=4, mgr=1004, joindate=2000-12-17, salary=10000.00, bonus=NULL, dept_id=20}
}
/**
* 5. 查询所有记录,将其封装为List
*/
@Test
public void test5(){
STRING SQL = "select * from emp";
LIST<Map<STRING, Object>> LIST = template.queryForList(SQL);
//遍历 list集合
FOR (Map<STRING, Object> stringObjectMap : LIST) {
System.out.println(stringObjectMap);
}
}
一:手动封装
* 6. 查询所有记录,将其封装为Emp对象的List集合
Emp 是JavaBean 对象
@Test
public void test6(){
STRING SQL = "select * from emp";
LIST<Emp> LIST = template.query(SQL, NEW RowMapper<Emp>() {
// 隐式实现RowMapper接口, 自定义名叫RowMapper封装类型为JavaBean类型的类
@Override
//所有的查询接口被自动封装在 rs 对象中
public Emp mapRow(ResultSet rs, INT i) throws SQLEXCEPTION {
Emp emp = NEW Emp();
INT id = rs.getInt("id");
STRING ename = rs.getString("ename");
INT job_id = rs.getInt("job_id");
INT mgr = rs.getInt("mgr");
DATE joindate = rs.getDate("joindate");
DOUBLE salary = rs.getDouble("salary");
DOUBLE bonus = rs.getDouble("bonus");
INT dept_id = rs.getInt("dept_id");
emp.setId(id);
emp.setEname(ename);
emp.setJob_id(job_id);
emp.setMgr(mgr);
emp.setJoindate(joindate);
emp.setSalary(salary);
emp.setBonus(bonus);
emp.setDept_id(dept_id);
RETURN emp;
}
});
FOR (Emp emp : LIST) {
System.out.println(emp);
}
}
二:自动封装
* 6. 查询所有记录,将其封装为Emp对象的List集合
@Test
public void test6_2(){
STRING SQL = "select * from emp";
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 emp";
LONG total = template.queryForObject(SQL, Long.class);// 封装为long类型的对象(long类是个数据类型类)
System.out.println(total);
}
}