1 Apache DBUtils框架

1.1 DBUtils简介

  • commons-dbutils是Apache组织提供的一个开源JDBC工具类库,它是对JDBC的简单封装,学习成本非常低,并且使用dbutils能极大的简化jdbc编码的工作量,同时也不会影响程序的性能。因此dbutils成为很多不喜欢Hibernate的公司的首选。

1.2 DBUtilsAPI简介

1.2.1 DbUtils类(没用)

  • DbUtils类:提供如关闭连接、装载JDBC驱动程序等常规工作的工具类,里面的所有方法都是静态的。主要方法如下:
  • Dbutils类提供了3个重载的关闭的方法,这些方法检查所提供的参数是不是null,如果不是,那么它们就关闭Connection、Statement和resultSet。
  1. public static void close(Connection conn) throws SQLException {
  2. if (conn != null) {
  3. conn.close();
  4. }
  5.  
  6. }
  1. public static void close(ResultSet rs) throws SQLException {
  2. if (rs != null) {
  3. rs.close();
  4. }
  5.  
  6. }
  1. public static void close(Statement stmt) throws SQLException {
  2. if (stmt != null) {
  3. stmt.close();
  4. }
  5.  
  6. }
  • DbUtils类提供的closeQuietly()这一类方法不仅仅能在Connection、Statement和ResultSet为null的情况下避免关闭,还能隐藏一些在程序中抛出的SQLException。
  1. public static void closeQuietly(Connection conn) {
  2. try {
  3. close(conn);
  4. } catch (SQLException var2) {
  5. ;
  6. }
  7.  
  8. }
  1. public static void closeQuietly(Connection conn, Statement stmt, ResultSet rs) {
  2. try {
  3. closeQuietly(rs);
  4. } finally {
  5. try {
  6. closeQuietly(stmt);
  7. } finally {
  8. closeQuietly(conn);
  9. }
  10. }
  11.  
  12. }
  1. public static void closeQuietly(ResultSet rs) {
  2. try {
  3. close(rs);
  4. } catch (SQLException var2) {
  5. ;
  6. }
  7.  
  8. }
  1. public static void closeQuietly(Statement stmt) {
  2. try {
  3. close(stmt);
  4. } catch (SQLException var2) {
  5. ;
  6. }
  7.  
  8. }
  • DbUtils类提供的commitAndCloseQuietly()用来提交连接,然后关闭连接,并且在关闭连接的时候不抛出SQLException。
  1. public static void commitAndClose(Connection conn) throws SQLException {
  2. if (conn != null) {
  3. try {
  4. conn.commit();
  5. } finally {
  6. conn.close();
  7. }
  8. }
  9.  
  10. }
  11.  
  12. public static void commitAndCloseQuietly(Connection conn) {
  13. try {
  14. commitAndClose(conn);
  15. } catch (SQLException var2) {
  16. ;
  17. }
  18.  
  19. }
  • DbUtils类提供的loadDriver()这一方法装载并注册JDBC程序,如果成功就返回true。使用该方法,你不需要捕捉ClassNotFoundException。
  1. public static boolean loadDriver(String driverClassName) {
  2. return loadDriver(DbUtils.class.getClassLoader(), driverClassName);
  3. }
  4.  
  5. public static boolean loadDriver(ClassLoader classLoader, String driverClassName) {
  6. try {
  7. classLoader.loadClass(driverClassName).newInstance();
  8. return true;
  9. } catch (IllegalAccessException var3) {
  10. return true;
  11. } catch (Exception var4) {
  12. return false;
  13. }
  14. }

