您现在的位置是:首页 >技术交流 >事务、数据库连接池和DBUtils网站首页技术交流
事务、数据库连接池和DBUtils
一、Java事务代码演示
在Java中,事务是通过JDBC(Java Database Connectivity)来实现的。事务是指一组操作,这些操作要么全部成功执行,要么全部失败回滚。下面给出一个Java代码演示事务的基本操作:
Connection conn = null;
PreparedStatement ps1 = null;
PreparedStatement ps2 = null;
try {
conn = getConnection();
conn.setAutoCommit(false);
String sql1 = "update account set balance=balance-? where name=?";
ps1 = conn.prepareStatement(sql1);
ps1.setInt(1, 100);
ps1.setString(2, "Tom");
ps1.executeUpdate();
String sql2 = "update account set balance=balance+? where name=?";
ps2 = conn.prepareStatement(sql2);
ps2.setInt(1, 100);
ps2.setString(2, "Jerry");
ps2.executeUpdate();
conn.commit();
} catch (SQLException e) {
conn.rollback();
e.printStackTrace();
} finally {
close(conn, ps1, ps2);
}
在上述代码中,首先获取数据库连接,然后将自动提交关闭,接着定义两个SQL语句分别更新Tom和Jerry的账户余额。这两个更新语句构成了一个事务,如果其中任何一个更新操作失败,就会回滚整个事务,即撤销已经执行的更新操作。如果两个更新操作都成功执行,就通过conn.commit()
提交事务。如果发生异常错误,就通过conn.rollback()
回滚事务。
二、事务的特性ACID
在数据库中,事务具有ACID的特性,即原子性、一致性、隔离性和持久性。
- 原子性:指事务是一个不可分割的工作单位,事务中的所有操作要么全部完成,要么全部不完成,不会出现中间状态。
- 一致性:指事务执行前后,数据库的完整性约束没有被破坏,即数据应该满足一定的完整性约束。
- 隔离性:指多个事务并发访问数据库时,每个事务都应该感觉不到其他事务的存在。
- 持久性:指一旦事务提交,对数据的修改就会永久保存到数据库中。
三、事务的安全隐患
虽然事务可以保证数据的完整性和一致性,但是在实际应用中,事务也存在安全隐患。例如:
- 脏读:指一个事务读取了另一个事务未提交的数据。如果这个事务回滚,那么另一个事务读取的数据就是无效的。
- 不可重复读:指在一个事务内,多次读取同一条数据,但是每次读取的结果不同。这是因为其他事务在该事务执行期间修改了数据。
- 幻读:指在一个事务内,多次读取同一范围的数据,但是每次读取的结果不同。这是因为其他事务在该事务执行期间插入或删除了数据。
为了避免这些安全隐患,需要对事务的隔离级别进行设置。MySQL提供了四个隔离级别:读未提交、读已提交、可重复读和串行化。隔离级别越高,安全性越高,但是性能也越低。
四、可串行化
串行化是最高的隔离级别,它可以消除所有的安全隐患,但是性能也是最低的。在实际应用中,如果并发量较小,可以考虑使用可串行化的隔离级别。
五、数据库连接池
在实际应用中,数据库连接的创建和销毁是一个比较耗费资源的过程,如果每次操作都重新创建和销毁连接,会导致系统的性能降低。为了提高系统的性能,可以使用数据库连接池。
数据库连接池是一组已经创建好的数据库连接,每次请求数据库时,从连接池中获取一个连接,用完后将连接释放回连接池。连接池会对连接进行管理,包括创建、销毁、维护和监控等操作。
六、自定义数据库连接池
Java中提供了多种连接池,例如Apache Commons DBCP、C3P0和Druid等。如果这些连接池不能满足要求,也可以自定义数据库连接池。
自定义数据库连接池的步骤如下:
- 创建连接池类,继承自
javax.sql.DataSource
。 - 在连接池类中创建一个线程安全的连接池集合,用于存储数据库连接。
- 在连接池类中实现
getConnection()
方法,用于从连接池中获取连接。 - 在连接池类中实现
releaseConnection()
方法,用于将连接释放回连接池。
七、开源连接池及配置应用
在实际应用中,可以选择使用开源的连接池。下面以Druid为例,介绍如何配置Druid连接池。
- 首先在pom.xml中添加Druid的依赖。
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.16</version>
</dependency>
- 在application.properties中添加Druid的配置。
spring.datasource.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.druid.initial-size=1
spring.datasource.druid.min-idle=1
spring.datasource.druid.max-active=20
spring.datasource.druid.max-wait=60000
spring.datasource.druid.time-between-eviction-runs-millis=60000
spring.datasource.druid.min-evictable-idle-time-millis=300000
spring.datasource.druid.validation-query=SELECT 1
spring.datasource.druid.test-while-idle=true
spring.datasource.druid.test-on-borrow=false
spring.datasource.druid.test-on-return=false
Druid连接池提供了很多配置项,可以根据具体需求进行调整。
八、DBUtils增删改查
DBUtils是Apache Commons的一个开源组件,提供了对JDBC的简化封装,可以让Java开发人员更加方便地进行增删改查操作。
DBUtils提供了多种操作方式,包括QueryRunner、ResultSetHandler、ScalarHandler和BatchExecutor等。下面以QueryRunner为例,介绍如何进行增删改查操作。
- 首先在pom.xml中添加DBUtils的依赖。
<dependency>
<groupId>commons-dbutils</groupId>
<artifactId>commons-dbutils</artifactId>
<version>1.7</version>
</dependency>
- 然后在代码中创建一个QueryRunner对象,并使用它进行增删改查操作。
QueryRunner qr = new QueryRunner(dataSource);
String sql = "INSERT INTO user (name, age) VALUES (?, ?)";
qr.update(sql, "Tom", 20);
sql = "SELECT * FROM user WHERE age > ?";
List<User> userList = qr.query(sql, new BeanListHandler<>(User.class), 18);
在上述代码中,首先创建一个QueryRunner对象,参数为数据库连接池。然后使用update()
方法进行插入操作,使用query()
方法进行查询操作。
九、总结
本文介绍了Java事务代码演示、事务的特性ACID、事务的安全隐患、可串行化、数据库连接池、自定义数据库连接池、开源连接池及配置应用、DBUtils增删改查等内容。通过学习本文,读者可以了解到Java事务的基本操作和特性,数据库连接池的作用和使用方法,以及DBUtils的简化封装。希望对Java开发人员有所帮助。