JdbcUtils最终版(使用common-dbutil、编写TxQueryRunner、处理多线程)

落日映苍穹つ 2021-06-15 20:36 319阅读 0赞

我自己都很懵逼,不知道自己干了啥。

好像主要是为了分离service层和dao层的工作,还得让他们使用同一个connection。然后编写了一个TxqueryRunner进一步封装整合,最后还处理了多线程并发访问的问题。
我要疯了。
先把代码贴上,留着慢慢消化。

JDBCUtils:

  1. package com.veeja.jdbc;
  2. //import java.io.InputStream;
  3. import java.sql.Connection;
  4. //import java.sql.DriverManager;
  5. import java.sql.ResultSet;
  6. import java.sql.SQLException;
  7. import java.sql.Statement;
  8. //import java.util.Properties;
  9. import javax.sql.DataSource;
  10. import com.mchange.v2.c3p0.ComboPooledDataSource;
  11. public class JDBCUtils {
  12. // static String driverClass = null;
  13. // static String url = null;
  14. // static String user = null;
  15. // static String passwd = null;
  16. //
  17. // static {
  18. // try {
  19. // // 1. 创建一个属性配置对象
  20. // Properties properties = new Properties();
  21. //
  22. // // 2. 把properties文件转化为inputstream流
  23. //
  24. // // 方法一:如果把properties文件放在工程的根目录下,可以使用下面的语句读取这个文件
  25. // // InputStream is = new FileInputStream("jdbc.properties");
  26. //
  27. // // 方法二:使用类加载器,去读取src目录下的资源文件
  28. // InputStream is = JDBCUtils.class.getClassLoader()
  29. // .getResourceAsStream("jdbc.properties");
  30. //
  31. // // 3. 导入输入流。
  32. // properties.load(is);
  33. //
  34. // // 4. 读取属性
  35. // driverClass = properties.getProperty("driverClass");
  36. // url = properties.getProperty("url");
  37. // user = properties.getProperty("user");
  38. // passwd = properties.getProperty("passwd");
  39. // } catch (Exception e) {
  40. // e.printStackTrace();
  41. // }
  42. // }
  43. // /**
  44. // * 注册驱动
  45. // */
  46. // private static void registerDriver() {
  47. // // DriverManager.registerDriver(new com.mysql.jdbc.Driver());
  48. // try {
  49. // Class.forName(driverClass);
  50. // } catch (ClassNotFoundException e) {
  51. // e.printStackTrace();
  52. // }
  53. // }
  54. public static ComboPooledDataSource dataSource = new ComboPooledDataSource();
  55. /** * 返回连接处建立的数据库连接 * * @return * @throws SQLException */
  56. public static Connection getConnection() throws SQLException {
  57. Connection connection = tl.get();
  58. // 当connection不为null的时候表示事务已经开始了。
  59. if (connection != null)
  60. return connection;
  61. return dataSource.getConnection();
  62. // Connection conn = null;
  63. // try {
  64. // // 2. 建立连接 参数1:协议+访问数据库 参数2:用户名 参数3:密码
  65. // conn = DriverManager.getConnection(url, user, passwd);
  66. // } catch (Exception e) {
  67. // e.printStackTrace();
  68. // }
  69. // System.out.println("获取数据库连接connection");
  70. // return conn;
  71. }
  72. /** * 返回连接池对象 */
  73. public DataSource getDataSource() {
  74. return dataSource;
  75. }
  76. /** * 释放资源 * * @param conn * @param st * @param rs */
  77. public static void release(Connection connection, Statement statement,
  78. ResultSet resultSet) {
  79. closeRs(resultSet);
  80. closeSt(statement);
  81. closeConn(connection);
  82. }
  83. // 释放ResultSet对象
  84. private static void closeRs(ResultSet resultSet) {
  85. System.out.println("释放ResultSet对象");
  86. try {
  87. if (resultSet != null) {
  88. resultSet.close();
  89. }
  90. } catch (SQLException e) {
  91. e.printStackTrace();
  92. } finally {
  93. resultSet = null;
  94. }
  95. }
  96. // 释放Statement对象
  97. private static void closeSt(Statement statement) {
  98. System.out.println("释放Statement对象。");
  99. try {
  100. if (statement != null) {
  101. statement.close();
  102. }
  103. } catch (SQLException e) {
  104. e.printStackTrace();
  105. } finally {
  106. statement = null;
  107. }
  108. }
  109. // 释放数据库连接。
  110. private static void closeConn(Connection connection) {
  111. System.out.println("释放数据库连接。");
  112. try {
  113. if (connection != null) {
  114. connection.close();
  115. }
  116. } catch (SQLException e) {
  117. e.printStackTrace();
  118. } finally {
  119. connection = null;
  120. }
  121. }
  122. // 事务专用连接!
  123. private static ThreadLocal<Connection> tl = new ThreadLocal<Connection>();
  124. /** * 开启事务,获取一个connection,设置它的setAutoCommit(false)。 还要保证DAO中使用的连接使我们刚刚创建的。 * * @throws SQLException */
  125. public static void beginTransaction() throws SQLException {
  126. Connection connection = tl.get();
  127. if (connection != null) {
  128. throw new SQLException("事务已经开启了,请不要重复开启事务!");
  129. }
  130. // 创建一个connection,设置为手动提交
  131. // 把这个connection给dao用
  132. // 还要让commitTransaction或者rollbackTransaction可以获取到。
  133. connection = getConnection();
  134. connection.setAutoCommit(false);
  135. tl.set(connection);// 把当前线程的连接保存起来
  136. }
  137. /** * 提交事务,获取beginTransaction提供的Connection,然后调用commit方法 * * @throws SQLException */
  138. public static void commitTransaction() throws SQLException {
  139. Connection connection = tl.get();// 获取当前线程的连接
  140. if (connection == null) {
  141. throw new SQLException("事务还没有开启,无法提交事务!");
  142. }
  143. connection.commit();
  144. connection.close();
  145. // 把它设置为null,表示事务已经结束了。再次调用getConnection()返回的就不是connection了
  146. // connection = null;
  147. tl.remove();// 从tl中移除了
  148. }
  149. /** * 回滚事务,获取beginTransaction提供的Connection,然后调用rollback方法 * * @throws SQLException */
  150. public static void roolbackTransaction() throws SQLException {
  151. Connection connection = tl.get();// 获取当前线程的连接
  152. if (connection == null) {
  153. throw new SQLException("事务还没有开启,无法回滚事务!");
  154. }
  155. connection.rollback();
  156. connection.close();
  157. // 把它设置为null,表示事务已经结束了。再次调用getConnection()返回的就不是connection了
  158. // connection = null;
  159. tl.remove();
  160. }
  161. /** * 释放连接 * * @param connection * @throws SQLException */
  162. public static void releaseConnection(Connection connection)
  163. throws SQLException {
  164. Connection connection1 = tl.get();
  165. /** * 判断是否为事务专用连接,如果是,就不关闭。 如果是事务专用连接,那么就要关闭连接。 */
  166. // 如果connection=null,说明现在没有事务,那么connection一定不是事务专用连接
  167. if (connection1 == null) {
  168. connection1.close();
  169. }
  170. // 如果connection!=null ,说明事务开启了,那么需要判断是否为事务专用连接.
  171. // 如果参数连接与connection是否相等,如果不相等,说明不是事务专用连接
  172. if (connection1 != null) {
  173. connection1.close();
  174. }
  175. }
  176. }