1.2.2 QueryRunner类

  • 该类简化了SQL查询,它和ResultSetHandler组合在一起使用可以完成大部分的数据库操作,能够大大的减少编码量。
  • QueryRunner类提供了两个构造方法:
  1. public QueryRunner(DataSource ds) {
  2. super(ds);
  3. }
  1. public QueryRunner() {
  2. }
  • QueryRunner类常用的方法如下:
  • 执行一个查询操作,在这个查询中,对象数组中的每个元素值被用来作为查询语句的置换参数。该方法会自行处理PreparedStatement和ResultSet的创建和关闭。(可用来进行事务处理)
  1. public <T> T query(Connection conn, String sql, ResultSetHandler<T> rsh, Object... params) throws SQLException {
  2. return this.query(conn, false, sql, rsh, params);
  3. }
  • 执行一个查询操作,在这个查询中,对象数组中的每个元素之被用来作为查询语句的置换参数。该方法会自行处理PreparedStatement和ResultSet的创建和关闭,和上面不同的是,这个方法是从构造方法传入的DataSource对象,获取连接。(依赖于数据库对事务的管理)
  1. public <T> T query(String sql, ResultSetHandler<T> rsh, Object... params) throws SQLException {
  2. Connection conn = this.prepareConnection();
  3. return this.query(conn, true, sql, rsh, params);
  4. }
  • 用来执行一个更新(插入、删除和更新)的操作。(可以对事务控制)
  1. public int update(Connection conn, String sql, Object param) throws SQLException {
  2. return this.update(conn, false, sql, param);
  3. }
  • 用来执行一个更新(插入、删除和更新)的操作。(依赖于底层数据库对事务的管理)
  1. public int update(String sql, Object... params) throws SQLException {
  2. Connection conn = this.prepareConnection();
  3. return this.update(conn, true, sql, params);
  4. }
  • 示例:增加、删除、更新
  • user.sql
  1. USE test;
  2. CREATE TABLE USER(
  3. id INT PRIMARY KEY AUTO_INCREMENT,
  4. NAME ) ,
  5. PASSWORD ), email varchar(20), birthday DATE
  6. );
  • c3p0-config.xml
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <c3p0-config>
  3. <default-config>
  4. <property name="driverClass">com.mysql.jdbc.Driver</property>
  5. <property name="jdbcUrl">jdbc:mysql:///test</property>
  6. <property name="user">root</property>
  7. <property name="password">root</property>
  8. <property name="initialPoolSize">10</property>
  9. <property name="maxIdleTime">30</property>
  10. <property name="maxPoolSize">100</property>
  11. <property name="minPoolSize">10</property>
  12. <property name="maxStatements">200</property>
  13. </default-config>
  14.  
  15. </c3p0-config>
  • C3P0util.java
  1. package com.util;
  2.  
  3. import com.mchange.v2.c3p0.ComboPooledDataSource;
  4.  
  5. import javax.sql.DataSource;
  6. import java.sql.Connection;
  7. import java.sql.SQLException;
  8.  
  9. public class C3P0util {
  10. private static ComboPooledDataSource dataSource = new ComboPooledDataSource();
  11.  
  12. public static DataSource getDataSource(){
  13. return dataSource;
  14. }
  15.  
  16. public static Connection getConnection(){
  17. try {
  18. return dataSource.getConnection();
  19. } catch (SQLException e) {
  20. throw new RuntimeException(e);
  21. }
  22. }
  23.  
  24. }
  • DbUtilTest.java
  1. package com.test;
  2.  
  3. import com.util.C3P0util;
  4. import org.apache.commons.dbutils.QueryRunner;
  5. import org.junit.Test;
  6.  
  7. import java.sql.SQLException;
  8. import java.util.Date;
  9.  
  10. public class DbUtilTest {
  11. private QueryRunner queryRunner = new QueryRunner(C3P0util.getDataSource());
  12.  
  13. /**
  14. * 插入
  15. * @throws SQLException
  16. */
  17. @Test
  18. public void testAdd() throws SQLException {
  19. queryRunner.update("insert into user values(null,?,?,?,?)","张三","admin","admin@163.com",new Date());
  20. }
  21.  
  22. /**
  23. * 更新
  24. */
  25. @Test
  26. public void testUpdate() throws SQLException {
  27. queryRunner.update("update user set name = ? where id = ?","李四",1);
  28. }
  29.  
  30. @Test
  31. public void testDelete() throws SQLException{
  32. queryRunner.update("delete from user where id = ?",1);
  33. }
  34.  
  35. }

1.2.3 ResultSetHandler接口

  • 该接口用于处理java.sql.ResultSet,将数据按照要求转换为另一种形式。
  • ResultSetHandler接口提供了一个单独的方法:Objject handle(java.sql.ResultSet rs)
  1. package org.apache.commons.dbutils;
  2.  
  3. import java.sql.ResultSet;
  4. import java.sql.SQLException;
  5.  
  6. public interface ResultSetHandler<T> {
  7. T handle(ResultSet var1) throws SQLException;
  8. }

