数据库连接池的概念
数据库连接池目的在于让数据库的执行效率更加高效,它能够事先通过配置文件定义’池’中的连接数量(即配置文件的’最大连接数’).来达到’池’的效果.当有人要用时,则从中抽取一个连接数给其使用,而当使用完毕后,通过’close’释放资源的方法,将其’连接’返还给数据池.
而数据库连接池基于各种公司开发的’数据池实现Jar包’而不同,比较出名的是[C3p0数据池jar包]和[Druid数据池jar包].
C3p0属于多年前的老Jar包,目前属于老项目在用,且不支持Template操作
而Druid是阿里巴巴开发的Jar包,目前的主流是这个,因此当创建数据连接池时,应优先该数据池Jar包.
资源释放(归还连接)
不管是C3p0数据池,还是Druid数据池,同样需要用到’close()‘方法释放资源.
不过此处的’释放资源’,跟往常的概念不同.
因为是数据池,此处’close()'方法的效果,其实是将’SQL连接’归还到数据池种中,而并非真的关闭了资源.而归还资源,是为了节省连接数.
比如你规定了最大连接数是10,此时调用者从数据池中获取了一个’SQL连接对象’,那么将剩下9个,如果一直不执行’close()'方法,那么数据池中剩余的SQL连接数量将一直不再增加,直到数据池中的连接数被拿光.
而执行了’close()'方法则会将’SQL连接’归还给数据池.
C3P0数据池的应用
导包入C3p0的Jar包并应用
在模块下建立libs文件夹,导入Jar包(假若SQL驱动Jar包不存在,则一同导入)到该文件夹下,并应用
包分别为:
c3p0-0.9.5.2.jar
mchange-commons-java-0.2.12.jar 在这里插入图片描述
定义配置文件并应用
配置文件中存有数据库的连接参数,文件名存在固定规则.
文件类型分两种,可以是Properties类型的’ c3p0.properties’
也可以是xml类型的’c3p0-config.xml’
都需要放置在Src目录下才能生效.
此处以’c3p0-config.xml’举例,其配置文件内容为:
<c3p0-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">root</property>
<!-- 连接池参数 -->
<property name="initialPoolSize">5</property>
<property name="maxPoolSize">10</property>
<property name="checkoutTimeout">3000</property>
</default-config>
<!-- 👇这个是第二配置,在new ComboPooledDataSource()时,如果传递构造参数为'otherc3p0'的话,那么就是调用本配置,目的是为了可以增加多个配置文件.默认情况下用第一配置就行了,即默认的空参构造 -->
<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>
定义C3p0数据连接池
格式:DataSource 自定义数据池对象名 = new ComboPooledDataSource();
列如:
DataSource ds = new ComboPooledDataSource();
从连接池获取SQL连接并定义
格式:Connection 自定义SQL连接对象名 = 自定义数据池对象名.getConnection();
列如:
Connection connection = ds.getConnection();
Druid数据池的应用(推荐)
导入Druid的Jar包并应用
将Jar包druid-1.0.9.jar(假若SQL驱动Jar包不存在,则一同导入)导入到libs目录下并应用
定义配置文件
Druid中,配置文件的类型为’properties’,名称任意,且放置的目录也任意.
但是需要通过Properties’对象来载入.
此处以我的配置文件举例,其配置文件的内容为:
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/test
username=root
password=root
initialSize=5
maxActive=10
maxWait=3000
通过反射IO流来加载配置文件
此处需要用到Properties对象来加载配置文件,但是当使用其’load’方法加载配置文件时,需要指定该配置文件的io,此处以反射本类的Class文件来获取其配置文件的IO流做例子.
反射IO流
格式:InputStream 自定义反射IO流对象名 = 本类名.class.getClassLoader().getResourceAsStream("自定义配置文件名.properties");
列如:
InputStream iniOfIo = DruidOfJdbc.class.getClassLoader().getResourceAsStream("druid.properties");
加载配置文件
格式:自定义Properties对象名.load(自定义反射io流对象名);
列如:
//定义Properties
Properties prop = new Properties();
//通过Properties方法读取配置信息
prop.load(iniOfIo);
定义Druid数据连接池对象
格式:DataSource 自定义数据池对象名 = DruidDataSourceFactory.createDataSource(自定义Properties对象名);
列如:
DataSource ds = DruidDataSourceFactory.createDataSource(prop);
注意:定义完Druiid数据池后,就可以用Spring框架下的Template功能进行数据库操作了.
只需要把数据池对象名当作参数传递给Template的构造方法即可.
如果不用Template进行数据库操作,那么就还需要获取并定义Druid数据池的连接.
从数据连接池获取SQL连接并定义
格式:Connection 自定义SQL连接对象名.getConnection();
JadcTemplate
Template是Spring框架下的一个封装功能,也就是将Java中JDBC的数据库操作代码进行了简化并封装.,它能够简便的执行SQL语句.
它的在创建时需要传递一个有参构造,这个有参构造必须是Druid的数据连接池对象.
导入Jar包并应用
需要在模块目录下建立libs文件夹,然后导入Jar包(假若SQL驱动Jar包不存在,则一同导入)并应用
包分别为:
commons-logging-1.2.jar
spring-beans-5.0.0.RELEASE.jar
spring-core-5.0.0.RELEASE.jar
spring-jdbc-5.0.0.RELEASE.jar
spring-tx-5.0.0.RELEASE.jar
定义Template对象
格式:JdbcTemplate 自定义Template对象名 = new JdbcTemplate(自定义Druid数据池对象名);
列如:
JdbcTemplate jdbcObj = new JdbcTemplate(ds)
执行SQL语句
注意:
1.在Template中,对于防止Sql注入的问号’?’,直接在执行SQL语句的方法中声明
大致格式为 自定义Template对象名.执行SQL语句的方法(string类型的SQL语句,充填问号的参数);
2.如果执行查询语句,要保证数据中不能存在空值’Null’,否则将会报错.
1.执行DML语句 增删改
执行DML表操作数据操作语句,并返回所影响行数
格式:自定义Template对象名.update(sql语句,充填问号的参数-可选);
列如:
int result = jdbcObj.update("DELETE FROM student3 WHERE name = ?","马云");
2.查询单行多列,结果赋值给Map集合
格式: Map<String, Object> 自定义MAP集合对象名 = 自定义Template对象名.queryForMap(sql语句,充填问号的参数-可选);
列如:
Map<String, Object> lq = jdbcObj.queryForMap("SELECT * FROM student3 ");
3.查询单行多列,结果封装到对象中
格式:对象类名 自定义对象名 = 自定义Template对象名.queryForObject(sql语句,new BeanPropertyRowMapper<对象类名>(对象类名.class),充填问号的参数-可选);
列如:
String sql = "SELECT * FROM student3 WHERE name = ? And age = ?";
Person personObj = jdbcObj.queryForObject(sql,new BeanPropertyRowMapper<Person>(Person.class),"马化腾",15);
4.查询多行多列,结果赋值给List集合
格式: List<Map<String, Object>> 自定义List集合对象名 = 自定义Template对象名.queryForList(sql语句,充填问号的参数-可选);
列如:
String sql = "SELECT * FROM emp";
List<Map<String, Object>> maps = jdbcObj.queryForList(sql);
//遍历结果
for (Map<String, Object> map : maps) {
System.out.println(map);
}
5.查询多行多列,结果封装到对象类型的集合中
格式:List<对象类名> 自定义对象名 = 自定义Template对象名.query(sql语句,new BeanPropertyRowMapper<对象类名>(对象类名.class),充填问号的参数-可选);
列如:
String sql = "SELECT * FROM student3";
List<Person> personList = jdbcObj.query(sql,new BeanPropertyRowMapper<Person>(Person.class));
6.查询单行单列,结果封装到基本数据类型变量中
格式: 基本数据类型 变量名 = 自定义Template对象名j.queryForObject(sql语句, 基本数据类型.class,充填问号的参数-可选);
列如:
String sql = "SELECT age FROM student3 WHERE name = '马化腾'";
Long numberOfAge = jdbcObj.queryForObject(sql, Long.class);
单元测试功能
'单元测试’是Java中的一个功能.用于测试某方法的代码是否执行成功.如果执行成功则返回绿色,失败则返回红色.
单元测试可以在一个类中,根据方法的不同,去执行其中的某个方法来进行测试.
关于功能所需要的Jar包
该功能需要Jar包 hamcrest-core-1.3.jar 和 junit-4.12.jar
将其Jar复制到模块的libs目录(没有则新建目录)下,然后去选择’Add as Library’以便添加成库
使用
在你欲测试的方法上一行添加注解关键字’Test’
接着对准注解了Test关键字的方法区域右键单击,就可以再点击’Run’来对相应的方法进行测试了.
Druid工具类
package cn.codeproject.druidmysql;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import com.mysql.jdbc.PreparedStatement;
import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;
public class DruidBean {
private static DataSource ds;
//静态预备加载
static {
Properties prop = new Properties();
//通过反射本类进而获取文件'druid.properties'的IO流路径. 注意:getResourceAsStream方法会直接把获得的路径转到IO流的方式.
InputStream classForIoObj = DruidBean.class.getClassLoader().getResourceAsStream("druid.properties");
try {
prop.load(classForIoObj);
//创建数据池对象,此时依照最大连接数,而瞬间在池子内拥有多个数据库连接,等着被别人拿来用.
ds = DruidDataSourceFactory.createDataSource(prop);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
//从数据库池中获取一个连接
public static Connection getConnection() throws SQLException {
return ds.getConnection();
}
//将整个数据池返回 用于JdbcTemplate
public static DataSource getDataSource(){
return ds;
}
//释放资源
public static void cloesConnect(Connection conn, PreparedStatement ps, ResultSet rs){
//注意:当你的SQL连接为从DruidDataSourceFactory.createDataSource SQL数据连接池中获得的话,CLOSE方法的底层逻辑会变成'归还连接'到数据连接池
if (conn!=null){//释放SQL连接资源 在数据池中理解为:归还连接给数据池
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (ps!=null){//释放SQL语句执行资源
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (rs!=null){//释放集合资源
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
Properties配置
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/test
username=root
password=root
initialSize=5
maxActive=10
maxWait=3000