在实际项目开发中访问操作数据库,肯定要使用到连接池技术,不仅可以提升数据库操作效率,也在某种程度上提高了代码质量。前面我们简单介绍了 c3p0 连接池的使用,今天我们还是以操作 mysql 为例简单介绍一下 druid 数据库连接池技术的使用。
druid 是阿里技术团队提供的一款优秀的开源数据库连接池,在国内使用非常广泛。作为后起之秀,其功能灵活强大稳定,性能也比 c3p0 要高,大有替代其它第三方数据库连接池的趋势。我们也推荐在项目和产品开发中优先考虑 druid 连接池技术的使用。
druid 的 GitHub 地址为:https://github.com/alibaba/druid (GitHub 访问可能比较慢)
druid 的 Gitee 地址为:https://gitee.com/wangmt2000/druid
一、配置 druid 连接池
我们首先创建一个 JavaSE 的 Maven 项目,在 pom.xml 文件中导入 druid 和 mysql 的 jar 包。
我们可以从 https://mvnrepository.com 上进行查找有关各种 jar 包依赖的 xml 配置内容,复制粘贴到 pom.xml 即可。
druid 的 jar 包网址是:https://mvnrepository.com/artifact/com.alibaba/druid
mysql 连接 java 的驱动 jar 包网址是:https://mvnrepository.com/artifact/mysql/mysql-connector-java
我在 pom.xml 配置的都是当前最新版本的 jar 包,如下所示:
<!-- 导入 druid 的 jar 包 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.8</version>
</dependency>
<!-- 导入 mysql 的 jar 包 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
配置好引用的 jar 包后,打开右侧的 Maven 窗口,刷新一下,这样 Maven 会自动下载所需的 jar 包文件。
然后在项目的 resources 资源目录下创建 druid 的 properties 配置文件,properties 配置文件可以随意命名,但是文件内容中每项配置的 key 必须是指定的名称,这里我使用 druid.properties 作为配置文件的名称,其文件内容如下所示:
# 数据库连接参数
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/testdb
username=root
password=123456
# 初始化连接的数量
initialSize=3
# 最大连接的数量
maxActive=20
# 获取连接的最大等待时间(毫秒)
maxWait=3000
当然可选配置项有很多,上面列出的只是最常用的核心配置项,有关详细的配置项列表,可以参看以下网址:
https://github.com/alibaba/druid/wiki/DruidDataSource配置 (GitHub 访问可能比较慢)
二、使用 druid 连接池
使用 druid 连接池,主要是使用 DruidDataSourceFactory 根据 properties 配置文件内容创建出 DataSource 数据源对象,然后调用其 getConnection 方法获取数据库连接对象,拿到连接对象之后,其它的操作跟 JDBC 访问数据库的操作一模一样,唯一的区别就是当调用连接的 close 方法时,底层不再是关闭销毁连接对象,而是将连接对象放入到连接池中,以便后续新的请求到来时,直接拿去使用。具体代码如下:
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Properties;
public class druidtest {
public static void main(String[] args) throws Exception {
//加载配置文件
InputStream is = druidtest.class.getClassLoader().getResourceAsStream("druid.properties");
Properties prop = new Properties();
prop.load(is);
//根据配置文件内容,创建出数据源对象
DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
//通过数据源对象获取数据库连接
//如果连接池中的连接已经被用完,则会等待一定的时间(所配置的时间)
//如果等待超时,就会抛出异常
Connection con = dataSource.getConnection();
//执行 sql 语句,获取并打印结果集
String sql = "select e_id,e_name,e_age from employee";
PreparedStatement pst = con.prepareStatement(sql);
ResultSet rs = pst.executeQuery();
while(rs.next()) {
System.out.println(
rs.getInt("e_id") + "\t" +
rs.getString("e_name") + "\t" +
rs.getInt("e_age"));
}
//释放资源
rs.close();
pst.close();
//这里的关闭连接,并没有关闭和销毁连接
//而是把连接对象,放入到连接池中,供后续访问时直接拿去使用
con.close();
}
}
如果你之前基于 JDBC 编写过通用的数据库访问类,那么将它改造为基于 druid 的数据库访问类,也是很容易的。
这里我提供一个相对比较完整的基于 druid 连接池的数据库访问类(具体细节就不详细介绍了),内容如下所示:
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.beans.PropertyDescriptor;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
public class jdbcHelper {
private static DataSource dataSource;
//静态初始化,加载 properties 配置文件,创建数据源对象
static {
try {
InputStream is =
druidtest.class.getClassLoader().getResourceAsStream("druid.properties");
Properties prop = new Properties();
prop.load(is);
dataSource = DruidDataSourceFactory.createDataSource(prop);
} catch (Exception ex) {
ex.printStackTrace();
}
}
//通过数据源对象,获取连接对象
public static Connection getConnection() {
Connection con = null;
try {
con = dataSource.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
return con;
}
//释放查询操作相关的资源(结果集对象,SQL语句对象,归还数据库连接)
public static void close(Connection con, Statement stat, ResultSet rs) {
if (con != null) {
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (stat != null) {
try {
stat.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
//释放增删改相关操作的资源(SQL语句对象,归还数据库连接)
public static void close(Connection con, Statement stat) {
close(con, stat, null);
}
//执行查询 SQL 语句,返回查询的单个值
public static <T> T queryForValue(String sql, Class<T> returnType, Object... parameters) {
T result = null;
Connection con = null;
PreparedStatement pst = null;
ResultSet rs = null;
try {
con = dataSource.getConnection();
pst = con.prepareStatement(sql);
if (parameters.length > 0) {
for (int i = 0; i < parameters.length; i++) {
pst.setObject(i + 1, parameters[i]);
}
}
rs = pst.executeQuery();
if (rs.next()) {
result = returnType.cast(rs.getObject(1));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
close(con, pst, rs);
}
return result;
}
//执行查询 SQL 语句,返回查询的单个实体对象
public static <T> T queryForObject(String sql, Class<T> returnType, Object... parameters) {
T result = null;
Connection con = null;
PreparedStatement pst = null;
ResultSet rs = null;
try {
result = returnType.getConstructor().newInstance();
con = dataSource.getConnection();
pst = con.prepareStatement(sql);
if (parameters.length > 0) {
for (int i = 0; i < parameters.length; i++) {
pst.setObject(i + 1, parameters[i]);
}
}
rs = pst.executeQuery();
if (rs.next()) {
ResultSetMetaData metaData = rs.getMetaData();
int count = metaData.getColumnCount();
for (int i = 1; i <= count; i++) {
String columnName = metaData.getColumnName(i);
Object value = rs.getObject(columnName);
PropertyDescriptor pd =
new PropertyDescriptor(columnName.toLowerCase(), returnType);
Method writeMethod = pd.getWriteMethod();
writeMethod.invoke(result, value);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
close(con, pst, rs);
}
return result;
}
//执行查询 SQL 语句,返回查询的实体对象列表
public static <T> List<T> queryForList(String sql, Class<T> returnType, Object... parameters) {
List<T> list = new ArrayList<>();
Connection con = null;
PreparedStatement pst = null;
ResultSet rs = null;
try {
con = dataSource.getConnection();
pst = con.prepareStatement(sql);
if (parameters.length > 0) {
for (int i = 0; i < parameters.length; i++) {
pst.setObject(i + 1, parameters[i]);
}
}
rs = pst.executeQuery();
ResultSetMetaData metaData = rs.getMetaData();
int count = metaData.getColumnCount();
while (rs.next()) {
T bean = returnType.getConstructor().newInstance();
for (int i = 1; i <= count; i++) {
String columnName = metaData.getColumnName(i);
Object value = rs.getObject(columnName);
PropertyDescriptor pd =
new PropertyDescriptor(columnName.toLowerCase(), returnType);
Method writeMethod = pd.getWriteMethod();
writeMethod.invoke(bean, value);
}
list.add(bean);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
close(con, pst, rs);
}
return list;
}
//执行增删改 SQL 语句,返回受影响的行数
public static int executeSql(String sql,Object...parameters) {
int count = 0;
Connection con = null;
PreparedStatement pst = null;
try{
con = dataSource.getConnection();
pst = con.prepareStatement(sql);
if (parameters.length > 0) {
for (int i = 0; i < parameters.length; i++) {
pst.setObject(i + 1, parameters[i]);
}
}
count = pst.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
close(con,pst);
}
return count;
}
}
然后在 Maven 项目的 test 目录下创建测试类,使用这个 druid 数据库访问类测试其使用方法:
import org.junit.Test;
import java.util.List;
public class jdbcHelperTest {
@Test
public void queryForValue() {
//查询员工数量
String sql = "select count(*) from employee";
Long value = jdbcHelper.queryForValue(sql,Long.class);
System.out.println(value);
}
@Test
public void queryForList() {
//查询所有员工
String sql = "select * from employee";
List<Employee> list = jdbcHelper.queryForList(sql, Employee.class);
for(Employee emp : list) {
System.out.println(emp);
}
}
@Test
public void queryForObject() {
//查询一条员工,并打印出来
String sql = "select * from employee WHERE e_id=?";
Employee emp = jdbcHelper.queryForObject(sql,Employee.class,1);
System.out.println(emp);
}
@Test
public void insert() {
//添加一条新员工
String sql = "insert into employee(e_id,e_name,e_age) values(?,?,?)";
Object[] params = {6,"任天蓬",40};
int result = jdbcHelper.executeSql(sql, params);
System.out.println(result);
}
@Test
public void update() {
//通过员工id,修改员工的年龄
String sql = "update employee set e_age=? where e_id=?";
Object[] params = {38,6};
int result = jdbcHelper.executeSql(sql, params);
System.out.println(result);
}
@Test
public void delete() {
//通过员工姓名,删除员工
String sql = "DELETE FROM employee WHERE e_name=?";
int result = jdbcHelper.executeSql(sql, "任天蓬");
System.out.println(result);
}
}
OK,以上只是简单的 druid 连接池技术的介绍,总体来说使用起来很简单,希望对大家有用。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/191157.html