1.2.4 ResultSetHandler接口的实现类

  • BeanHandler:将结果集中的第一行数据封装到一个对应的JavaBean对象中。
  • BeanListHandler:将结果集中的每一行数据都封装到一个对应的JavaBean对象中,存放到List集合中。
  • ScalarHandler:返回一行一列的数据,如select count(*) from user。
  • 示例:
  • user.sql
  1. use test;
  2. create table user(
  3. id int primary key auto_increment,
  4. name ) ,
  5. password ),
  6. email )
  7. birthday date
  8. );
  9.  
  10. insert into user values (null,'张三','abc','adc@163.com','2017-11-11');
  11. insert into user values (null,'李四','bcd','bcd@163.com','2017-11-11');
  12. insert into user values (null,'王五','cde','cde@163.com','2017-11-11');
  • c3p0-config.xml
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <c3p0-config>
  3. <default-config>
  4. <property name="driverClass">com.mysql.jdbc.Driver</property>
  5. <property name="jdbcUrl">jdbc:mysql:///test</property>
  6. <property name="user">root</property>
  7. <property name="password">root</property>
  8. <property name="initialPoolSize">10</property>
  9. <property name="maxIdleTime">30</property>
  10. <property name="maxPoolSize">100</property>
  11. <property name="minPoolSize">10</property>
  12. <property name="maxStatements">200</property>
  13. </default-config>
  14.  
  15. </c3p0-config>
  • C3P0util.java
  1. package com.util;
  2.  
  3. import com.mchange.v2.c3p0.ComboPooledDataSource;
  4.  
  5. import javax.sql.DataSource;
  6. import java.sql.Connection;
  7. import java.sql.SQLException;
  8.  
  9. public class C3P0util {
  10. private static ComboPooledDataSource dataSource = new ComboPooledDataSource();
  11.  
  12. public static DataSource getDataSource(){
  13. return dataSource;
  14. }
  15.  
  16. public static Connection getConnection(){
  17. try {
  18. return dataSource.getConnection();
  19. } catch (SQLException e) {
  20. throw new RuntimeException(e);
  21. }
  22. }
  23.  
  24. }
  • User.java
  1. package com.domain;
  2.  
  3. import java.io.Serializable;
  4. import java.util.Date;
  5.  
  6. public class User implements Serializable {
  7. private Integer id;
  8. private String name;
  9. private String password;
  10. private String email;
  11. private Date birthday;
  12.  
  13. public Integer getId() {
  14. return id;
  15. }
  16.  
  17. public void setId(Integer id) {
  18. this.id = id;
  19. }
  20.  
  21. public String getName() {
  22. return name;
  23. }
  24.  
  25. public void setName(String name) {
  26. this.name = name;
  27. }
  28.  
  29. public String getPassword() {
  30. return password;
  31. }
  32.  
  33. public void setPassword(String password) {
  34. this.password = password;
  35. }
  36.  
  37. public String getEmail() {
  38. return email;
  39. }
  40.  
  41. public void setEmail(String email) {
  42. this.email = email;
  43. }
  44.  
  45. public Date getBirthday() {
  46. return birthday;
  47. }
  48.  
  49. public void setBirthday(Date birthday) {
  50. this.birthday = birthday;
  51. }
  52.  
  53. @Override
  54. public String toString() {
  55. return "User{" +
  56. "id=" + id +
  57. ", name='" + name + '\'' +
  58. ", password='" + password + '\'' +
  59. ", email='" + email + '\'' +
  60. ", birthday=" + birthday +
  61. '}';
  62. }
  63. }
  • DbUtil.java
  1. package com.test;
  2.  
  3. import com.domain.User;
  4. import com.util.C3P0util;
  5. import org.apache.commons.dbutils.QueryRunner;
  6. import org.apache.commons.dbutils.handlers.BeanHandler;
  7. import org.apache.commons.dbutils.handlers.BeanListHandler;
  8. import org.apache.commons.dbutils.handlers.ScalarHandler;
  9. import org.junit.Test;
  10.  
  11. import java.sql.SQLException;
  12. import java.util.List;
  13.  
  14. public class DbUtilTest {
  15. private QueryRunner queryRunner = new QueryRunner(C3P0util.getDataSource());
  16.  
  17. /**
  18. * 将查询的数据封装到javabean中,不管多少个记录,只返回第一行的记录
  19. */
  20. @Test
  21. public void testQueryOne() throws SQLException {
  22. User user = queryRunner.query("select * from user",new BeanHandler<User>(User.class));
  23. System.out.println(user);
  24. }
  25.  
  26. /**
  27. * 将查询的数据封装到Javabean中,返回的是List集合
  28. * @throws SQLException
  29. */
  30. @Test
  31. public void testQueryAll() throws SQLException{
  32. List<User> users = queryRunner.query("select * from user",new BeanListHandler<User>(User.class));
  33. for(User u:users){
  34. System.out.println(u);
  35. }
  36. }
  37.  
  38. @Test
  39. public void testCount() throws SQLException{
  40. Object count = queryRunner.query("select count(*) from user",new ScalarHandler());
  41. System.out.println(count);
  42. }
  43.  
  44. }

2 在实际开发中事务如何管理

  • sql脚本
  1. USE test;
  2. CREATE TABLE account(
  3. id INT PRIMARY KEY AUTO_INCREMENT,
  4. NAME ),
  5. money DOUBLE
  6.  
  7. );
  8.  
  9. );
  10. );
  11. );

