diff --git a/README.md b/README.md
index 093f5c6..07660fa 100644
--- a/README.md
+++ b/README.md
@@ -104,22 +104,22 @@
```xml
- junit
- junit
- 4.12
- test
+ junit
+ junit
+ 4.12
+ test
- org.apache.commons
- commons-dbcp2
- 2.6.0
+ org.apache.commons
+ commons-dbcp2
+ 2.6.0
- log4j
- log4j
- 1.2.17
+ log4j
+ log4j
+ 1.2.17
@@ -170,14 +170,14 @@ maxWaitMillis=-1
路径:`cn.zzs.dbcp`
```java
- // 导入配置文件
- Properties properties = new Properties();
- InputStream in = JDBCUtil.class.getClassLoader().getResourceAsStream("dbcp.properties");
- properties.load(in);
- // 根据配置文件内容获得数据源对象
- DataSource dataSource = BasicDataSourceFactory.createDataSource(properties);
- // 获得连接
- Connection conn = dataSource.getConnection();
+ // 导入配置文件
+ Properties properties = new Properties();
+ InputStream in = JDBCUtil.class.getClassLoader().getResourceAsStream("dbcp.properties");
+ properties.load(in);
+ // 根据配置文件内容获得数据源对象
+ DataSource dataSource = BasicDataSourceFactory.createDataSource(properties);
+ // 获得连接
+ Connection conn = dataSource.getConnection();
```
## 编写测试类
@@ -185,34 +185,34 @@ maxWaitMillis=-1
这里以保存用户为例,路径test目录下的`cn.zzs.dbcp`。
```java
- @Test
- public void save() throws SQLException {
- // 创建sql
- String sql = "insert into demo_user values(null,?,?,?,?,?)";
- Connection connection = null;
- PreparedStatement statement = null;
- try {
- // 获得连接
- connection = JDBCUtils.getConnection();
- // 开启事务设置非自动提交
- connection.setAutoCommit(false);
- // 获得Statement对象
- statement = connection.prepareStatement(sql);
- // 设置参数
- statement.setString(1, "zzf003");
- statement.setInt(2, 18);
- statement.setDate(3, new Date(System.currentTimeMillis()));
- statement.setDate(4, new Date(System.currentTimeMillis()));
- statement.setBoolean(5, false);
- // 执行
- statement.executeUpdate();
- // 提交事务
- connection.commit();
- } finally {
- // 释放资源
- JDBCUtils.release(connection, statement, null);
- }
- }
+ @Test
+ public void save() throws SQLException {
+ // 创建sql
+ String sql = "insert into demo_user values(null,?,?,?,?,?)";
+ Connection connection = null;
+ PreparedStatement statement = null;
+ try {
+ // 获得连接
+ connection = JDBCUtils.getConnection();
+ // 开启事务设置非自动提交
+ connection.setAutoCommit(false);
+ // 获得Statement对象
+ statement = connection.prepareStatement(sql);
+ // 设置参数
+ statement.setString(1, "zzf003");
+ statement.setInt(2, 18);
+ statement.setDate(3, new Date(System.currentTimeMillis()));
+ statement.setDate(4, new Date(System.currentTimeMillis()));
+ statement.setBoolean(5, false);
+ // 执行
+ statement.executeUpdate();
+ // 提交事务
+ connection.commit();
+ } finally {
+ // 释放资源
+ JDBCUtils.release(connection, statement, null);
+ }
+ }
```
@@ -501,51 +501,51 @@ accessToUnderlyingConnectionAllowed=false
5. 开启空闲资源回收线程(如果设置`timeBetweenEvictionRunsMillis`为正数)。
```java
- protected DataSource createDataSource() throws SQLException {
- if(closed) {
- throw new SQLException("Data source is closed");
- }
- if(dataSource != null) {
- return dataSource;
- }
-
- synchronized(this) {
- if(dataSource != null) {
- return dataSource;
- }
- // 注册MBean,用于支持JMX,这方面的内容不在这里扩展
- jmxRegister();
-
- // 创建原生Connection工厂:本质就是持有数据库驱动对象和几个连接参数
- final ConnectionFactory driverConnectionFactory = createConnectionFactory();
-
- // 将driverConnectionFactory包装成池化Connection工厂
- PoolableConnectionFactory poolableConnectionFactory = createPoolableConnectionFactory(driverConnectionFactory);
- // 设置PreparedStatements缓存(其实在这里可以发现,上面创建池化工厂时就设置了缓存,这里没必要再设置一遍)
- poolableConnectionFactory.setPoolStatements(poolPreparedStatements);
- poolableConnectionFactory.setMaxOpenPreparedStatements(maxOpenPreparedStatements);
-
- // 创建数据库连接池对象GenericObjectPool,用于管理连接
- // BasicDataSource将持有GenericObjectPool对象
- createConnectionPool(poolableConnectionFactory);
-
- // 创建PoolingDataSource对象
- // 该对象持有GenericObjectPool对象的引用
- DataSource newDataSource = createDataSourceInstance();
- newDataSource.setLogWriter(logWriter);
-
- // 根据我们设置的initialSize创建初始连接
- for(int i = 0; i < initialSize; i++) {
- connectionPool.addObject();
- }
-
- // 开启连接池的evictor线程
- startPoolMaintenance();
- // 最后BasicDataSource将持有上面创建的PoolingDataSource对象
- dataSource = newDataSource;
- return dataSource;
- }
- }
+ protected DataSource createDataSource() throws SQLException {
+ if(closed) {
+ throw new SQLException("Data source is closed");
+ }
+ if(dataSource != null) {
+ return dataSource;
+ }
+
+ synchronized(this) {
+ if(dataSource != null) {
+ return dataSource;
+ }
+ // 注册MBean,用于支持JMX,这方面的内容不在这里扩展
+ jmxRegister();
+
+ // 创建原生Connection工厂:本质就是持有数据库驱动对象和几个连接参数
+ final ConnectionFactory driverConnectionFactory = createConnectionFactory();
+
+ // 将driverConnectionFactory包装成池化Connection工厂
+ PoolableConnectionFactory poolableConnectionFactory = createPoolableConnectionFactory(driverConnectionFactory);
+ // 设置PreparedStatements缓存(其实在这里可以发现,上面创建池化工厂时就设置了缓存,这里没必要再设置一遍)
+ poolableConnectionFactory.setPoolStatements(poolPreparedStatements);
+ poolableConnectionFactory.setMaxOpenPreparedStatements(maxOpenPreparedStatements);
+
+ // 创建数据库连接池对象GenericObjectPool,用于管理连接
+ // BasicDataSource将持有GenericObjectPool对象
+ createConnectionPool(poolableConnectionFactory);
+
+ // 创建PoolingDataSource对象
+ // 该对象持有GenericObjectPool对象的引用
+ DataSource newDataSource = createDataSourceInstance();
+ newDataSource.setLogWriter(logWriter);
+
+ // 根据我们设置的initialSize创建初始连接
+ for(int i = 0; i < initialSize; i++) {
+ connectionPool.addObject();
+ }
+
+ // 开启连接池的evictor线程
+ startPoolMaintenance();
+ // 最后BasicDataSource将持有上面创建的PoolingDataSource对象
+ dataSource = newDataSource;
+ return dataSource;
+ }
+ }
```
以上方法涉及到几个类,这里再补充下`UML`图。
@@ -1154,24 +1154,24 @@ accessToUnderlyingConnectionAllowed=false
本文在前面例子的基础上增加以下依赖,因为是web项目,所以打包方式为`war`:
```xml
-
- javax.servlet
- jstl
- 1.2
- provided
-
-
- javax.servlet
- javax.servlet-api
- 3.1.0
- provided
-
-
- javax.servlet.jsp
- javax.servlet.jsp-api
- 2.2.1
- provided
-
+
+ javax.servlet
+ jstl
+ 1.2
+ provided
+
+
+ javax.servlet
+ javax.servlet-api
+ 3.1.0
+ provided
+
+
+ javax.servlet.jsp
+ javax.servlet.jsp-api
+ 2.2.1
+ provided
+
```
## 编写context.xml
@@ -1181,20 +1181,20 @@ accessToUnderlyingConnectionAllowed=false
```xml
-
+
+ />
+ />
```
@@ -1233,17 +1233,17 @@ accessToUnderlyingConnectionAllowed=false
Test DriverAdapterCPDS
bean/DriverAdapterCPDS
org.apache.commons.dbcp2.cpdsadapter.DriverAdapterCPDS
-
-
- Test SharedPoolDataSource
- bean/SharedPoolDataSourceFactory
- org.apache.commons.dbcp2.datasources.SharedPoolDataSource
-
+
+
+ Test SharedPoolDataSource
+ bean/SharedPoolDataSourceFactory
+ org.apache.commons.dbcp2.datasources.SharedPoolDataSource
+
Test erUserPoolDataSource
bean/erUserPoolDataSourceFactory
org.apache.commons.dbcp2.datasources.erUserPoolDataSource
-
+
```
## 编写jsp
@@ -1254,22 +1254,22 @@ accessToUnderlyingConnectionAllowed=false
<%
// 获得名称服务的上下文对象
- Context initCtx = new InitialContext();
- Context envCtx = (Context)initCtx.lookup("java:comp/env/");
-
- // 查找指定名字的对象
- DataSource ds = (DataSource)envCtx.lookup("bean/SharedPoolDataSourceFactory");
-
- DataSource ds2 = (DataSource)envCtx.lookup("bean/PerUserPoolDataSourceFactory");
- // 获取连接
- Connection conn = ds.getConnection("root","root");
- System.out.println("conn" + conn);
+ Context initCtx = new InitialContext();
+ Context envCtx = (Context)initCtx.lookup("java:comp/env/");
+
+ // 查找指定名字的对象
+ DataSource ds = (DataSource)envCtx.lookup("bean/SharedPoolDataSourceFactory");
+
+ DataSource ds2 = (DataSource)envCtx.lookup("bean/PerUserPoolDataSourceFactory");
+ // 获取连接
+ Connection conn = ds.getConnection("root","root");
+ System.out.println("conn" + conn);
Connection conn2 = ds2.getConnection("zzf","zzf");
System.out.println("conn2" + conn2);
// ... 使用连接操作数据库,以及释放资源 ...
- conn.close();
- conn2.close();
+ conn.close();
+ conn2.close();
%>
```
@@ -1325,12 +1325,12 @@ XA RECOVER; -- 查看处于prepare状态的事务列表
```xml
-
- javax.transaction
- jta
- 1.1
-
-
+
+ javax.transaction
+ jta
+ 1.1
+
+
com.atomikos
transactions-jdbc
3.9.3
@@ -1342,42 +1342,42 @@ XA RECOVER; -- 查看处于prepare状态的事务列表
这里千万记得要设置`DefaultCatalog`,否则当前事务中注册不同资源管理器时,可能都会被当成同一个资源管理器而拒绝注册并报错,因为这个问题,花了我好长时间才解决。
```java
- public BasicManagedDataSource getBasicManagedDataSource(
- TransactionManager transactionManager,
- String url,
- String username,
- String password) {
- BasicManagedDataSource basicManagedDataSource = new BasicManagedDataSource();
- basicManagedDataSource.setTransactionManager(transactionManager);
- basicManagedDataSource.setUrl(url);
- basicManagedDataSource.setUsername(username);
- basicManagedDataSource.setPassword(password);
- basicManagedDataSource.setDefaultAutoCommit(false);
- basicManagedDataSource.setXADataSource("com.mysql.cj.jdbc.MysqlXADataSource");
- return basicManagedDataSource;
- }
- @Test
- public void test01() throws Exception {
- // 获得事务管理器
- TransactionManager transactionManager = new UserTransactionManager();
-
- // 获取第一个数据库的数据源
- BasicManagedDataSource basicManagedDataSource1 = getBasicManagedDataSource(
- transactionManager,
- "jdbc:mysql://localhost:3306/github_demo?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=true",
- "root",
- "root");
- // 注意,这一步非常重要
- basicManagedDataSource1.setDefaultCatalog("github_demo");
-
- // 获取第二个数据库的数据源
- BasicManagedDataSource basicManagedDataSource2 = getBasicManagedDataSource(
- transactionManager,
- "jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=true",
- "zzf",
- "zzf");
- // 注意,这一步非常重要
- basicManagedDataSource1.setDefaultCatalog("test");
+ public BasicManagedDataSource getBasicManagedDataSource(
+ TransactionManager transactionManager,
+ String url,
+ String username,
+ String password) {
+ BasicManagedDataSource basicManagedDataSource = new BasicManagedDataSource();
+ basicManagedDataSource.setTransactionManager(transactionManager);
+ basicManagedDataSource.setUrl(url);
+ basicManagedDataSource.setUsername(username);
+ basicManagedDataSource.setPassword(password);
+ basicManagedDataSource.setDefaultAutoCommit(false);
+ basicManagedDataSource.setXADataSource("com.mysql.cj.jdbc.MysqlXADataSource");
+ return basicManagedDataSource;
+ }
+ @Test
+ public void test01() throws Exception {
+ // 获得事务管理器
+ TransactionManager transactionManager = new UserTransactionManager();
+
+ // 获取第一个数据库的数据源
+ BasicManagedDataSource basicManagedDataSource1 = getBasicManagedDataSource(
+ transactionManager,
+ "jdbc:mysql://localhost:3306/github_demo?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=true",
+ "root",
+ "root");
+ // 注意,这一步非常重要
+ basicManagedDataSource1.setDefaultCatalog("github_demo");
+
+ // 获取第二个数据库的数据源
+ BasicManagedDataSource basicManagedDataSource2 = getBasicManagedDataSource(
+ transactionManager,
+ "jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=true",
+ "zzf",
+ "zzf");
+ // 注意,这一步非常重要
+ basicManagedDataSource1.setDefaultCatalog("test");
}
```
@@ -1386,56 +1386,56 @@ XA RECOVER; -- 查看处于prepare状态的事务列表
通过运行代码可以发现,当数据库1和2的操作都成功,才会提交,只要其中一个数据库执行失败,两个操作都会回滚。
```java
- @Test
- public void test01() throws Exception {
- Connection connection1 = null;
- Statement statement1 = null;
- Connection connection2 = null;
- Statement statement2 = null;
- transactionManager.begin();
- try {
- // 获取连接并进行数据库操作,这里会将会将XAResource注册到当前线程的XA事务对象
- /**
- * XA START xid1;-- 启动一个事务,并使之为active状态
- */
- connection1 = basicManagedDataSource1.getConnection();
- statement1 = connection1.createStatement();
- /**
- * update github_demo.demo_user set deleted = 1 where id = '1'; -- 事务中的语句
- */
- boolean result1 = statement1.execute("update github_demo.demo_user set deleted = 1 where id = '1'");
- System.out.println(result1);
-
- /**
- * XA START xid2;-- 启动一个事务,并使之为active状态
- */
- connection2 = basicManagedDataSource2.getConnection();
- statement2 = connection2.createStatement();
- /**
- * update test.demo_user set deleted = 1 where id = '1'; -- 事务中的语句
- */
- boolean result2 = statement2.execute("update test.demo_user set deleted = 1 where id = '1'");
- System.out.println(result2);
-
- /**
- * 当这执行以下语句:
- * XA END xid1; -- 把事务置为idle状态
- * XA PREPARE xid1; -- 把事务置为prepare状态
- * XA END xid2; -- 把事务置为idle状态
- * XA PREPARE xid2; -- 把事务置为prepare状态
- * XA COMMIT xid1; -- 提交事务
- * XA COMMIT xid2; -- 提交事务
- */
- transactionManager.commit();
- } catch(Exception e) {
- e.printStackTrace();
- } finally {
- statement1.close();
- statement2.close();
- connection1.close();
- connection2.close();
- }
- }
+ @Test
+ public void test01() throws Exception {
+ Connection connection1 = null;
+ Statement statement1 = null;
+ Connection connection2 = null;
+ Statement statement2 = null;
+ transactionManager.begin();
+ try {
+ // 获取连接并进行数据库操作,这里会将会将XAResource注册到当前线程的XA事务对象
+ /**
+ * XA START xid1;-- 启动一个事务,并使之为active状态
+ */
+ connection1 = basicManagedDataSource1.getConnection();
+ statement1 = connection1.createStatement();
+ /**
+ * update github_demo.demo_user set deleted = 1 where id = '1'; -- 事务中的语句
+ */
+ boolean result1 = statement1.execute("update github_demo.demo_user set deleted = 1 where id = '1'");
+ System.out.println(result1);
+
+ /**
+ * XA START xid2;-- 启动一个事务,并使之为active状态
+ */
+ connection2 = basicManagedDataSource2.getConnection();
+ statement2 = connection2.createStatement();
+ /**
+ * update test.demo_user set deleted = 1 where id = '1'; -- 事务中的语句
+ */
+ boolean result2 = statement2.execute("update test.demo_user set deleted = 1 where id = '1'");
+ System.out.println(result2);
+
+ /**
+ * 当这执行以下语句:
+ * XA END xid1; -- 把事务置为idle状态
+ * XA PREPARE xid1; -- 把事务置为prepare状态
+ * XA END xid2; -- 把事务置为idle状态
+ * XA PREPARE xid2; -- 把事务置为prepare状态
+ * XA COMMIT xid1; -- 提交事务
+ * XA COMMIT xid2; -- 提交事务
+ */
+ transactionManager.commit();
+ } catch(Exception e) {
+ e.printStackTrace();
+ } finally {
+ statement1.close();
+ statement2.close();
+ connection1.close();
+ connection2.close();
+ }
+ }
```
> 相关源码请移步:https://github.com/ZhangZiSheng001/dbcp-demo
diff --git a/pom.xml b/pom.xml
index 24c031c..2e3ad0c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,68 +1,67 @@
-
- 4.0.0
- cn.zzs
- DBCP-demo
- war
- 1.0.0
- DBCP-demo
- http://maven.apache.org
-
-
-
- junit
- junit
- 4.12
- test
-
-
-
- org.apache.commons
- commons-dbcp2
- 2.6.0
-
-
-
- log4j
- log4j
- 1.2.17
-
-
-
- mysql
- mysql-connector-java
- 8.0.15
-
-
-
- javax.servlet
- jstl
- 1.2
- provided
-
-
- javax.servlet
- javax.servlet-api
- 3.1.0
- provided
-
-
- javax.servlet.jsp
- javax.servlet.jsp-api
- 2.2.1
- provided
-
+
+ 4.0.0
+ cn.zzs
+ DBCP-demo
+ war
+ 1.0.0
+ DBCP-demo
+ http://maven.apache.org
+
+
+
+ junit
+ junit
+ 4.12
+ test
+
+
+
+ org.apache.commons
+ commons-dbcp2
+ 2.6.0
+
+
+
+ log4j
+ log4j
+ 1.2.17
+
+
+
+ mysql
+ mysql-connector-java
+ 8.0.15
+
+
+
+ javax.servlet
+ jstl
+ 1.2
+ provided
+
+
+ javax.servlet
+ javax.servlet-api
+ 3.1.0
+ provided
+
+
+ javax.servlet.jsp
+ javax.servlet.jsp-api
+ 2.2.1
+ provided
+
-
- javax.transaction
- jta
- 1.1
-
-
+
+ javax.transaction
+ jta
+ 1.1
+
+
com.atomikos
transactions-jdbc
3.9.3
-
+
diff --git a/src/main/java/cn/zzs/dbcp/JDBCUtils.java b/src/main/java/cn/zzs/dbcp/JDBCUtils.java
index bfe1ae2..ca87898 100644
--- a/src/main/java/cn/zzs/dbcp/JDBCUtils.java
+++ b/src/main/java/cn/zzs/dbcp/JDBCUtils.java
@@ -20,107 +20,107 @@ import org.apache.commons.logging.LogFactory;
*/
public class JDBCUtils {
- private static DataSource dataSource;
+ private static DataSource dataSource;
- private static ThreadLocal tl = new ThreadLocal<>();
+ private static ThreadLocal tl = new ThreadLocal<>();
- private static final Object obj = new Object();
+ private static final Object obj = new Object();
- private static final Log log = LogFactory.getLog(JDBCUtils.class);
+ private static final Log log = LogFactory.getLog(JDBCUtils.class);
- static {
- init();
- }
+ static {
+ init();
+ }
- /**
- *
- * 获取数据库连接对象的方法,线程安全
- * @author: zzs
- * @date: 2019年8月31日 下午9:22:29
- * @return: Connection
- */
- public static Connection getConnection() throws SQLException {
- // 从当前线程中获取连接对象
- Connection connection = tl.get();
- // 判断为空的话,创建连接并绑定到当前线程
- if(connection == null) {
- synchronized(obj) {
- if((connection = tl.get()) == null) {
- connection = createConnection();
- tl.set(connection);
- }
- }
- }
- return connection;
- }
+ /**
+ *
+ * 获取数据库连接对象的方法,线程安全
+ * @author: zzs
+ * @date: 2019年8月31日 下午9:22:29
+ * @return: Connection
+ */
+ public static Connection getConnection() throws SQLException {
+ // 从当前线程中获取连接对象
+ Connection connection = tl.get();
+ // 判断为空的话,创建连接并绑定到当前线程
+ if(connection == null) {
+ synchronized(obj) {
+ if((connection = tl.get()) == null) {
+ connection = createConnection();
+ tl.set(connection);
+ }
+ }
+ }
+ return connection;
+ }
- /**
- *
- * 释放资源
- * @author: zzs
- * @date: 2019年8月31日 下午9:39:24
- * @param conn
- * @param statement
- * @return: void
- */
- public static void release(Connection conn, Statement statement, ResultSet resultSet) {
- if(resultSet != null) {
- try {
- resultSet.close();
- } catch(SQLException e) {
- log.error("关闭ResultSet对象异常", e);
- }
- }
- if(statement != null) {
- try {
- statement.close();
- } catch(SQLException e) {
- log.error("关闭Statement对象异常", e);
- }
- }
- // 注意:这里不关闭连接
- if(conn != null) {
- try {
- conn.close();
- tl.remove();
- } catch(SQLException e) {
- log.error("关闭Connection对象异常", e);
- }
- }
- }
+ /**
+ *
+ * 释放资源
+ * @author: zzs
+ * @date: 2019年8月31日 下午9:39:24
+ * @param conn
+ * @param statement
+ * @return: void
+ */
+ public static void release(Connection conn, Statement statement, ResultSet resultSet) {
+ if(resultSet != null) {
+ try {
+ resultSet.close();
+ } catch(SQLException e) {
+ log.error("关闭ResultSet对象异常", e);
+ }
+ }
+ if(statement != null) {
+ try {
+ statement.close();
+ } catch(SQLException e) {
+ log.error("关闭Statement对象异常", e);
+ }
+ }
+ // 注意:这里不关闭连接
+ if(conn != null) {
+ try {
+ conn.close();
+ tl.remove();
+ } catch(SQLException e) {
+ log.error("关闭Connection对象异常", e);
+ }
+ }
+ }
- /**
- *
- * 创建数据库连接
- * @author: zzs
- * @date: 2019年8月31日 下午9:27:03
- * @return: Connection
- * @throws SQLException
- */
- private static Connection createConnection() throws SQLException {
- Connection conn = null;
- // 获得连接
- conn = dataSource.getConnection();
- return conn;
- }
+ /**
+ *
+ * 创建数据库连接
+ * @author: zzs
+ * @date: 2019年8月31日 下午9:27:03
+ * @return: Connection
+ * @throws SQLException
+ */
+ private static Connection createConnection() throws SQLException {
+ Connection conn = null;
+ // 获得连接
+ conn = dataSource.getConnection();
+ return conn;
+ }
- /**
- * 根据指定配置文件创建数据源对象
- * @author: zzs
- * @date: 2019年9月1日 上午10:53:05
- * @return: void
- * @throws Exception
- */
- private static void init() {
- // 导入配置文件
- Properties properties = new Properties();
- InputStream in = JDBCUtils.class.getClassLoader().getResourceAsStream("dbcp.properties");
- try {
- properties.load(in);
- // 根据配置文件内容获得数据源对象
- dataSource = BasicDataSourceFactory.createDataSource(properties);
- } catch(Exception ex) {
- throw new RuntimeException("根据指定配置文件创建数据源出错", ex);
- }
- }
+ /**
+ * 根据指定配置文件创建数据源对象
+ * @author: zzs
+ * @date: 2019年9月1日 上午10:53:05
+ * @return: void
+ * @throws Exception
+ */
+ private static void init() {
+ // 导入配置文件
+ Properties properties = new Properties();
+ InputStream in = JDBCUtils.class.getClassLoader().getResourceAsStream("dbcp.properties");
+ try {
+ properties.load(in);
+ // 根据配置文件内容获得数据源对象
+ dataSource = BasicDataSourceFactory.createDataSource(properties);
+ } catch(Exception ex) {
+ throw new RuntimeException("根据指定配置文件创建数据源出错", ex);
+ }
+ }
}
diff --git a/src/test/java/cn/zzs/dbcp/BasicDataSourceTest.java b/src/test/java/cn/zzs/dbcp/BasicDataSourceTest.java
index 97322a0..fa9cf94 100644
--- a/src/test/java/cn/zzs/dbcp/BasicDataSourceTest.java
+++ b/src/test/java/cn/zzs/dbcp/BasicDataSourceTest.java
@@ -15,126 +15,126 @@ import org.junit.Test;
*/
public class BasicDataSourceTest {
- /**
- * 测试添加用户
- * @throws SQLException
- */
- @Test
- public void save() throws SQLException {
- // 创建sql
- String sql = "insert into demo_user values(null,?,?,?,?,?)";
- Connection connection = null;
- PreparedStatement statement = null;
- try {
- // 获得连接
- connection = JDBCUtils.getConnection();
- // 开启事务设置非自动提交
- connection.setAutoCommit(false);
- // 获得Statement对象
- statement = connection.prepareStatement(sql);
- // 设置参数
- statement.setString(1, "zzf003");
- statement.setInt(2, 18);
- statement.setDate(3, new Date(System.currentTimeMillis()));
- statement.setDate(4, new Date(System.currentTimeMillis()));
- statement.setBoolean(5, false);
- // 执行
- statement.executeUpdate();
- // 提交事务
- connection.commit();
- } finally {
- // 释放资源
- JDBCUtils.release(connection, statement, null);
- }
- }
+ /**
+ * 测试添加用户
+ * @throws SQLException
+ */
+ @Test
+ public void save() throws SQLException {
+ // 创建sql
+ String sql = "insert into demo_user values(null,?,?,?,?,?)";
+ Connection connection = null;
+ PreparedStatement statement = null;
+ try {
+ // 获得连接
+ connection = JDBCUtils.getConnection();
+ // 开启事务设置非自动提交
+ connection.setAutoCommit(false);
+ // 获得Statement对象
+ statement = connection.prepareStatement(sql);
+ // 设置参数
+ statement.setString(1, "zzf003");
+ statement.setInt(2, 18);
+ statement.setDate(3, new Date(System.currentTimeMillis()));
+ statement.setDate(4, new Date(System.currentTimeMillis()));
+ statement.setBoolean(5, false);
+ // 执行
+ statement.executeUpdate();
+ // 提交事务
+ connection.commit();
+ } finally {
+ // 释放资源
+ JDBCUtils.release(connection, statement, null);
+ }
+ }
- /**
- * 测试更新用户
- * @throws SQLException
- */
- @Test
- public void update() throws SQLException {
- // 创建sql
- String sql = "update demo_user set age = ?,gmt_modified = ? where name = ?";
- Connection connection = null;
- PreparedStatement statement = null;
- try {
- // 获得连接
- connection = JDBCUtils.getConnection();
- // 开启事务
- connection.setAutoCommit(false);
- // 获得Statement对象
- statement = connection.prepareStatement(sql);
- // 设置参数
- statement.setInt(1, 19);
- statement.setDate(2, new Date(System.currentTimeMillis()));
- statement.setString(3, "zzf003");
- // 执行
- statement.executeUpdate();
- // 提交事务
- connection.commit();
- } finally {
- // 释放资源
- JDBCUtils.release(connection, statement, null);
- }
- }
+ /**
+ * 测试更新用户
+ * @throws SQLException
+ */
+ @Test
+ public void update() throws SQLException {
+ // 创建sql
+ String sql = "update demo_user set age = ?,gmt_modified = ? where name = ?";
+ Connection connection = null;
+ PreparedStatement statement = null;
+ try {
+ // 获得连接
+ connection = JDBCUtils.getConnection();
+ // 开启事务
+ connection.setAutoCommit(false);
+ // 获得Statement对象
+ statement = connection.prepareStatement(sql);
+ // 设置参数
+ statement.setInt(1, 19);
+ statement.setDate(2, new Date(System.currentTimeMillis()));
+ statement.setString(3, "zzf003");
+ // 执行
+ statement.executeUpdate();
+ // 提交事务
+ connection.commit();
+ } finally {
+ // 释放资源
+ JDBCUtils.release(connection, statement, null);
+ }
+ }
- /**
- * 测试查找用户
- * @throws SQLException
- */
- @Test
- public void findAll() throws SQLException {
- // 创建sql
- String sql = "select * from demo_user where deleted = false";
- Connection connection = null;
- PreparedStatement statement = null;
- ResultSet resultSet = null;
- try {
- // 获得连接
- connection = JDBCUtils.getConnection();
- // 获得Statement对象
- statement = connection.prepareStatement(sql);
- // 执行
- resultSet = statement.executeQuery();
- // 遍历结果集
- while(resultSet.next()) {
- String name = resultSet.getString(2);
- int age = resultSet.getInt(3);
- System.out.println("用户名:" + name + ",年龄:" + age);
- }
- } finally {
- // 释放资源
- JDBCUtils.release(connection, statement, resultSet);
- }
- }
+ /**
+ * 测试查找用户
+ * @throws SQLException
+ */
+ @Test
+ public void findAll() throws SQLException {
+ // 创建sql
+ String sql = "select * from demo_user where deleted = false";
+ Connection connection = null;
+ PreparedStatement statement = null;
+ ResultSet resultSet = null;
+ try {
+ // 获得连接
+ connection = JDBCUtils.getConnection();
+ // 获得Statement对象
+ statement = connection.prepareStatement(sql);
+ // 执行
+ resultSet = statement.executeQuery();
+ // 遍历结果集
+ while(resultSet.next()) {
+ String name = resultSet.getString(2);
+ int age = resultSet.getInt(3);
+ System.out.println("用户名:" + name + ",年龄:" + age);
+ }
+ } finally {
+ // 释放资源
+ JDBCUtils.release(connection, statement, resultSet);
+ }
+ }
+
+ /**
+ * 测试删除用户
+ */
+ @Test
+ public void delete() throws Exception {
+ // 创建sql
+ String sql = "delete from demo_user where name = ?";
+ Connection connection = null;
+ PreparedStatement statement = null;
+ try {
+ // 获得连接
+ connection = JDBCUtils.getConnection();
+ // 设置非自动提交
+ connection.setAutoCommit(false);
+ // 获得Statement对象
+ statement = connection.prepareStatement(sql);
+ // 设置参数
+ statement.setString(1, "zzf003");
+ // 执行
+ statement.executeUpdate();
+ // 提交事务
+ connection.commit();
+ } finally {
+ // 释放资源
+ JDBCUtils.release(connection, statement, null);
+ }
+ }
- /**
- * 测试删除用户
- */
- @Test
- public void delete() throws Exception {
- // 创建sql
- String sql = "delete from demo_user where name = ?";
- Connection connection = null;
- PreparedStatement statement = null;
- try {
- // 获得连接
- connection = JDBCUtils.getConnection();
- // 设置非自动提交
- connection.setAutoCommit(false);
- // 获得Statement对象
- statement = connection.prepareStatement(sql);
- // 设置参数
- statement.setString(1, "zzf003");
- // 执行
- statement.executeUpdate();
- // 提交事务
- connection.commit();
- } finally {
- // 释放资源
- JDBCUtils.release(connection, statement, null);
- }
- }
-
}
diff --git a/src/test/java/cn/zzs/dbcp/BasicManagedDataSourceTest.java b/src/test/java/cn/zzs/dbcp/BasicManagedDataSourceTest.java
index 78f061c..b2db09d 100644
--- a/src/test/java/cn/zzs/dbcp/BasicManagedDataSourceTest.java
+++ b/src/test/java/cn/zzs/dbcp/BasicManagedDataSourceTest.java
@@ -17,91 +17,78 @@ import com.atomikos.icatch.jta.UserTransactionManager;
*/
public class BasicManagedDataSourceTest {
- public BasicManagedDataSource getBasicManagedDataSource(
- TransactionManager transactionManager,
- String url,
- String username,
- String password) {
- BasicManagedDataSource basicManagedDataSource = new BasicManagedDataSource();
- basicManagedDataSource.setTransactionManager(transactionManager);
- basicManagedDataSource.setUrl(url);
- basicManagedDataSource.setUsername(username);
- basicManagedDataSource.setPassword(password);
- basicManagedDataSource.setDefaultAutoCommit(false);
- basicManagedDataSource.setXADataSource("com.mysql.cj.jdbc.MysqlXADataSource");
- return basicManagedDataSource;
- }
+ public BasicManagedDataSource getBasicManagedDataSource(TransactionManager transactionManager, String url, String username, String password) {
+ BasicManagedDataSource basicManagedDataSource = new BasicManagedDataSource();
+ basicManagedDataSource.setTransactionManager(transactionManager);
+ basicManagedDataSource.setUrl(url);
+ basicManagedDataSource.setUsername(username);
+ basicManagedDataSource.setPassword(password);
+ basicManagedDataSource.setDefaultAutoCommit(false);
+ basicManagedDataSource.setXADataSource("com.mysql.cj.jdbc.MysqlXADataSource");
+ return basicManagedDataSource;
+ }
- @Test
- public void test01() throws Exception {
- // 获得事务管理器
- TransactionManager transactionManager = new UserTransactionManager();
-
- // 获取第一个数据库的数据源
- BasicManagedDataSource basicManagedDataSource1 = getBasicManagedDataSource(
- transactionManager,
- "jdbc:mysql://localhost:3306/github_demo?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=true",
- "root",
- "root");
- // 注意,这一步非常重要
- basicManagedDataSource1.setDefaultCatalog("github_demo");
-
- // 获取第二个数据库的数据源
- BasicManagedDataSource basicManagedDataSource2 = getBasicManagedDataSource(
- transactionManager,
- "jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=true",
- "zzf",
- "zzf");
- // 注意,这一步非常重要
- basicManagedDataSource1.setDefaultCatalog("test");
-
-
- Connection connection1 = null;
- Statement statement1 = null;
- Connection connection2 = null;
- Statement statement2 = null;
- transactionManager.begin();
- try {
- // 获取连接并进行数据库操作,这里会将会将XAResource注册到当前线程的XA事务对象
- /**
- * XA START xid1;-- 启动一个事务,并使之为active状态
- */
- connection1 = basicManagedDataSource1.getConnection();
- statement1 = connection1.createStatement();
- /**
- * update github_demo.demo_user set deleted = 1 where id = '1'; -- 事务中的语句
- */
- boolean result1 = statement1.execute("update github_demo.demo_user set deleted = 1 where id = '1'");
- System.out.println(result1);
-
- /**
- * XA START xid2;-- 启动一个事务,并使之为active状态
- */
- connection2 = basicManagedDataSource2.getConnection();
- statement2 = connection2.createStatement();
- /**
- * update test.demo_user set deleted = 1 where id = '1'; -- 事务中的语句
- */
- boolean result2 = statement2.execute("update test.demo_user set deleted = 1 where id = '1'");
- System.out.println(result2);
-
- /**
- * 当这执行以下语句:
- * XA END xid1; -- 把事务置为idle状态
- * XA PREPARE xid1; -- 把事务置为prepare状态
- * XA END xid2; -- 把事务置为idle状态
- * XA PREPARE xid2; -- 把事务置为prepare状态
- * XA COMMIT xid1; -- 提交事务
- * XA COMMIT xid2; -- 提交事务
- */
- transactionManager.commit();
- } catch(Exception e) {
- e.printStackTrace();
- } finally {
- statement1.close();
- statement2.close();
- connection1.close();
- connection2.close();
- }
- }
+ @Test
+ public void test01() throws Exception {
+ // 获得事务管理器
+ TransactionManager transactionManager = new UserTransactionManager();
+
+ // 获取第一个数据库的数据源
+ BasicManagedDataSource basicManagedDataSource1 = getBasicManagedDataSource(transactionManager, "jdbc:mysql://localhost:3306/github_demo?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=true", "root", "root");
+ // 注意,这一步非常重要
+ basicManagedDataSource1.setDefaultCatalog("github_demo");
+
+ // 获取第二个数据库的数据源
+ BasicManagedDataSource basicManagedDataSource2 = getBasicManagedDataSource(transactionManager, "jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=true", "zzf", "zzf");
+ // 注意,这一步非常重要
+ basicManagedDataSource1.setDefaultCatalog("test");
+
+ Connection connection1 = null;
+ Statement statement1 = null;
+ Connection connection2 = null;
+ Statement statement2 = null;
+ transactionManager.begin();
+ try {
+ // 获取连接并进行数据库操作,这里会将会将XAResource注册到当前线程的XA事务对象
+ /**
+ * XA START xid1;-- 启动一个事务,并使之为active状态
+ */
+ connection1 = basicManagedDataSource1.getConnection();
+ statement1 = connection1.createStatement();
+ /**
+ * update github_demo.demo_user set deleted = 1 where id = '1'; -- 事务中的语句
+ */
+ boolean result1 = statement1.execute("update github_demo.demo_user set deleted = 1 where id = '1'");
+ System.out.println(result1);
+
+ /**
+ * XA START xid2;-- 启动一个事务,并使之为active状态
+ */
+ connection2 = basicManagedDataSource2.getConnection();
+ statement2 = connection2.createStatement();
+ /**
+ * update test.demo_user set deleted = 1 where id = '1'; -- 事务中的语句
+ */
+ boolean result2 = statement2.execute("update test.demo_user set deleted = 1 where id = '1'");
+ System.out.println(result2);
+
+ /**
+ * 当这执行以下语句:
+ * XA END xid1; -- 把事务置为idle状态
+ * XA PREPARE xid1; -- 把事务置为prepare状态
+ * XA END xid2; -- 把事务置为idle状态
+ * XA PREPARE xid2; -- 把事务置为prepare状态
+ * XA COMMIT xid1; -- 提交事务
+ * XA COMMIT xid2; -- 提交事务
+ */
+ transactionManager.commit();
+ } catch(Exception e) {
+ e.printStackTrace();
+ } finally {
+ statement1.close();
+ statement2.close();
+ connection1.close();
+ connection2.close();
+ }
+ }
}