TxQueryRunner

覆写父类中所有没有使用connection的方法。

  1. package com.veeja.jdbc;
  2. import java.sql.Connection;
  3. import java.sql.SQLException;
  4. import org.apache.commons.dbutils.QueryRunner;
  5. import org.apache.commons.dbutils.ResultSetHandler;
  6. /** * * 这个类中的方法,自己来处理连接的问题 . 无需外界传递! * 通过JdbcUtils.getConnection()得到连接! * 有可能是事务连接,也可能是普通的连接! * JdbcUtils.releaseConnection()完成对连接的释放! 如果是普通连接,关闭之! * * @author Veeja.Liu * @emial veejaliu@gmail.com * */
  7. public class TxQueryRunner extends QueryRunner {
  8. public int[] batch(String sql, Object[][] params) throws SQLException {
  9. // 1.得到连接
  10. // 2.执行父类方法,传递连接对象
  11. // 3. 释放连接
  12. // 4. 返回值
  13. Connection connection = JDBCUtils.getConnection();
  14. int[] result = super.batch(connection, sql, params);
  15. JDBCUtils.releaseConnection(connection);
  16. return result;
  17. }
  18. public Object query(String sql, Object param, ResultSetHandler rsh)
  19. throws SQLException {
  20. // 1.得到连接
  21. // 2.执行父类方法,传递连接对象
  22. // 3. 释放连接
  23. // 4. 返回值
  24. Connection connection = JDBCUtils.getConnection();
  25. Object result = super.query(connection, sql, param, rsh);
  26. JDBCUtils.releaseConnection(connection);
  27. return result;
  28. }
  29. public Object query(String sql, Object[] params, ResultSetHandler rsh)
  30. throws SQLException {
  31. // 1.得到连接
  32. // 2.执行父类方法,传递连接对象
  33. // 3. 释放连接
  34. // 4. 返回值
  35. Connection connection = JDBCUtils.getConnection();
  36. Object result = super.query(connection, sql, params, rsh);
  37. JDBCUtils.releaseConnection(connection);
  38. return result;
  39. }
  40. public Object query(String sql, ResultSetHandler rsh, Object[] params)
  41. throws SQLException {
  42. // 1.得到连接
  43. // 2.执行父类方法,传递连接对象
  44. // 3. 释放连接
  45. // 4. 返回值
  46. Connection connection = JDBCUtils.getConnection();
  47. Object result = super.query(connection, sql, rsh, params);
  48. JDBCUtils.releaseConnection(connection);
  49. return result;
  50. }
  51. public Object query(String sql, ResultSetHandler rsh) throws SQLException {
  52. // 1.得到连接
  53. // 2.执行父类方法,传递连接对象
  54. // 3. 释放连接
  55. // 4. 返回值
  56. Connection connection = JDBCUtils.getConnection();
  57. Object result = super.query(connection, sql, rsh);
  58. JDBCUtils.releaseConnection(connection);
  59. return result;
  60. }
  61. public int update(String sql) throws SQLException {
  62. // 1.得到连接
  63. // 2.执行父类方法,传递连接对象
  64. // 3. 释放连接
  65. // 4. 返回值
  66. Connection connection = JDBCUtils.getConnection();
  67. int result = super.update(connection, sql);
  68. JDBCUtils.releaseConnection(connection);
  69. return result;
  70. }
  71. public int update(String sql, Object param) throws SQLException {
  72. // 1.得到连接
  73. // 2.执行父类方法,传递连接对象
  74. // 3. 释放连接
  75. // 4. 返回值
  76. Connection connection = JDBCUtils.getConnection();
  77. int result = super.update(connection, sql, param);
  78. JDBCUtils.releaseConnection(connection);
  79. return result;
  80. }
  81. public int update(String sql, Object[] params) throws SQLException {
  82. // 1.得到连接
  83. // 2.执行父类方法,传递连接对象
  84. // 3. 释放连接
  85. // 4. 返回值
  86. Connection connection = JDBCUtils.getConnection();
  87. int result = super.update(connection, sql, params);
  88. JDBCUtils.releaseConnection(connection);
  89. return result;
  90. }
  91. }

Dao

这里的测试并不规范。

  1. package com.veeja.jdbc;
  2. import java.sql.SQLException;
  3. import org.apache.commons.dbutils.QueryRunner;
  4. public class UserDao {
  5. public static void main(String[] args) throws SQLException {
  6. Integer id = new Integer(1);
  7. String name = "aaaa";
  8. update(name, id);
  9. }
  10. public static void update(String name, Integer id) throws SQLException {
  11. QueryRunner qRunner = new TxQueryRunner();
  12. String sql = "update student set name = ? where id = ?";
  13. Object[] params = { name, id };
  14. qRunner.update(sql, params);
  15. }
  16. }

发表评论

表情:
评论列表 (有 0 条评论,319人围观)

还没有评论,来说两句吧...

相关阅读