2.1 version1

  • pom.xml
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!--
  3. Licensed to the Apache Software Foundation (ASF) under one
  4. or more contributor license agreements. See the NOTICE file
  5. distributed with this work for additional information
  6. regarding copyright ownership. The ASF licenses this file
  7. to you under the Apache License, Version 2.0 (the
  8. "License"); you may not use this file except in compliance
  9. with the License. You may obtain a copy of the License at
  10.  
  11. http://www.apache.org/licenses/LICENSE-2.0
  12.  
  13. Unless required by applicable law or agreed to in writing,
  14. software distributed under the License is distributed on an
  15. "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  16. KIND, either express or implied. See the License for the
  17. specific language governing permissions and limitations
  18. under the License.
  19. -->
  20. <!-- $Id: pom.xml 642118 2008-03-28 08:04:16Z reinhard $ -->
  21. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  22.  
  23. <modelVersion>4.0.0</modelVersion>
  24. <packaging>war</packaging>
  25.  
  26. <name>Tx</name>
  27. <groupId>com.xuweiwei</groupId>
  28. <artifactId>Tx</artifactId>
  29. <version>1.0-SNAPSHOT</version>
  30.  
  31. <build>
  32. <plugins>
  33. <plugin>
  34. <groupId>org.mortbay.jetty</groupId>
  35. <artifactId>maven-jetty-plugin</artifactId>
  36. <version>6.1.7</version>
  37. <configuration>
  38. <connectors>
  39. <connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">
  40. <port>8888</port>
  41. <maxIdleTime>30000</maxIdleTime>
  42. </connector>
  43. </connectors>
  44. <webAppSourceDirectory>${project.build.directory}/${pom.artifactId}-${pom.version}</webAppSourceDirectory>
  45. <contextPath>/</contextPath>
  46. </configuration>
  47. </plugin>
  48. </plugins>
  49. </build>
  50.  
  51. <dependencies>
  52.  
  53. <dependency>
  54. <groupId>junit</groupId>
  55. <artifactId>junit</artifactId>
  56. <version>4.12</version>
  57. <scope>test</scope>
  58. </dependency>
  59. <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
  60. <dependency>
  61. <groupId>mysql</groupId>
  62. <artifactId>mysql-connector-java</artifactId>
  63. <version>5.1.40</version>
  64. </dependency>
  65. <!-- https://mvnrepository.com/artifact/c3p0/c3p0 -->
  66. <dependency>
  67. <groupId>c3p0</groupId>
  68. <artifactId>c3p0</artifactId>
  69. <version>0.9.1.2</version>
  70. </dependency>
  71. <!-- https://mvnrepository.com/artifact/commons-dbutils/commons-dbutils -->
  72. <dependency>
  73. <groupId>commons-dbutils</groupId>
  74. <artifactId>commons-dbutils</artifactId>
  75. <version>1.7</version>
  76. </dependency>
  77. <dependency>
  78. <groupId>org.junit.jupiter</groupId>
  79. <artifactId>junit-jupiter-api</artifactId>
  80. <version>RELEASE</version>
  81. </dependency>
  82.  
  83. </dependencies>
  84.  
  85. </project>
  • c3p0-config.xml
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <c3p0-config>
  3. <default-config>
  4. <property name="driverClass">com.mysql.jdbc.Driver</property>
  5. <property name="jdbcUrl">jdbc:mysql:///test</property>
  6. <property name="user">root</property>
  7. <property name="password">root</property>
  8. <property name="initialPoolSize">10</property>
  9. <property name="maxIdleTime">30</property>
  10. <property name="maxPoolSize">100</property>
  11. <property name="minPoolSize">10</property>
  12. <property name="maxStatements">200</property>
  13. </default-config>
  14.  
  15. </c3p0-config>
  • C3P0util.java
  1. package com.xuweiwei.util;
  2.  
  3. import com.mchange.v2.c3p0.ComboPooledDataSource;
  4.  
  5. import javax.sql.DataSource;
  6. import java.sql.Connection;
  7. import java.sql.SQLException;
  8.  
  9. public class C3P0util {
  10. private static ComboPooledDataSource dataSource = new ComboPooledDataSource();
  11.  
  12. public static DataSource getDataSource(){
  13. return dataSource;
  14. }
  15.  
  16. public static Connection getConnection(){
  17. try {
  18. return dataSource.getConnection();
  19. } catch (SQLException e) {
  20. throw new RuntimeException(e);
  21. }
  22. }
  23.  
  24. }
  • AccountDAO.java
  1. package com.xuweiwei.dao;
  2.  
  3. public interface AccountDAO {
  4.  
  5. /**
  6. * 转账
  7. * @param sourceAccountName
  8. * @param targetAccountName
  9. * @param money
  10. */
  11. public void transfer(String sourceAccountName,String targetAccountName,double money);
  12.  
  13. }
  • AccountDAOImpl.java
  1. package com.xuweiwei.dao.impl;
  2.  
  3. import com.xuweiwei.dao.AccountDAO;
  4. import com.xuweiwei.util.C3P0util;
  5. import org.apache.commons.dbutils.QueryRunner;
  6.  
  7. import java.sql.Connection;
  8. import java.sql.SQLException;
  9.  
  10. public class AccountDAOImpl implements AccountDAO {
  11. private QueryRunner queryRunner = new QueryRunner();
  12.  
  13. @Override
  14. public void transfer(String sourceAccountName, String targetAccountName, double money) {
  15. Connection conn = null;
  16. try{
  17. conn = C3P0util.getConnection();
  18. conn.setAutoCommit(false);
  19. queryRunner.update(conn,"update account set money = money -? where name = ? ",money,sourceAccountName);
  20. int i = 1 / 0;
  21. queryRunner.update(conn,"update account set money = money + ? where name = ? ",money,targetAccountName);
  22. }catch (Exception e){
  23. if(conn != null){
  24. try {
  25. conn.rollback();
  26. } catch (SQLException e1) {
  27. e1.printStackTrace();
  28. }
  29. }
  30. throw new RuntimeException(e);
  31. }finally {
  32. if(conn != null){
  33. try {
  34. conn.commit();
  35. conn.close();
  36. } catch (SQLException e) {
  37. e.printStackTrace();
  38. }
  39. }
  40. }
  41.  
  42. }
  43. }
  • AccountService.java
  1. package com.xuweiwei.service;
  2.  
  3. public interface AccountService {
  4. /**
  5. * 转账
  6. * @param sourceAccountName
  7. * @param targetAccountName
  8. * @param money
  9. */
  10. public void transfer(String sourceAccountName,String targetAccountName,double money);
  11. }
  • AccountServiceImpl.java
  1. package com.xuweiwei.service.impl;
  2.  
  3. import com.xuweiwei.dao.AccountDAO;
  4. import com.xuweiwei.dao.impl.AccountDAOImpl;
  5. import com.xuweiwei.service.AccountService;
  6.  
  7. public class AccountServiceImpl implements AccountService {
  8. private AccountDAO accountDAO = new AccountDAOImpl();
  9.  
  10. @Override
  11. public void transfer(String sourceAccountName, String targetAccountName, double money) {
  12. accountDAO.transfer(sourceAccountName,targetAccountName,money);
  13. }
  14. }
  • AccountTest.java
  1. package com.xuweiwei.client;
  2.  
  3. import com.xuweiwei.service.AccountService;
  4. import com.xuweiwei.service.impl.AccountServiceImpl;
  5. import org.junit.jupiter.api.Test;
  6.  
  7. public class AccountTest {
  8. private AccountService accountService = new AccountServiceImpl();
  9.  
  10. @Test
  11. public void testTransfer(){
  12. String sourceAccountName = "aaa";
  13. String targetAccountName = "bbb";
  14. double money = 100;
  15. accountService.transfer(sourceAccountName,targetAccountName,money);
  16. }
  17.  
  18. }
  • 代码地址:https://github.com/xuweiweiwoaini/Tx_One
  • 此种方式的缺点:

    • ①DAO层应该只考虑增加、删除、更新、查询等原子性操作,而不是这种逻辑操作。
    • ②事务应该放在业务层,而不是DAO层。  

