数据库连接池
当我们每次使用数据库时都需要注册驱动,释放资源这类操作。而现在创建了一个数据库连接池,方便我们在使用时提高效率。
-
数据库连接池概念:
其实就是一个容器(集合),存放数据库连接的容器 -
好处:
①节约资源
②用户访问高效 -
实现:
- 标准接口:DataSource java.sql包下
- 方法:
① 获取连接:getConnection();
② 归还连接:Connection.close();如果连接对象是从连接池中获取的,那么调用close方法的时候就不会关闭连接,而是归还连接。
- 方法:
- 一般我们不去实现它,由数据厂商来实现
① C3P0:数据库连接池技术
② Druid:数据库连接池实现技术,由阿里巴巴提供的。
- 标准接口:DataSource java.sql包下
-
C3P0:数据池连接技术
- 步骤:
① 导入两个jar包,c3p0-0.9.5.2.jar mchange-commons-java-0.2.12.jar
注意不要忘记导入数据库驱动jar包像mysql-connector-java-5.1.44-bin.jar这样。
② 定义配置文件:
名称:c3p0.properties或者c3p0.config.xml
路径:直接将文件放在src目录
③ 创建核心对象 数据库连接池对象 ComboPooledDataSource
④ 获取连接:getConnection();
这儿获取链接的时候可以传参,也可以使用默认的。看一下c3p0-config-xml文件,这个文件里有多个连接对象,其中有一个是默认的。还有一些是有其他名字。在调用getConnection()方法时传递的参数就是数据池的名字。传哪一个调用的数据池就是哪一个。c3p0-config.xml文件,连接池
<?xml version="1.0" encoding="utf-8"?> <c3p0-config> <!--这个是默认配置,在不传参数的时候这个就是被连接的数据池 <default-config>--> <default-config> <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">这儿放的是密码</property> <!--初始化申请的连接数量--> <property name="initialPoolSize">5</property> <!--最大的连接数量,如果超出最大连接数量,会等待超时时间过后就报 错--> <property name="maxPoolSize">10</property> <!--超时时间:也就是说上面的参数也可能配置错误,如果配置错误就会等待三秒,然后报错超时连接--> <property name="checkoutTimeout">3000</property> </default-config> <!--这个是另一个数据库连接池,可以根据需要自己来配置参数--> <named-config name="otherc3p0"> </named-config> </c3p0-config>
- 步骤:
- Druid:数据库连接池实现技术,由阿里提供
- 步骤:
- 导入jar包
- 定义配置文件
① properties形式
② 可以叫任意名,可以放在任意目录下 - 加载配置文件。
- 获取数据库连接池对象:通过工厂来获取 DruidDataSourceFactory
- 获取连接:getConnection();
- 定义工具类
- 定义一个类:JDBCUtils
- 提供静态代码块加载配置文件,初始化连接池对象
- 提供方法
- 获取连接方法:通过数据库连接池获取连接
- 释放资源
- 获取连接池的方法
- 步骤:
抽取工具类
public class JDBCUtils {
//1.定义一个成员变量
private static DataSource ds;
static {
//1.加载配置文件
Properties pro = new Properties();
try {
pro.load(JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties"));
} catch (IOException e) {
e.printStackTrace();
}
//2.获取DataSource
try {
ds = DruidDataSourceFactory.createDataSource(pro);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取连接
* @return
* @throws SQLException
*/
public static Connection getConnection() throws SQLException {
return ds.getConnection();
}
/**
* 获取连接池方法
*/
public static DataSource getDataSource() {
return ds;
}
/**
* 释放资源
*/
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();
}
}
}
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 JDBC :JDBC Template
-
Spring框架对JDBC的简单封装。提供一个JDBCTemplate对象简化JDBC的开发
-
JDBCTemplate使我们简化了代码,只需要获取JDBCTemplate对象,写sql语句并执行就OK了
-
步骤:
- 导入jar包,五个都导入。
- 创建JDBCTemplate对象。依赖于数据源DataSource。
JDBCTemplate template = new JDBCTemplate(ds); - 调用JDBCTemplate的方法来完成CRUD的操作
- update(); 执行DML语句。增删改
- queryForMap(); 查询结果,将结果集封装为map集合
将列名作为key,值作为value来封装 - quaryForList(); 查询结果,将结果集封装为list集合
将每一个记录封装为Map,再将Map封装到List中 - query(); 查询结果,将结果封装为JavaBean对象
query的参数:RowMapper- 一般我们使用BeanPropertyRowMapper实现类。可以完成数据到JavaBean的自动封装
- new BeanPropertyRowMapper<类型>(类型.class));
- queryForObject; 查询结果将结果封装为对象
- 这个通常用来使用聚合函数的时候使用
注意:
- quaryForMap只能查询到一条记录,因为是封装为Map
- quaryForList可以查询到多条记录,当然一条记录也是可以查询的。
Template测试代码:
看代码前有这样一个表格:
还有这么一个Account类:Account类就不写出来了,简单说下,Account类中,都是id、name、balance的get和set方法,也重写了toString方法。
接下来是测试代码:
public class JDBCTemplateDemo2 {
private static JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
//1.将zhaoyi的balance改为8000
public static int first() {
String sql = "update account set balance = 80000 where name = ?";
int account = template.update(sql, "zhaoyi");
return account;
}
//2.将account表添加一条数据,id默认,name为zhengqi,balance为10000
public static int second() {
String sql = "insert into account values(null,'zhengqi',?)";
int count = template.update(sql, 10000);
return count;
}
//3.删除刚才添加的记录
public static int third() {
String sql = "delete from account where name = ?";
int account = template.update(sql, "zhengqi");
return account;
}
//4.查询id为1的记录,并将其封装为Map集合,注意:map只能用来查询单个数据。
public static Map fourth() {
String sql = "select * from account where id = ?";
Map<String, Object> stringObjectMap = template.queryForMap(sql, 1);
return stringObjectMap;
//查询结果 {id=1, name=zhaoyi, balance=80000}
}
//5.查询两条结果,使用List来查 会将列名作为key,值作为value来封装
public static List fivth() {
String sql = "select * from account where id = ? or id = ?";
List<Map<String, Object>> maps = template.queryForList(sql, 1, 2);
return maps;
//查询结果 [{id=1, name=zhaoyi, balance=80000}, {id=2, name=qianer, balance=2000}]
}
//6.查询所有记录,将其封装为Account对象的list集合
public static void sixth() {
String sql = "select * from account";
List<Account> list = template.query(sql, new RowMapper<Account>() {
@Override
public Account mapRow(ResultSet rs, int i) throws SQLException {
Account account = new Account();
int id = rs.getInt("id");
String name = rs.getString("name");
int balance = rs.getInt("balance");
account.setId(id);
account.setBalance(balance);
account.setName(name);
return account;
}
});
for (Account account : list) {
System.out.println(account);
}
}
//6.查询所有记录,将其封装为Account对象的list集合,一种简单方式,java提供的BeanPropertyRowMapper
public static void sixth_2() {
String sql = "select * from account";
List<Account> list = template.query(sql,new BeanPropertyRowMapper<Account>(Account.class));
for (Object o : list) {
System.out.println(o);
}
}
//7.查询总记录数
public static void seventh() {
String sql = "select count(id) from account";
Long aLong = template.queryForObject(sql, Long.class);
System.out.println(aLong);
}
}