JDBC(四)
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。
- public static void close(Connection conn) throws SQLException {
- if (conn != null) {
- conn.close();
- }
- }
- public static void close(ResultSet rs) throws SQLException {
- if (rs != null) {
- rs.close();
- }
- }
- public static void close(Statement stmt) throws SQLException {
- if (stmt != null) {
- stmt.close();
- }
- }
- DbUtils类提供的closeQuietly()这一类方法不仅仅能在Connection、Statement和ResultSet为null的情况下避免关闭,还能隐藏一些在程序中抛出的SQLException。
- public static void closeQuietly(Connection conn) {
- try {
- close(conn);
- } catch (SQLException var2) {
- ;
- }
- }
- public static void closeQuietly(Connection conn, Statement stmt, ResultSet rs) {
- try {
- closeQuietly(rs);
- } finally {
- try {
- closeQuietly(stmt);
- } finally {
- closeQuietly(conn);
- }
- }
- }
- public static void closeQuietly(ResultSet rs) {
- try {
- close(rs);
- } catch (SQLException var2) {
- ;
- }
- }
- public static void closeQuietly(Statement stmt) {
- try {
- close(stmt);
- } catch (SQLException var2) {
- ;
- }
- }
- DbUtils类提供的commitAndCloseQuietly()用来提交连接,然后关闭连接,并且在关闭连接的时候不抛出SQLException。
- public static void commitAndClose(Connection conn) throws SQLException {
- if (conn != null) {
- try {
- conn.commit();
- } finally {
- conn.close();
- }
- }
- }
- public static void commitAndCloseQuietly(Connection conn) {
- try {
- commitAndClose(conn);
- } catch (SQLException var2) {
- ;
- }
- }
- DbUtils类提供的loadDriver()这一方法装载并注册JDBC程序,如果成功就返回true。使用该方法,你不需要捕捉ClassNotFoundException。
- public static boolean loadDriver(String driverClassName) {
- return loadDriver(DbUtils.class.getClassLoader(), driverClassName);
- }
- public static boolean loadDriver(ClassLoader classLoader, String driverClassName) {
- try {
- classLoader.loadClass(driverClassName).newInstance();
- return true;
- } catch (IllegalAccessException var3) {
- return true;
- } catch (Exception var4) {
- return false;
- }
- }
1.2.2 QueryRunner类
- 该类简化了SQL查询,它和ResultSetHandler组合在一起使用可以完成大部分的数据库操作,能够大大的减少编码量。
- QueryRunner类提供了两个构造方法:
- public QueryRunner(DataSource ds) {
- super(ds);
- }
- public QueryRunner() {
- }
- QueryRunner类常用的方法如下:
- 执行一个查询操作,在这个查询中,对象数组中的每个元素值被用来作为查询语句的置换参数。该方法会自行处理PreparedStatement和ResultSet的创建和关闭。(可用来进行事务处理)
- public <T> T query(Connection conn, String sql, ResultSetHandler<T> rsh, Object... params) throws SQLException {
- return this.query(conn, false, sql, rsh, params);
- }
- 执行一个查询操作,在这个查询中,对象数组中的每个元素之被用来作为查询语句的置换参数。该方法会自行处理PreparedStatement和ResultSet的创建和关闭,和上面不同的是,这个方法是从构造方法传入的DataSource对象,获取连接。(依赖于数据库对事务的管理)
- public <T> T query(String sql, ResultSetHandler<T> rsh, Object... params) throws SQLException {
- Connection conn = this.prepareConnection();
- return this.query(conn, true, sql, rsh, params);
- }
- 用来执行一个更新(插入、删除和更新)的操作。(可以对事务控制)
- public int update(Connection conn, String sql, Object param) throws SQLException {
- return this.update(conn, false, sql, param);
- }
- 用来执行一个更新(插入、删除和更新)的操作。(依赖于底层数据库对事务的管理)
- public int update(String sql, Object... params) throws SQLException {
- Connection conn = this.prepareConnection();
- return this.update(conn, true, sql, params);
- }
- 示例:增加、删除、更新
- user.sql
- USE test;
- CREATE TABLE USER(
- id INT PRIMARY KEY AUTO_INCREMENT,
- NAME ) ,
- PASSWORD ), email varchar(20), birthday DATE
- );
- c3p0-config.xml
- <?xml version="1.0" encoding="UTF-8"?>
- <c3p0-config>
- <default-config>
- <property name="driverClass">com.mysql.jdbc.Driver</property>
- <property name="jdbcUrl">jdbc:mysql:///test</property>
- <property name="user">root</property>
- <property name="password">root</property>
- <property name="initialPoolSize">10</property>
- <property name="maxIdleTime">30</property>
- <property name="maxPoolSize">100</property>
- <property name="minPoolSize">10</property>
- <property name="maxStatements">200</property>
- </default-config>
- </c3p0-config>
- C3P0util.java
- package com.util;
- import com.mchange.v2.c3p0.ComboPooledDataSource;
- import javax.sql.DataSource;
- import java.sql.Connection;
- import java.sql.SQLException;
- public class C3P0util {
- private static ComboPooledDataSource dataSource = new ComboPooledDataSource();
- public static DataSource getDataSource(){
- return dataSource;
- }
- public static Connection getConnection(){
- try {
- return dataSource.getConnection();
- } catch (SQLException e) {
- throw new RuntimeException(e);
- }
- }
- }
- DbUtilTest.java
- package com.test;
- import com.util.C3P0util;
- import org.apache.commons.dbutils.QueryRunner;
- import org.junit.Test;
- import java.sql.SQLException;
- import java.util.Date;
- public class DbUtilTest {
- private QueryRunner queryRunner = new QueryRunner(C3P0util.getDataSource());
- /**
- * 插入
- * @throws SQLException
- */
- @Test
- public void testAdd() throws SQLException {
- queryRunner.update("insert into user values(null,?,?,?,?)","张三","admin","admin@163.com",new Date());
- }
- /**
- * 更新
- */
- @Test
- public void testUpdate() throws SQLException {
- queryRunner.update("update user set name = ? where id = ?","李四",1);
- }
- @Test
- public void testDelete() throws SQLException{
- queryRunner.update("delete from user where id = ?",1);
- }
- }
1.2.3 ResultSetHandler接口
- 该接口用于处理java.sql.ResultSet,将数据按照要求转换为另一种形式。
- ResultSetHandler接口提供了一个单独的方法:Objject handle(java.sql.ResultSet rs)
- package org.apache.commons.dbutils;
- import java.sql.ResultSet;
- import java.sql.SQLException;
- public interface ResultSetHandler<T> {
- T handle(ResultSet var1) throws SQLException;
- }
1.2.4 ResultSetHandler接口的实现类
- BeanHandler:将结果集中的第一行数据封装到一个对应的JavaBean对象中。
- BeanListHandler:将结果集中的每一行数据都封装到一个对应的JavaBean对象中,存放到List集合中。
- ScalarHandler:返回一行一列的数据,如select count(*) from user。
- 示例:
- user.sql
- use test;
- create table user(
- id int primary key auto_increment,
- name ) ,
- password ),
- email )
- birthday date
- );
- insert into user values (null,'张三','abc','adc@163.com','2017-11-11');
- insert into user values (null,'李四','bcd','bcd@163.com','2017-11-11');
- insert into user values (null,'王五','cde','cde@163.com','2017-11-11');
- c3p0-config.xml
- <?xml version="1.0" encoding="UTF-8"?>
- <c3p0-config>
- <default-config>
- <property name="driverClass">com.mysql.jdbc.Driver</property>
- <property name="jdbcUrl">jdbc:mysql:///test</property>
- <property name="user">root</property>
- <property name="password">root</property>
- <property name="initialPoolSize">10</property>
- <property name="maxIdleTime">30</property>
- <property name="maxPoolSize">100</property>
- <property name="minPoolSize">10</property>
- <property name="maxStatements">200</property>
- </default-config>
- </c3p0-config>
- C3P0util.java
- package com.util;
- import com.mchange.v2.c3p0.ComboPooledDataSource;
- import javax.sql.DataSource;
- import java.sql.Connection;
- import java.sql.SQLException;
- public class C3P0util {
- private static ComboPooledDataSource dataSource = new ComboPooledDataSource();
- public static DataSource getDataSource(){
- return dataSource;
- }
- public static Connection getConnection(){
- try {
- return dataSource.getConnection();
- } catch (SQLException e) {
- throw new RuntimeException(e);
- }
- }
- }
- User.java
- package com.domain;
- import java.io.Serializable;
- import java.util.Date;
- public class User implements Serializable {
- private Integer id;
- private String name;
- private String password;
- private String email;
- private Date birthday;
- public Integer getId() {
- return id;
- }
- public void setId(Integer id) {
- this.id = id;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public String getPassword() {
- return password;
- }
- public void setPassword(String password) {
- this.password = password;
- }
- public String getEmail() {
- return email;
- }
- public void setEmail(String email) {
- this.email = email;
- }
- public Date getBirthday() {
- return birthday;
- }
- public void setBirthday(Date birthday) {
- this.birthday = birthday;
- }
- @Override
- public String toString() {
- return "User{" +
- "id=" + id +
- ", name='" + name + '\'' +
- ", password='" + password + '\'' +
- ", email='" + email + '\'' +
- ", birthday=" + birthday +
- '}';
- }
- }
- DbUtil.java
- package com.test;
- import com.domain.User;
- import com.util.C3P0util;
- import org.apache.commons.dbutils.QueryRunner;
- import org.apache.commons.dbutils.handlers.BeanHandler;
- import org.apache.commons.dbutils.handlers.BeanListHandler;
- import org.apache.commons.dbutils.handlers.ScalarHandler;
- import org.junit.Test;
- import java.sql.SQLException;
- import java.util.List;
- public class DbUtilTest {
- private QueryRunner queryRunner = new QueryRunner(C3P0util.getDataSource());
- /**
- * 将查询的数据封装到javabean中,不管多少个记录,只返回第一行的记录
- */
- @Test
- public void testQueryOne() throws SQLException {
- User user = queryRunner.query("select * from user",new BeanHandler<User>(User.class));
- System.out.println(user);
- }
- /**
- * 将查询的数据封装到Javabean中,返回的是List集合
- * @throws SQLException
- */
- @Test
- public void testQueryAll() throws SQLException{
- List<User> users = queryRunner.query("select * from user",new BeanListHandler<User>(User.class));
- for(User u:users){
- System.out.println(u);
- }
- }
- @Test
- public void testCount() throws SQLException{
- Object count = queryRunner.query("select count(*) from user",new ScalarHandler());
- System.out.println(count);
- }
- }
2 在实际开发中事务如何管理
- sql脚本
- USE test;
- CREATE TABLE account(
- id INT PRIMARY KEY AUTO_INCREMENT,
- NAME ),
- money DOUBLE
- );
- );
- );
- );
2.1 version1
- pom.xml
- <?xml version="1.0" encoding="UTF-8"?>
- <!--
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
- -->
- <!-- $Id: pom.xml 642118 2008-03-28 08:04:16Z reinhard $ -->
- <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">
- <modelVersion>4.0.0</modelVersion>
- <packaging>war</packaging>
- <name>Tx</name>
- <groupId>com.xuweiwei</groupId>
- <artifactId>Tx</artifactId>
- <version>1.0-SNAPSHOT</version>
- <build>
- <plugins>
- <plugin>
- <groupId>org.mortbay.jetty</groupId>
- <artifactId>maven-jetty-plugin</artifactId>
- <version>6.1.7</version>
- <configuration>
- <connectors>
- <connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">
- <port>8888</port>
- <maxIdleTime>30000</maxIdleTime>
- </connector>
- </connectors>
- <webAppSourceDirectory>${project.build.directory}/${pom.artifactId}-${pom.version}</webAppSourceDirectory>
- <contextPath>/</contextPath>
- </configuration>
- </plugin>
- </plugins>
- </build>
- <dependencies>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <version>4.12</version>
- <scope>test</scope>
- </dependency>
- <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
- <dependency>
- <groupId>mysql</groupId>
- <artifactId>mysql-connector-java</artifactId>
- <version>5.1.40</version>
- </dependency>
- <!-- https://mvnrepository.com/artifact/c3p0/c3p0 -->
- <dependency>
- <groupId>c3p0</groupId>
- <artifactId>c3p0</artifactId>
- <version>0.9.1.2</version>
- </dependency>
- <!-- https://mvnrepository.com/artifact/commons-dbutils/commons-dbutils -->
- <dependency>
- <groupId>commons-dbutils</groupId>
- <artifactId>commons-dbutils</artifactId>
- <version>1.7</version>
- </dependency>
- <dependency>
- <groupId>org.junit.jupiter</groupId>
- <artifactId>junit-jupiter-api</artifactId>
- <version>RELEASE</version>
- </dependency>
- </dependencies>
- </project>
- c3p0-config.xml
- <?xml version="1.0" encoding="UTF-8"?>
- <c3p0-config>
- <default-config>
- <property name="driverClass">com.mysql.jdbc.Driver</property>
- <property name="jdbcUrl">jdbc:mysql:///test</property>
- <property name="user">root</property>
- <property name="password">root</property>
- <property name="initialPoolSize">10</property>
- <property name="maxIdleTime">30</property>
- <property name="maxPoolSize">100</property>
- <property name="minPoolSize">10</property>
- <property name="maxStatements">200</property>
- </default-config>
- </c3p0-config>
- C3P0util.java
- package com.xuweiwei.util;
- import com.mchange.v2.c3p0.ComboPooledDataSource;
- import javax.sql.DataSource;
- import java.sql.Connection;
- import java.sql.SQLException;
- public class C3P0util {
- private static ComboPooledDataSource dataSource = new ComboPooledDataSource();
- public static DataSource getDataSource(){
- return dataSource;
- }
- public static Connection getConnection(){
- try {
- return dataSource.getConnection();
- } catch (SQLException e) {
- throw new RuntimeException(e);
- }
- }
- }
- AccountDAO.java
- package com.xuweiwei.dao;
- public interface AccountDAO {
- /**
- * 转账
- * @param sourceAccountName
- * @param targetAccountName
- * @param money
- */
- public void transfer(String sourceAccountName,String targetAccountName,double money);
- }
- AccountDAOImpl.java
- package com.xuweiwei.dao.impl;
- import com.xuweiwei.dao.AccountDAO;
- import com.xuweiwei.util.C3P0util;
- import org.apache.commons.dbutils.QueryRunner;
- import java.sql.Connection;
- import java.sql.SQLException;
- public class AccountDAOImpl implements AccountDAO {
- private QueryRunner queryRunner = new QueryRunner();
- @Override
- public void transfer(String sourceAccountName, String targetAccountName, double money) {
- Connection conn = null;
- try{
- conn = C3P0util.getConnection();
- conn.setAutoCommit(false);
- queryRunner.update(conn,"update account set money = money -? where name = ? ",money,sourceAccountName);
- int i = 1 / 0;
- queryRunner.update(conn,"update account set money = money + ? where name = ? ",money,targetAccountName);
- }catch (Exception e){
- if(conn != null){
- try {
- conn.rollback();
- } catch (SQLException e1) {
- e1.printStackTrace();
- }
- }
- throw new RuntimeException(e);
- }finally {
- if(conn != null){
- try {
- conn.commit();
- conn.close();
- } catch (SQLException e) {
- e.printStackTrace();
- }
- }
- }
- }
- }
- AccountService.java
- package com.xuweiwei.service;
- public interface AccountService {
- /**
- * 转账
- * @param sourceAccountName
- * @param targetAccountName
- * @param money
- */
- public void transfer(String sourceAccountName,String targetAccountName,double money);
- }
- AccountServiceImpl.java
- package com.xuweiwei.service.impl;
- import com.xuweiwei.dao.AccountDAO;
- import com.xuweiwei.dao.impl.AccountDAOImpl;
- import com.xuweiwei.service.AccountService;
- public class AccountServiceImpl implements AccountService {
- private AccountDAO accountDAO = new AccountDAOImpl();
- @Override
- public void transfer(String sourceAccountName, String targetAccountName, double money) {
- accountDAO.transfer(sourceAccountName,targetAccountName,money);
- }
- }
- AccountTest.java
- package com.xuweiwei.client;
- import com.xuweiwei.service.AccountService;
- import com.xuweiwei.service.impl.AccountServiceImpl;
- import org.junit.jupiter.api.Test;
- public class AccountTest {
- private AccountService accountService = new AccountServiceImpl();
- @Test
- public void testTransfer(){
- String sourceAccountName = "aaa";
- String targetAccountName = "bbb";
- double money = 100;
- accountService.transfer(sourceAccountName,targetAccountName,money);
- }
- }
- 代码地址:https://github.com/xuweiweiwoaini/Tx_One
- 此种方式的缺点:
- ①DAO层应该只考虑增加、删除、更新、查询等原子性操作,而不是这种逻辑操作。
- ②事务应该放在业务层,而不是DAO层。
2.2 Version2
- Account.java
- package com.xuweiwei.domain;
- import java.io.Serializable;
- public class Account implements Serializable {
- private Integer id;
- private String name;
- private double money;
- public Integer getId() {
- return id;
- }
- public void setId(Integer id) {
- this.id = id;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public double getMoney() {
- return money;
- }
- public void setMoney(double money) {
- this.money = money;
- }
- @Override
- public String toString() {
- return "Account{" +
- "id=" + id +
- ", name='" + name + '\'' +
- ", money=" + money +
- '}';
- }
- }
- AccountDAO.java
- package com.xuweiwei.dao;
- import com.xuweiwei.domain.Account;
- public interface AccountDAO {
- /**
- * 根据用户名查询账户
- * @param name
- * @return
- */
- public Account findByName(String name);
- /**
- * 更新账户
- * @param account
- */
- public void update(Account account);
- }
- AccountDAOImpl.java
- package com.xuweiwei.dao.impl;
- import com.xuweiwei.dao.AccountDAO;
- import com.xuweiwei.domain.Account;
- import org.apache.commons.dbutils.QueryRunner;
- import org.apache.commons.dbutils.handlers.BeanHandler;
- import java.sql.Connection;
- public class AccountDAOImpl implements AccountDAO {
- private QueryRunner queryRunner = new QueryRunner();
- private Connection conn;
- public AccountDAOImpl(Connection conn){
- this.conn = conn;
- }
- @Override
- public Account findByName(String name) {
- try {
- Account account = queryRunner.query(conn,"select * from account where name = ?",new BeanHandler<Account>(Account.class),name);
- return account;
- }catch (Exception e){
- throw new RuntimeException(e);
- }
- }
- @Override
- public void update(Account account) {
- try {
- queryRunner.update(conn,"update account set money = ? where id = ?",account.getMoney(),account.getId());
- }catch (Exception e){
- throw new RuntimeException(e);
- }
- }
- }
- AccountService.java
- package com.xuweiwei.service;
- public interface AccountService {
- /**
- * 转账
- * @param sourceAccountName
- * @param targetAccountName
- * @param money
- */
- public void transfer(String sourceAccountName,String targetAccountName,double money);
- }
- AccountServiceImpl.java
- package com.xuweiwei.service.impl;
- import com.xuweiwei.dao.AccountDAO;
- import com.xuweiwei.dao.impl.AccountDAOImpl;
- import com.xuweiwei.domain.Account;
- import com.xuweiwei.service.AccountService;
- import com.xuweiwei.util.C3P0util;
- import java.sql.Connection;
- import java.sql.SQLException;
- public class AccountServiceImpl implements AccountService {
- @Override
- public void transfer(String sourceAccountName, String targetAccountName, double money) {
- Connection conn = null;
- try {
- conn = C3P0util.getConnection();
- conn.setAutoCommit(false);
- AccountDAO accountDAO = new AccountDAOImpl(conn);
- Account sAccount = accountDAO.findByName(sourceAccountName);
- Account tAccount = accountDAO.findByName(targetAccountName);
- sAccount.setMoney(sAccount.getMoney() - money);
- tAccount.setMoney(tAccount.getMoney() +money);
- accountDAO.update(sAccount);
- int i = 1 /0;
- accountDAO.update(tAccount);
- }catch (Exception e){
- if(conn != null){
- try {
- conn.rollback();
- } catch (SQLException e1) {
- e1.printStackTrace();
- }
- }
- throw new RuntimeException(e);
- }finally {
- if(conn != null){
- try {
- conn.commit();
- conn.close();
- } catch (SQLException e) {
- e.printStackTrace();
- }
- }
- }
- }
- }
- 代码地址:https://github.com/xuweiweiwoaini/Tx_Two
- 缺点:
- ①每个方法都要实例DAO,难道不能只实例化一次?
- ②每次都需要将Connection传入到DAO层,难道不能不需要传递?
2.3 Version 3
- 软件三层架构
- TransactionManager.java
- package com.xuweiwei.util;
- import java.sql.Connection;
- public class TransactionManager {
- private static ThreadLocal<Connection> threadLocal = new ThreadLocal<Connection>();
- public static Connection getConnection(){
- Connection conn = threadLocal.get();
- if(conn == null){
- conn = C3P0util.getConnection();
- threadLocal.set(conn);
- }
- return conn;
- }
- public static void startTransaction(){
- try {
- Connection conn = getConnection();
- conn.setAutoCommit(false);
- }catch (Exception e){
- e.printStackTrace();
- }
- }
- public static void rollback(){
- try {
- Connection conn = getConnection();
- conn.rollback();
- }catch (Exception e){
- e.printStackTrace();
- }
- }
- public static void commit(){
- try {
- Connection conn = getConnection();
- conn.commit();
- }catch (Exception e){
- e.printStackTrace();
- }
- }
- public static void close(){
- try {
- Connection conn = getConnection();
- conn.close();
- threadLocal.remove();
- }catch (Exception e){
- e.printStackTrace();
- }
- }
- }
- AccountDAOImpl.java
- package com.xuweiwei.dao.impl;
- import com.xuweiwei.dao.AccountDAO;
- import com.xuweiwei.domain.Account;
- import com.xuweiwei.util.TransactionManager;
- import org.apache.commons.dbutils.QueryRunner;
- import org.apache.commons.dbutils.handlers.BeanHandler;
- public class AccountDAOImpl implements AccountDAO {
- private QueryRunner queryRunner = new QueryRunner();
- @Override
- public Account findByName(String name) {
- try {
- Account account = queryRunner.query(TransactionManager.getConnection(),"select * from account where name = ?",new BeanHandler<Account>(Account.class),name);
- return account;
- }catch (Exception e){
- throw new RuntimeException(e);
- }
- }
- @Override
- public void update(Account account) {
- try {
- queryRunner.update(TransactionManager.getConnection(),"update account set money = ? where id = ?",account.getMoney(),account.getId());
- }catch (Exception e){
- throw new RuntimeException(e);
- }
- }
- }
- AcountServiceImpl.java
- package com.xuweiwei.service.impl;
- import com.xuweiwei.dao.AccountDAO;
- import com.xuweiwei.dao.impl.AccountDAOImpl;
- import com.xuweiwei.domain.Account;
- import com.xuweiwei.service.AccountService;
- import com.xuweiwei.util.TransactionManager;
- public class AccountServiceImpl implements AccountService {
- private AccountDAO accountDAO = new AccountDAOImpl();
- @Override
- public void transfer(String sourceAccountName, String targetAccountName, double money) {
- try {
- TransactionManager.startTransaction();
- Account sAccount = accountDAO.findByName(sourceAccountName);
- Account tAccount = accountDAO.findByName(targetAccountName);
- sAccount.setMoney(sAccount.getMoney() - money);
- tAccount.setMoney(tAccount.getMoney() +money);
- accountDAO.update(sAccount);
- //int i = 1 /0;
- accountDAO.update(tAccount);
- }catch (Exception e){
- TransactionManager.rollback();
- throw new RuntimeException(e);
- }finally {
- TransactionManager.commit();
- TransactionManager.close();
- }
- }
- }
- 代码地址:https://github.com/xuweiweiwoaini/Tx_Three
- 缺点:
- ①如果我需要打印日志、计算消耗时间,那么我必须在每个方法前后都加一些非功能些的代码,所以,使用AOP来解决。
2.4 Version4
- BeanFactory.java
- package com.xuweiwei.util;
- import com.xuweiwei.service.AccountService;
- import com.xuweiwei.service.impl.AccountServiceImpl;
- import java.lang.reflect.InvocationHandler;
- import java.lang.reflect.Method;
- import java.lang.reflect.Proxy;
- public class BeanFactory {
- public static AccountService getAccountService() {
- AccountService accountService = new AccountServiceImpl();
- AccountService proxy = (AccountService) Proxy.newProxyInstance(accountService.getClass().getClassLoader(), accountService.getClass().getInterfaces(), new InvocationHandler() {
- @Override
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- try {
- TransactionManager.startTransaction();
- Object obj = method.invoke(accountService,args);
- return obj;
- }catch (Exception e){
- TransactionManager.rollback();
- throw new RuntimeException(e);
- }finally {
- TransactionManager.commit();
- TransactionManager.close();
- }
- }
- });
- return proxy;
- }
- }
- AccountServiceImpl.java
- package com.xuweiwei.service.impl;
- import com.xuweiwei.dao.AccountDAO;
- import com.xuweiwei.dao.impl.AccountDAOImpl;
- import com.xuweiwei.domain.Account;
- import com.xuweiwei.service.AccountService;
- import com.xuweiwei.util.TransactionManager;
- public class AccountServiceImpl implements AccountService {
- private AccountDAO accountDAO = new AccountDAOImpl();
- @Override
- public void transfer(String sourceAccountName, String targetAccountName, double money) {
- Account sAccount = accountDAO.findByName(sourceAccountName);
- Account tAccount = accountDAO.findByName(targetAccountName);
- sAccount.setMoney(sAccount.getMoney() - money);
- tAccount.setMoney(tAccount.getMoney() +money);
- accountDAO.update(sAccount);
- int i = 1 /0;
- accountDAO.update(tAccount);
- }
- }
- AccountTest.java
- package com.xuweiwei.client;
- import com.xuweiwei.service.AccountService;
- import com.xuweiwei.service.impl.AccountServiceImpl;
- import com.xuweiwei.util.BeanFactory;
- import org.junit.jupiter.api.Test;
- public class AccountTest {
- private AccountService accountService = BeanFactory.getAccountService();
- @Test
- public void testTransfer(){
- String sourceAccountName = "aaa";
- String targetAccountName = "bbb";
- double money = 100;
- accountService.transfer(sourceAccountName,targetAccountName,money);
- }
- }
- 代码:https://github.com/xuweiweiwoaini/Tx_Four
JDBC(四)的更多相关文章
- JDBC四种驱动程序
四种JDBC驱动程序 JDBC-ODBC桥驱动程序(JDBC-ODBC Bridge Driver) 此类驱动程序由JDBC-ODBC桥和一个ODBC驱动程序组成.其工作原理是,通过一段本地C代码将J ...
- java JDBC (四)
package cn.sasa.demo4; import java.sql.Connection; import java.sql.PreparedStatement; import java.sq ...
- JDBC四(web基础学习笔记十)
一.增加 .修改.删除.查询 将功能整合在一个类中 package pb.base; import java.sql.Connection; import java.sql.DriverManager ...
- java基础之JDBC四:事务简单示例
/** * 事务 */ public class Test { public static void main(String[] args) { Connection conn = null; Pre ...
- JavaWeb -JDBC使用(数据库-javaweb连接)
使用JDBC四个大类 1. DriverManager:管理jdbc驱动 2. Connection:连接(通过DriverManager产生) 3. Statement/PreparedStatem ...
- SQL基础之JDBC、连接池
JDBC JDBC四个核心对象 这几个类都是在java.sql包中 DriverManager(类): 数据库驱动管理类.这个类的作用:1)注册驱动; 2)创建java代码和数据库之间的连接,即获取C ...
- 第七周PSP
团队项目PSP 一:表格 C类型 C内容 S开始时间 E结束时间 I时间间隔 T净时间(mins) 预计花费时间(mins) 讨论 讨论用户界面 8:20 10:34 20 58 68 分析与 ...
- 使用hibernate时出现 org.hibernate.HibernateException: Unable to get the default Bean Validation factory
hibernate 在使用junit测试报错: org.hibernate.HibernateException: Unable to get the default Bean Validation ...
- JdbcTemplae使用入门&&Spring三种连接池配置&&Spring配置文件引用外部properties文件
JdbcTemplate的使用 Spring为了各种支持的持久化技术,都提供了简单操作的模版和回调. JdbcTemplate 简化 JDBC 操作HibernateTemplate 简化 Hiber ...
- Spring事务管理--多个ORM框架在使用时的情况分析
公司的项目已经接近尾声了,总结一下项目中用到的技术,我发现项目中的有些东西还是挺模糊的,只是知道这么用就行了.并不清楚其中的原理.由于公司的项目比较老,是7年前的一个项目了,中间一直有人在维护,也是在 ...
随机推荐
- koa2教程(一)-快速开始
来自Koa官网对于Koa的简介: koa 是由 Express 原班人马打造的,致力于成为一个更小.更富有表现力.更健壮的 Web 框架. 使用 koa 编写 web 应用,通过组合不同的 async ...
- springBoot项目打war包部署到tomcat上
1 首先得在本地跑通. 2 处理启动类Application @SpringBootApplication public class Application extends SpringBootSer ...
- PHP开发工程师应该具备那些技术能力
根据各大招聘网站的数据分析,2017年IT行业,其中从事软件开发和数据分析的毕业生的月薪最高.究其原因是因为随着互联网的不断发展,岗位人才稀缺,需求量大.那么如何快速的成为软件开发人员,比如PHP开发 ...
- Gradient Boosted Regression
3.2.4.3.6. sklearn.ensemble.GradientBoostingRegressor class sklearn.ensemble.GradientBoostingRegress ...
- deeplearning.ai 人工智能行业大师访谈 Pieter Abbeel 听课笔记
1. Pieter Abbeel小时候想做一个篮球运动员 - -!上学的时候喜欢数学和物理,上大学之后很自然的学工程.Pieter定义工程问题是"解决实际中应用物理和数学的问题". ...
- JVM GC知识回顾
这两天刚好有朋友问到我面试中GC相关问题应该怎么答,作为java面试中热门问题,其实没有什么标准回答.这篇文章结合自己之前的总结,对GC做一个回顾. 1.分代收集 当前主流VM垃圾收集都采用" ...
- 信息学奥赛一本通算法(C++版)基础算法:高精度计算
高精度加法(大位相加) #include <bits/stdc++.h> using namespace std; int main() { ],b1[]; ],b[],c[];//a,b ...
- hihoCoder1498-Diligent Robots
#1498 : Diligent Robots Time Limit:10000ms Case Time Limit:1000ms Memory Limit:256MB Description The ...
- springboot:快速构建一个springboot项目
前言: springboot作为springcloud的基础,springboot的热度一直很高,所以就有了这个springboot系列,花些时间来了解和学习为自己做技术储备,以备不时之需[手动滑稽] ...
- 【JSP/Servlet】后台如何获取复选框或可选属性的同名参数
感觉自己jsp/servlet部分学的太差了--今天突然想到还有这种操作,遂分享之 比如有些时候我们需要使用复选框发送同名数据的时候,后台接收参数是个麻烦事,还有可选属性也是如此 有丰富经验的会想到a ...