2.2 Version2

  • Account.java
  1. package com.xuweiwei.domain;
  2.  
  3. import java.io.Serializable;
  4.  
  5. public class Account implements Serializable {
  6. private Integer id;
  7. private String name;
  8. private double money;
  9.  
  10. public Integer getId() {
  11. return id;
  12. }
  13.  
  14. public void setId(Integer id) {
  15. this.id = id;
  16. }
  17.  
  18. public String getName() {
  19. return name;
  20. }
  21.  
  22. public void setName(String name) {
  23. this.name = name;
  24. }
  25.  
  26. public double getMoney() {
  27. return money;
  28. }
  29.  
  30. public void setMoney(double money) {
  31. this.money = money;
  32. }
  33.  
  34. @Override
  35. public String toString() {
  36. return "Account{" +
  37. "id=" + id +
  38. ", name='" + name + '\'' +
  39. ", money=" + money +
  40. '}';
  41. }
  42. }
  • AccountDAO.java
  1. package com.xuweiwei.dao;
  2.  
  3. import com.xuweiwei.domain.Account;
  4.  
  5. public interface AccountDAO {
  6.  
  7. /**
  8. * 根据用户名查询账户
  9. * @param name
  10. * @return
  11. */
  12. public Account findByName(String name);
  13.  
  14. /**
  15. * 更新账户
  16. * @param account
  17. */
  18. public void update(Account account);
  19.  
  20. }
  • AccountDAOImpl.java
  1. package com.xuweiwei.dao.impl;
  2.  
  3. import com.xuweiwei.dao.AccountDAO;
  4. import com.xuweiwei.domain.Account;
  5. import org.apache.commons.dbutils.QueryRunner;
  6. import org.apache.commons.dbutils.handlers.BeanHandler;
  7.  
  8. import java.sql.Connection;
  9.  
  10. public class AccountDAOImpl implements AccountDAO {
  11. private QueryRunner queryRunner = new QueryRunner();
  12. private Connection conn;
  13. public AccountDAOImpl(Connection conn){
  14. this.conn = conn;
  15. }
  16.  
  17. @Override
  18. public Account findByName(String name) {
  19. try {
  20.  
  21. Account account = queryRunner.query(conn,"select * from account where name = ?",new BeanHandler<Account>(Account.class),name);
  22.  
  23. return account;
  24. }catch (Exception e){
  25. throw new RuntimeException(e);
  26. }
  27. }
  28.  
  29. @Override
  30. public void update(Account account) {
  31. try {
  32. queryRunner.update(conn,"update account set money = ? where id = ?",account.getMoney(),account.getId());
  33.  
  34. }catch (Exception e){
  35. throw new RuntimeException(e);
  36. }
  37. }
  38. }
  • AccountService.java
  1. package com.xuweiwei.service;
  2.  
  3. public interface AccountService {
  4. /**
  5. * 转账
  6. * @param sourceAccountName
  7. * @param targetAccountName
  8. * @param money
  9. */
  10. public void transfer(String sourceAccountName,String targetAccountName,double money);
  11. }
  • AccountServiceImpl.java
  1. package com.xuweiwei.service.impl;
  2.  
  3. import com.xuweiwei.dao.AccountDAO;
  4. import com.xuweiwei.dao.impl.AccountDAOImpl;
  5. import com.xuweiwei.domain.Account;
  6. import com.xuweiwei.service.AccountService;
  7. import com.xuweiwei.util.C3P0util;
  8.  
  9. import java.sql.Connection;
  10. import java.sql.SQLException;
  11.  
  12. public class AccountServiceImpl implements AccountService {
  13.  
  14. @Override
  15. public void transfer(String sourceAccountName, String targetAccountName, double money) {
  16. Connection conn = null;
  17. try {
  18. conn = C3P0util.getConnection();
  19. conn.setAutoCommit(false);
  20. AccountDAO accountDAO = new AccountDAOImpl(conn);
  21. Account sAccount = accountDAO.findByName(sourceAccountName);
  22. Account tAccount = accountDAO.findByName(targetAccountName);
  23. sAccount.setMoney(sAccount.getMoney() - money);
  24. tAccount.setMoney(tAccount.getMoney() +money);
  25. accountDAO.update(sAccount);
  26. int i = 1 /0;
  27. accountDAO.update(tAccount);
  28.  
  29. }catch (Exception e){
  30. if(conn != null){
  31. try {
  32. conn.rollback();
  33. } catch (SQLException e1) {
  34. e1.printStackTrace();
  35. }
  36. }
  37. throw new RuntimeException(e);
  38. }finally {
  39. if(conn != null){
  40. try {
  41. conn.commit();
  42. conn.close();
  43. } catch (SQLException e) {
  44. e.printStackTrace();
  45. }
  46.  
  47. }
  48. }
  49. }
  50. }
  • 代码地址:https://github.com/xuweiweiwoaini/Tx_Two
  • 缺点:
    • ①每个方法都要实例DAO,难道不能只实例化一次?
    • ②每次都需要将Connection传入到DAO层,难道不能不需要传递?  

2.3 Version 3

  • 软件三层架构

  • TransactionManager.java
  1. package com.xuweiwei.util;
  2.  
  3. import java.sql.Connection;
  4.  
  5. public class TransactionManager {
  6. private static ThreadLocal<Connection> threadLocal = new ThreadLocal<Connection>();
  7.  
  8. public static Connection getConnection(){
  9. Connection conn = threadLocal.get();
  10. if(conn == null){
  11. conn = C3P0util.getConnection();
  12. threadLocal.set(conn);
  13. }
  14. return conn;
  15.  
  16. }
  17.  
  18. public static void startTransaction(){
  19. try {
  20. Connection conn = getConnection();
  21. conn.setAutoCommit(false);
  22. }catch (Exception e){
  23. e.printStackTrace();
  24. }
  25. }
  26.  
  27. public static void rollback(){
  28.  
  29. try {
  30. Connection conn = getConnection();
  31. conn.rollback();
  32. }catch (Exception e){
  33. e.printStackTrace();
  34. }
  35.  
  36. }
  37.  
  38. public static void commit(){
  39.  
  40. try {
  41. Connection conn = getConnection();
  42. conn.commit();
  43. }catch (Exception e){
  44. e.printStackTrace();
  45. }
  46.  
  47. }
  48.  
  49. public static void close(){
  50. try {
  51. Connection conn = getConnection();
  52. conn.close();
  53. threadLocal.remove();
  54. }catch (Exception e){
  55. e.printStackTrace();
  56. }
  57.  
  58. }
  59.  
  60. }
  • AccountDAOImpl.java
  1. package com.xuweiwei.dao.impl;
  2.  
  3. import com.xuweiwei.dao.AccountDAO;
  4. import com.xuweiwei.domain.Account;
  5. import com.xuweiwei.util.TransactionManager;
  6. import org.apache.commons.dbutils.QueryRunner;
  7. import org.apache.commons.dbutils.handlers.BeanHandler;
  8.  
  9. public class AccountDAOImpl implements AccountDAO {
  10. private QueryRunner queryRunner = new QueryRunner();
  11.  
  12. @Override
  13. public Account findByName(String name) {
  14. try {
  15.  
  16. Account account = queryRunner.query(TransactionManager.getConnection(),"select * from account where name = ?",new BeanHandler<Account>(Account.class),name);
  17.  
  18. return account;
  19. }catch (Exception e){
  20. throw new RuntimeException(e);
  21. }
  22. }
  23.  
  24. @Override
  25. public void update(Account account) {
  26. try {
  27. queryRunner.update(TransactionManager.getConnection(),"update account set money = ? where id = ?",account.getMoney(),account.getId());
  28.  
  29. }catch (Exception e){
  30. throw new RuntimeException(e);
  31. }
  32. }
  33. }
  • AcountServiceImpl.java
  1. package com.xuweiwei.service.impl;
  2.  
  3. import com.xuweiwei.dao.AccountDAO;
  4. import com.xuweiwei.dao.impl.AccountDAOImpl;
  5. import com.xuweiwei.domain.Account;
  6. import com.xuweiwei.service.AccountService;
  7. import com.xuweiwei.util.TransactionManager;
  8.  
  9. public class AccountServiceImpl implements AccountService {
  10. private AccountDAO accountDAO = new AccountDAOImpl();
  11.  
  12. @Override
  13. public void transfer(String sourceAccountName, String targetAccountName, double money) {
  14. try {
  15. TransactionManager.startTransaction();
  16. Account sAccount = accountDAO.findByName(sourceAccountName);
  17. Account tAccount = accountDAO.findByName(targetAccountName);
  18. sAccount.setMoney(sAccount.getMoney() - money);
  19. tAccount.setMoney(tAccount.getMoney() +money);
  20. accountDAO.update(sAccount);
  21. //int i = 1 /0;
  22. accountDAO.update(tAccount);
  23.  
  24. }catch (Exception e){
  25. TransactionManager.rollback();
  26. throw new RuntimeException(e);
  27. }finally {
  28. TransactionManager.commit();
  29. TransactionManager.close();
  30. }
  31. }
  32. }
  • 代码地址:https://github.com/xuweiweiwoaini/Tx_Three
  • 缺点:
    • ①如果我需要打印日志、计算消耗时间,那么我必须在每个方法前后都加一些非功能些的代码,所以,使用AOP来解决。  

2.4 Version4

  • BeanFactory.java
  1. package com.xuweiwei.util;
  2.  
  3. import com.xuweiwei.service.AccountService;
  4. import com.xuweiwei.service.impl.AccountServiceImpl;
  5.  
  6. import java.lang.reflect.InvocationHandler;
  7. import java.lang.reflect.Method;
  8. import java.lang.reflect.Proxy;
  9.  
  10. public class BeanFactory {
  11. public static AccountService getAccountService() {
  12. AccountService accountService = new AccountServiceImpl();
  13.  
  14. AccountService proxy = (AccountService) Proxy.newProxyInstance(accountService.getClass().getClassLoader(), accountService.getClass().getInterfaces(), new InvocationHandler() {
  15. @Override
  16. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  17.  
  18. try {
  19. TransactionManager.startTransaction();
  20. Object obj = method.invoke(accountService,args);
  21. return obj;
  22. }catch (Exception e){
  23. TransactionManager.rollback();
  24. throw new RuntimeException(e);
  25. }finally {
  26. TransactionManager.commit();
  27. TransactionManager.close();
  28. }
  29.  
  30. }
  31. });
  32. return proxy;
  33.  
  34. }
  35. }
  • AccountServiceImpl.java
  1. package com.xuweiwei.service.impl;
  2.  
  3. import com.xuweiwei.dao.AccountDAO;
  4. import com.xuweiwei.dao.impl.AccountDAOImpl;
  5. import com.xuweiwei.domain.Account;
  6. import com.xuweiwei.service.AccountService;
  7. import com.xuweiwei.util.TransactionManager;
  8.  
  9. public class AccountServiceImpl implements AccountService {
  10. private AccountDAO accountDAO = new AccountDAOImpl();
  11.  
  12. @Override
  13. public void transfer(String sourceAccountName, String targetAccountName, double money) {
  14.  
  15. Account sAccount = accountDAO.findByName(sourceAccountName);
  16. Account tAccount = accountDAO.findByName(targetAccountName);
  17. sAccount.setMoney(sAccount.getMoney() - money);
  18. tAccount.setMoney(tAccount.getMoney() +money);
  19. accountDAO.update(sAccount);
  20. int i = 1 /0;
  21. accountDAO.update(tAccount);
  22.  
  23. }
  24. }
  • AccountTest.java
  1. package com.xuweiwei.client;
  2.  
  3. import com.xuweiwei.service.AccountService;
  4. import com.xuweiwei.service.impl.AccountServiceImpl;
  5. import com.xuweiwei.util.BeanFactory;
  6. import org.junit.jupiter.api.Test;
  7.  
  8. public class AccountTest {
  9. private AccountService accountService = BeanFactory.getAccountService();
  10.  
  11. @Test
  12. public void testTransfer(){
  13. String sourceAccountName = "aaa";
  14. String targetAccountName = "bbb";
  15. double money = 100;
  16. accountService.transfer(sourceAccountName,targetAccountName,money);
  17. }
  18.  
  19. }
  • 代码:https://github.com/xuweiweiwoaini/Tx_Four

JDBC(四)的更多相关文章

  1. JDBC四种驱动程序

    四种JDBC驱动程序 JDBC-ODBC桥驱动程序(JDBC-ODBC Bridge Driver) 此类驱动程序由JDBC-ODBC桥和一个ODBC驱动程序组成.其工作原理是,通过一段本地C代码将J ...

  2. java JDBC (四)

    package cn.sasa.demo4; import java.sql.Connection; import java.sql.PreparedStatement; import java.sq ...

  3. JDBC四(web基础学习笔记十)

    一.增加 .修改.删除.查询 将功能整合在一个类中 package pb.base; import java.sql.Connection; import java.sql.DriverManager ...

  4. java基础之JDBC四:事务简单示例

    /** * 事务 */ public class Test { public static void main(String[] args) { Connection conn = null; Pre ...

  5. JavaWeb -JDBC使用(数据库-javaweb连接)

    使用JDBC四个大类 1. DriverManager:管理jdbc驱动 2. Connection:连接(通过DriverManager产生) 3. Statement/PreparedStatem ...

  6. SQL基础之JDBC、连接池

    JDBC JDBC四个核心对象 这几个类都是在java.sql包中 DriverManager(类): 数据库驱动管理类.这个类的作用:1)注册驱动; 2)创建java代码和数据库之间的连接,即获取C ...

  7. 第七周PSP

    团队项目PSP 一:表格     C类型 C内容 S开始时间 E结束时间 I时间间隔 T净时间(mins) 预计花费时间(mins) 讨论 讨论用户界面 8:20 10:34 20 58 68 分析与 ...

  8. 使用hibernate时出现 org.hibernate.HibernateException: Unable to get the default Bean Validation factory

    hibernate 在使用junit测试报错: org.hibernate.HibernateException: Unable to get the default Bean Validation ...

  9. JdbcTemplae使用入门&&Spring三种连接池配置&&Spring配置文件引用外部properties文件

    JdbcTemplate的使用 Spring为了各种支持的持久化技术,都提供了简单操作的模版和回调. JdbcTemplate 简化 JDBC 操作HibernateTemplate 简化 Hiber ...

  10. Spring事务管理--多个ORM框架在使用时的情况分析

    公司的项目已经接近尾声了,总结一下项目中用到的技术,我发现项目中的有些东西还是挺模糊的,只是知道这么用就行了.并不清楚其中的原理.由于公司的项目比较老,是7年前的一个项目了,中间一直有人在维护,也是在 ...

随机推荐

  1. koa2教程(一)-快速开始

    来自Koa官网对于Koa的简介: koa 是由 Express 原班人马打造的,致力于成为一个更小.更富有表现力.更健壮的 Web 框架. 使用 koa 编写 web 应用,通过组合不同的 async ...

  2. springBoot项目打war包部署到tomcat上

    1 首先得在本地跑通. 2 处理启动类Application @SpringBootApplication public class Application extends SpringBootSer ...

  3. PHP开发工程师应该具备那些技术能力

    根据各大招聘网站的数据分析,2017年IT行业,其中从事软件开发和数据分析的毕业生的月薪最高.究其原因是因为随着互联网的不断发展,岗位人才稀缺,需求量大.那么如何快速的成为软件开发人员,比如PHP开发 ...

  4. Gradient Boosted Regression

    3.2.4.3.6. sklearn.ensemble.GradientBoostingRegressor class sklearn.ensemble.GradientBoostingRegress ...

  5. deeplearning.ai 人工智能行业大师访谈 Pieter Abbeel 听课笔记

    1. Pieter Abbeel小时候想做一个篮球运动员 - -!上学的时候喜欢数学和物理,上大学之后很自然的学工程.Pieter定义工程问题是"解决实际中应用物理和数学的问题". ...

  6. JVM GC知识回顾

    这两天刚好有朋友问到我面试中GC相关问题应该怎么答,作为java面试中热门问题,其实没有什么标准回答.这篇文章结合自己之前的总结,对GC做一个回顾. 1.分代收集 当前主流VM垃圾收集都采用" ...

  7. 信息学奥赛一本通算法(C++版)基础算法:高精度计算

    高精度加法(大位相加) #include <bits/stdc++.h> using namespace std; int main() { ],b1[]; ],b[],c[];//a,b ...

  8. hihoCoder1498-Diligent Robots

    #1498 : Diligent Robots Time Limit:10000ms Case Time Limit:1000ms Memory Limit:256MB Description The ...

  9. springboot:快速构建一个springboot项目

    前言: springboot作为springcloud的基础,springboot的热度一直很高,所以就有了这个springboot系列,花些时间来了解和学习为自己做技术储备,以备不时之需[手动滑稽] ...

  10. 【JSP/Servlet】后台如何获取复选框或可选属性的同名参数

    感觉自己jsp/servlet部分学的太差了--今天突然想到还有这种操作,遂分享之 比如有些时候我们需要使用复选框发送同名数据的时候,后台接收参数是个麻烦事,还有可选属性也是如此 有丰富经验的会想到a ...