第九章 Spring5 高级应用及核心原理(三)

一、事务管理

1.1 JdbcTemplate
- 添加依赖
  <?xml version="1.0" encoding="UTF-8"?>
  <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/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
  
      <groupId>com.gupaoedu</groupId>
      <artifactId>SpringJdbcTemplate</artifactId>
      <version>1.0-SNAPSHOT</version>
  
      <dependencies>
          <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
          <dependency>
              <groupId>org.springframework</groupId>
              <artifactId>spring-orm</artifactId>
              <version>5.1.17.RELEASE</version>
          </dependency>
          <dependency>
              <groupId>org.springframework</groupId>
              <artifactId>spring-context</artifactId>
              <version>5.1.17.RELEASE</version>
          </dependency>
          <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
          <!-- 如果Mysql是8.0的就用这个驱动 -->
          <!--<dependency>
              <groupId>mysql</groupId>
              <artifactId>mysql-connector-java</artifactId>
              <version>8.0.16</version>
          </dependency>-->
          <!-- 如果Mysql是5.7的就用这个驱动 -->
          <dependency>
              <groupId>mysql</groupId>
              <artifactId>mysql-connector-java</artifactId>
              <version>5.1.38</version>
          </dependency>
          <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
          <dependency>
              <groupId>org.aspectj</groupId>
              <artifactId>aspectjweaver</artifactId>
              <version>1.9.1</version>
          </dependency>
      </dependencies>
  
  </project>
  
- 创建 User
  package com.gupaoedu.pojo;
  
  public class User {
  
      private Integer id;
      
      private String name;
  
      private Integer age;
  
      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 Integer getAge() {
          return age;
      }
  
      public void setAge(Integer age) {
          this.age = age;
      }
  
      @Override
      public String toString() {
          return "User{" +
                  "id=" + id +
                  ", name='" + name + '\'' +
                  ", age=" + age +
                  '}';
      }
  }
  
- 新建 IUserDao
  package com.gupaoedu.dao;
  
  import com.gupaoedu.pojo.User;
  import java.util.List;
  
  public interface IUserDao {
  
      public Integer addUser(User user);
  
      public List<User> query();
  
  }
  
- 新建 UserDaoImpl
  package com.gupaoedu.dao.impl;
  
  import com.gupaoedu.dao.IUserDao;
  import com.gupaoedu.pojo.User;
  import org.springframework.beans.factory.annotation.Autowired;
  import org.springframework.jdbc.core.JdbcTemplate;
  import org.springframework.jdbc.core.RowMapper;
  import org.springframework.stereotype.Repository;
  import java.sql.ResultSet;
  import java.sql.SQLException;
  import java.util.List;
  
  @Repository
  public class UserDaoImpl implements IUserDao {
  
      @Autowired
      private JdbcTemplate template;
      private String sql;
  
      public Integer addUser(User user) {
          sql = "insert into users(name, age) values(?, ?)";
          return template.update(sql, user.getName(), user.getAge());
      }
  
      public List<User> query() {
          sql = "select * from users order by id desc";
          List<User> users = template.query(sql, new RowMapper<User>() {
              public User mapRow(ResultSet resultSet, int i) throws SQLException {
                  User user = new User();
                  try {
                      user.setId(resultSet.getInt("id"));
                      user.setName(resultSet.getString("name"));
                      user.setAge(resultSet.getInt("age"));
                  } catch (SQLException e) {
                      e.printStackTrace();
                  }
                  return user;
              }
          });
          return users;
      }
  }
  
- 新建 IUserService
  package com.gupaoedu.service;
  
  import com.gupaoedu.pojo.User;
  import java.util.List;
  
  public interface IUserService {
  
      public Integer addUser(User user);
  
      public List<User> query();
  
  }
  
- 新建 UserServiceImpl
  package com.gupaoedu.service.impl;
  
  import com.gupaoedu.dao.IUserDao;
  import com.gupaoedu.pojo.User;
  import com.gupaoedu.service.IUserService;
  import org.springframework.beans.factory.annotation.Autowired;
  import org.springframework.stereotype.Service;
  import java.util.List;
  
  @Service
  public class UserServiceImpl implements IUserService {
  
      @Autowired
      private IUserDao dao;
  
      public Integer addUser(User user) {
          return dao.addUser(user);
      }
  
      public List<User> query() {
          return dao.query();
      }
  }
  
- 新建 JavaConfig
  package com.gupaoedu;
  
  import com.gupaoedu.pojo.User;
  import com.gupaoedu.service.IUserService;
  import org.springframework.context.ApplicationContext;
  import org.springframework.context.annotation.*;
  import org.springframework.jdbc.core.JdbcTemplate;
  import org.springframework.jdbc.datasource.DriverManagerDataSource;
  import javax.sql.DataSource;
  
  @Configuration
  @ComponentScan
  public class JavaConfig {
  
      @Bean
      public DataSource dataSource() {
          DriverManagerDataSource dataSource = new DriverManagerDataSource();
          dataSource.setDriverClassName("com.mysql.jdbc.Driver");
          dataSource.setUrl("jdbc:mysql://localhost:3306/test?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF-8");
          dataSource.setUsername("root");
          dataSource.setPassword("123456");
          return dataSource;
      }
  
      @Bean
      @DependsOn("dataSource")
      public JdbcTemplate template(DataSource dataSource) {
          return new JdbcTemplate(dataSource);
      }
  
      public static void main(String[] args) {
          ApplicationContext ac = new AnnotationConfigApplicationContext(JavaConfig.class);
          IUserService bean = ac.getBean(IUserService.class);
          User user = new User();
          user.setName("灰灰");
          user.setAge(18);
          System.out.println(bean.addUser(user));
          System.out.println(bean.query());
      }
  
  }
  
- 执行结果
1
[User{id=1, name='灰灰', age=18}]
 
1.2 jdbc 事务管理机制
- 【IUserDao】新增 addUserInfo 和 transaction 接口;
  package com.gupao.dao;
  
  import com.gupao.pojo.User;
  import java.util.List;
  
  public interface IUserDao {
  
      public Integer addUser(User user);
  
      public List<User> query();
  
      public Integer addUserInfo(String username, String password);
  
      public Integer transaction(User user, String username, String password);
  
  }
 
- 【UserDaoImpl】实现 addUserInfo 和 transaction 接口;
  package com.gupao.dao.impl;
  
  import com.gupao.dao.IUserDao;
  import com.gupao.pojo.User;
  import org.springframework.beans.factory.annotation.Autowired;
  import org.springframework.jdbc.core.JdbcTemplate;
  import org.springframework.jdbc.core.RowMapper;
  import org.springframework.stereotype.Repository;
  import java.sql.*;
  import java.util.List;
  
  @Repository
  public class UserDaoImpl implements IUserDao {
  
      private final String DRIVERNAME = "com.mysql.jdbc.Driver";
      private final String URL = "jdbc:mysql://localhost:3306/test?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF-8";
      private final String USERNAME = "root";
      private final String PASSWORD = "123456";
  
      @Autowired
      private JdbcTemplate template;
      private String sql;
      private Connection conn = null;
      private PreparedStatement ps = null;
  
      public Integer addUser(User user) {
          /*sql = "insert into users(name, age) values(?, ?)";
          int iRet = template.update(sql, user.getName(), user.getAge());*/
          int iRet = 0;
          try {
              Class.forName(DRIVERNAME);
              conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
              sql = "insert into users(name, age) values(?, ?)";
              ps = conn.prepareStatement(sql);
              ps.setString(1, user.getName());
              ps.setInt(2, user.getAge());
              iRet = ps.executeUpdate();
          } catch (Exception e) {
              e.printStackTrace();
          } finally {
              if(ps != null) {
                  try {
                      ps.close();
                  } catch (SQLException e) {
                      e.printStackTrace();
                  }
              }
              if(conn != null) {
                  try {
                      conn.close();
                  } catch (SQLException e) {
                      e.printStackTrace();
                  }
              }
          }
  
          return iRet;
      }
  
      public Integer addUserInfo(String userName, String passwrod) {
          /*sql = "insert into user_info(username, password) values(?, ?)";
          int iRet = template.update(sql, userName, passwrod);*/
          int iRet = 0;
          try {
              Class.forName(DRIVERNAME);
              conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
              sql = "insert into user_info(username, password) values(?, ?)";
              ps = conn.prepareStatement(sql);
              ps.setString(1, userName);
              ps.setString(2, passwrod);
              iRet = ps.executeUpdate();
          } catch (Exception e) {
              e.printStackTrace();
          } finally {
              if(ps != null) {
                  try {
                      ps.close();
                  } catch (SQLException e) {
                      e.printStackTrace();
                  }
              }
              if(conn != null) {
                  try {
                      conn.close();
                  } catch (SQLException e) {
                      e.printStackTrace();
                  }
              }
          }
  
          return iRet;
      }
  
      public Integer transaction(User user, String username, String password) {
          int iRet = 0;
          try {
              Class.forName(DRIVERNAME);
              conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
              // 关闭自动提交
              conn.setAutoCommit(false);
              sql = "insert into users(name, age) values(?, ?)";
              ps = conn.prepareStatement(sql);
              ps.setString(1, user.getName());
              ps.setInt(2, user.getAge());
              iRet = ps.executeUpdate();
              sql = "insert into user_info(username, password1) values(?, ?)";
              ps = conn.prepareStatement(sql);
              ps.setString(1, username);
              ps.setString(2, password);
              iRet += ps.executeUpdate();
              conn.commit();
          } catch (Exception e) {
              try {
                  conn.rollback();
              } catch (SQLException e1) {
                  e1.printStackTrace();
              }
              e.printStackTrace();
          } finally {
              if(ps != null) {
                  try {
                      ps.close();
                  } catch (SQLException e) {
                      e.printStackTrace();
                  }
              }
              if(conn != null) {
                  try {
                      conn.close();
                  } catch (SQLException e) {
                      e.printStackTrace();
                  }
              }
          }
  
          return iRet;
      }
  
      public List<User> query() {
          sql = "select * from users order by id desc";
          List<User> list = template.query(sql, new RowMapper<User>() {
              public User mapRow(ResultSet resultSet, int i) throws SQLException {
                  User user = new User();
                  try {
                      user.setId(resultSet.getInt("id"));
                      user.setName(resultSet.getString("name"));
                      user.setAge(resultSet.getInt("age"));
                  } catch (SQLException e) {
                      e.printStackTrace();
                  }
                  return user;
              }
          });
          return list;
      }
  
  }
  
- 【IUserService】新增 addUserInfo 和 transaction 接口;
  package com.gupao.service;
  
  import com.gupao.pojo.User;
  import java.util.List;
  
  public interface IUserService {
  
      public Integer addUser(User user);
  
      public List<User> query();
  
      public Integer addUserInfo(String username, String password);
  
      public Integer transaction(User user, String username, String password);
  
  }
  
- 【UserServiceImpl】新增 addUserInfo 和 transaction;
  package com.gupao.service.impl;
  
  import com.gupao.dao.IUserDao;
  import com.gupao.pojo.User;
  import com.gupao.service.IUserService;
  import org.springframework.beans.factory.annotation.Autowired;
  import org.springframework.stereotype.Service;
  import java.util.List;
  
  @Service
  public class UserServicImpl implements IUserService {
  
      @Autowired
      private IUserDao userDao;
  
      public Integer addUser(User user) {
          return userDao.addUser(user);
      }
  
      public List<User> query() {
          return userDao.query();
      }
  
      public Integer addUserInfo(String username, String password) {
          return userDao.addUserInfo(username, password);
      }
  
      public Integer transaction(User user, String username, String password) {
          return userDao.transaction(user, username, password);
      }
  
  }
  
- 修改 JavaConfig
  package com.gupao;
  
  import com.gupao.pojo.User;
  import com.gupao.service.IUserService;
  import org.springframework.context.ApplicationContext;
  import org.springframework.context.annotation.*;
  import org.springframework.jdbc.core.JdbcTemplate;
  import org.springframework.jdbc.datasource.DriverManagerDataSource;
  import javax.sql.DataSource;
  
  @Configuration
  @ComponentScan
  public class JavaConfig {
  
      @Bean
      public DataSource dataSource() {
          DriverManagerDataSource dataSource = new DriverManagerDataSource();
          dataSource.setDriverClassName("com.mysql.jdbc.Driver");
          dataSource.setUrl("jdbc:mysql://localhost:3306/test?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF-8");
          dataSource.setUsername("root");
          dataSource.setPassword("123456");
          return dataSource;
      }
  
      @Bean
      @DependsOn("dataSource")
      public JdbcTemplate template(DataSource dataSource) {
          return new JdbcTemplate(dataSource);
      }
  
      public static void main(String[] args) {
          ApplicationContext ac = new AnnotationConfigApplicationContext(JavaConfig.class);
          IUserService bean = ac.getBean(IUserService.class);
          User user = new User();
          user.setName("灰灰");
          user.setAge(18);
          /*System.out.println(bean.addUser(user));
          System.out.println(bean.addUserInfo("huihui", "123456"));*/
          System.out.println(bean.transaction(user, "huihui", "123456"));
      }
  
  }
  
1.3 jdk 代理机制实现事务管理
- 新建【DbUtils】
  package com.gupao.utils;
  
  import java.sql.Connection;
  import java.sql.DriverManager;
  
  public class DbUtils {
  
      private static final String DRIVERNAME = "com.mysql.jdbc.Driver";
      private static final String URL = "jdbc:mysql://localhost:3306/test?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF-8";
      private static final String USERNAME = "root";
      private static final String PASSWORD = "123456";
  
      private static Connection conn = null;
  
      public static  Connection getConnection() {
          if(conn == null) {
              try {
                  Class.forName(DRIVERNAME);
                  conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
              } catch (Exception e) {
                  e.printStackTrace();
              }
          }
          return conn;
      }
  
  }
  
- 修改【UserDaoImpl】
  package com.gupao.dao.impl;
  
  import com.gupao.dao.IUserDao;
  import com.gupao.pojo.User;
  import com.gupao.utils.DbUtils;
  import org.springframework.beans.factory.annotation.Autowired;
  import org.springframework.jdbc.core.JdbcTemplate;
  import org.springframework.jdbc.core.RowMapper;
  import org.springframework.stereotype.Repository;
  import java.sql.*;
  import java.util.List;
  
  @Repository
  public class UserDaoImpl implements IUserDao {
  
      private final String DRIVERNAME = "com.mysql.jdbc.Driver";
      private final String URL = "jdbc:mysql://localhost:3306/test?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF-8";
      private final String USERNAME = "root";
      private final String PASSWORD = "123456";
  
      @Autowired
      private JdbcTemplate template;
      private String sql;
      private Connection conn = null;
      private PreparedStatement ps = null;
  
      public Integer addUser(User user) throws SQLException {
          /*sql = "insert into users(name, age) values(?, ?)";
          int iRet = template.update(sql, user.getName(), user.getAge());*/
          int iRet = 0;
          conn = DbUtils.getConnection();
          sql = "insert into users(name, age) values(?, ?)";
          ps = conn.prepareStatement(sql);
          ps.setString(1, user.getName());
          ps.setInt(2, user.getAge());
          iRet = ps.executeUpdate();
          return iRet;
      }
  
      public Integer addUserInfo(String userName, String passwrod) throws Exception {
          /*sql = "insert into user_info(username, password) values(?, ?)";
          int iRet = template.update(sql, userName, passwrod);*/
          int iRet = 0;
          conn = DbUtils.getConnection();
          sql = "insert into user_info(username, password) values(?, ?)";
          ps = conn.prepareStatement(sql);
          ps.setString(1, userName);
          ps.setString(2, passwrod);
          iRet = ps.executeUpdate();
          return iRet;
      }
  
      public Integer transaction(User user, String username, String password) throws Exception {
          int iRet = 0;
          conn = DbUtils.getConnection();
          sql = "insert into users(name, age) values(?, ?)";
          ps = conn.prepareStatement(sql);
          ps.setString(1, user.getName());
          ps.setInt(2, user.getAge());
          iRet = ps.executeUpdate();
          sql = "insert into user_info(username, password) values(?, ?)";
          ps = conn.prepareStatement(sql);
          ps.setString(1, username);
          ps.setString(2, password);
          iRet += ps.executeUpdate();
          return iRet;
      }
  
      public List<User> query() {
          sql = "select * from users order by id desc";
          List<User> list = template.query(sql, new RowMapper<User>() {
              public User mapRow(ResultSet resultSet, int i) throws SQLException {
                  User user = new User();
                  try {
                      user.setId(resultSet.getInt("id"));
                      user.setName(resultSet.getString("name"));
                      user.setAge(resultSet.getInt("age"));
                  } catch (SQLException e) {
                      e.printStackTrace();
                  }
                  return user;
              }
          });
          return list;
      }
  
  }

  
- 修改【IUserDao】
  package com.gupao.dao;
  
  import com.gupao.pojo.User;
  import java.sql.SQLException;
  import java.util.List;
  
  public interface IUserDao {
  
      public Integer addUser(User user) throws SQLException;
  
      public List<User> query();
  
      public Integer addUserInfo(String username, String password) throws Exception;
  
      public Integer transaction(User user, String username, String password) throws Exception;
  
  }
  
- 修改【UserServicImpl】
  package com.gupao.service.impl;
  
  import com.gupao.dao.IUserDao;
  import com.gupao.dao.impl.UserDaoImpl;
  import com.gupao.pojo.User;
  import com.gupao.service.IUserService;
  import org.springframework.beans.factory.annotation.Autowired;
  import org.springframework.stereotype.Service;
  import java.util.List;
  
  @Service
  public class UserServicImpl implements IUserService {
  
      //@Autowired
      private IUserDao userDao = new UserDaoImpl();
  
      public Integer addUser(User user) throws Exception {
          return userDao.addUser(user);
      }
  
      public List<User> query() {
          return userDao.query();
      }
  
      public Integer addUserInfo(String username, String password) throws Exception {
          return userDao.addUserInfo(username, password);
      }
  
      public Integer transaction(User user, String username, String password) throws Exception {
          //return userDao.tx(user, username, password);
          int iRet = 0;
          iRet = userDao.addUser(user);
          iRet += userDao.addUserInfo(username, password);
          return iRet;
      }
  
  }
  
- 修改【IUserService】
  package com.gupao.service;
  
  import com.gupao.pojo.User;
  import java.util.List;
  
  public interface IUserService {
  
      public Integer addUser(User user) throws Exception;
  
      public List<User> query();
  
      public Integer addUserInfo(String username, String password) throws Exception;
  
      public Integer transaction(User user, String username, String password) throws Exception;
  
  }

  
- 修改【JavaConfig】
  package com.gupao;
  
  import com.gupao.pojo.User;
  import com.gupao.service.IUserService;
  import com.gupao.service.impl.UserServicImpl;
  import com.gupao.utils.DbUtils;
  import org.springframework.context.ApplicationContext;
  import org.springframework.context.annotation.*;
  import org.springframework.jdbc.core.JdbcTemplate;
  import org.springframework.jdbc.datasource.DriverManagerDataSource;
  import javax.sql.DataSource;
  import java.lang.reflect.InvocationHandler;
  import java.lang.reflect.Method;
  import java.lang.reflect.Proxy;
  import java.sql.Connection;
  
  @Configuration
  @ComponentScan
  public class JavaConfig {
  
      @Bean
      public DataSource dataSource() {
          DriverManagerDataSource dataSource = new DriverManagerDataSource();
          dataSource.setDriverClassName("com.mysql.jdbc.Driver");
          dataSource.setUrl("jdbc:mysql://localhost:3306/test?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF-8");
          dataSource.setUsername("root");
          dataSource.setPassword("123456");
          return dataSource;
      }
  
      @Bean
      @DependsOn("dataSource")
      public JdbcTemplate template(DataSource dataSource) {
          return new JdbcTemplate(dataSource);
      }
  
      public static void main(String[] args) {
          /*ApplicationContext ac = new AnnotationConfigApplicationContext(JavaConfig.class);
          IUserService bean = ac.getBean(IUserService.class);
          User user = new User();
          user.setName("灰灰");
          user.setAge(18);
          *//*System.out.println(bean.addUser(user));
          System.out.println(bean.addUserInfo("huihui", "123456"));*//*
          System.out.println(bean.tx(user, "huihui", "123456"));*/
          // 获取目标对象
          final IUserService target = new UserServicImpl();
          // 获取代理对象
          IUserService proxy = (IUserService) Proxy.newProxyInstance(JavaConfig.class.getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {
              public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                  Connection conn = null;
                  try {
                      conn = DbUtils.getConnection();
                      conn.setAutoCommit(false);
                      method.invoke(target, args[0], args[1], args[2]);// 目标对象执行
                      System.out.println("执行成功 ... ... ");
                      conn.commit();
                  } catch (Exception e) {
                      e.printStackTrace();
                      System.out.println("执行失败,数据回滚 ... ");
                      conn.rollback();
                  } finally {
                      conn.close();
                  }
                  return null;
              }
          });
          User user = new User();
          user.setName("灰灰");
          user.setAge(18);
          try {
              proxy.transaction(user, "huihui", "123456");
          } catch (Exception e) {
              e.printStackTrace();
          }
      }
  
  }
  
1.4 基于 Aspect J 的方式自定义事务
- 定义自定义注解
  package com.gupao.annotation;
  
  import java.lang.annotation.Retention;
  import java.lang.annotation.RetentionPolicy;
  
  @Retention(RetentionPolicy.RUNTIME)
  public @interface GpTx {
  }
 
- 在【UserServicImpl】的【transaction】方法上添加【@GpTx】注解
  package com.gupao.service.impl;
  
  import com.gupao.annotation.GpTx;
  import com.gupao.dao.IUserDao;
  import com.gupao.dao.impl.UserDaoImpl;
  import com.gupao.pojo.User;
  import com.gupao.service.IUserService;
  import org.springframework.beans.factory.annotation.Autowired;
  import org.springframework.stereotype.Service;
  import java.util.List;
  
  @Service
  public class UserServicImpl implements IUserService {
  
      //@Autowired
      private IUserDao userDao = new UserDaoImpl();
  
      public Integer addUser(User user) throws Exception {
          return userDao.addUser(user);
      }
  
      public List<User> query() {
          return userDao.query();
      }
  
      public Integer addUserInfo(String username, String password) throws Exception {
          return userDao.addUserInfo(username, password);
      }
  
      @GpTx
      public Integer transaction(User user, String username, String password) throws Exception {
          //return userDao.tx(user, username, password);
          int iRet = 0;
          iRet = userDao.addUser(user);
          iRet += userDao.addUserInfo(username, password);
          return iRet;
      }
  
  }
  
- 自定义切面类【GpAspect】
  package com.gupao.aspect;
  
  import com.gupao.utils.DbUtils;
  import org.aspectj.lang.annotation.*;
  import org.springframework.stereotype.Component;
  import java.sql.Connection;
  import java.sql.SQLException;
  
  @Aspect
  @Component
  public class GpAspect {
  
      /**
       * 事务处理的前置方法
       * @throws SQLException
       */
      @Before(value = "@annotation(com.gupao.annotation.GpTx)")
      public void beforeTx() throws SQLException {
          Connection conn = DbUtils.getConnection();
          conn.setAutoCommit(false);
      }
  
      /**
       * 事务处理的后置通知
       * @throws SQLException
       */
      @AfterReturning(value = "@annotation(com.gupao.annotation.GpTx)")
      public void afterReturningTx() throws SQLException {
          Connection conn = DbUtils.getConnection();
          System.out.println("执行成功 ... ... ");
          conn.commit();
      }
  
      /**
       * 事务处理的最终通知
       * @throws SQLException
       */
      @After(value = "@annotation(com.gupao.annotation.GpTx)")
      public void afterTx() throws SQLException {
          Connection conn = DbUtils.getConnection();
          //conn.close();
      }
  
      @AfterThrowing(value = "@annotation(com.gupao.annotation.GpTx)")
      public void afterThrowingTx() throws SQLException {
          Connection conn = DbUtils.getConnection();
          System.out.println("失败回滚 ... ... ");
          conn.rollback();
      }
  }
  
- 【JavaConfig】添加【@EnableAspectJAutoProxy】类注解
  package com.gupao;
  
  import com.gupao.pojo.User;
  import com.gupao.service.IUserService;
  import com.gupao.service.impl.UserServicImpl;
  import com.gupao.utils.DbUtils;
  import org.springframework.context.ApplicationContext;
  import org.springframework.context.annotation.*;
  import org.springframework.jdbc.core.JdbcTemplate;
  import org.springframework.jdbc.datasource.DriverManagerDataSource;
  import javax.sql.DataSource;
  import java.lang.reflect.InvocationHandler;
  import java.lang.reflect.Method;
  import java.lang.reflect.Proxy;
  import java.sql.Connection;
  
  @Configuration
  @ComponentScan
  @EnableAspectJAutoProxy
  public class JavaConfig {
  
      @Bean
      public DataSource dataSource() {
          DriverManagerDataSource dataSource = new DriverManagerDataSource();
          dataSource.setDriverClassName("com.mysql.jdbc.Driver");
          dataSource.setUrl("jdbc:mysql://localhost:3306/test?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF-8");
          dataSource.setUsername("root");
          dataSource.setPassword("123456");
          return dataSource;
      }
  
      @Bean
      @DependsOn("dataSource")
      public JdbcTemplate template(DataSource dataSource) {
          return new JdbcTemplate(dataSource);
      }
  
      public static void main(String[] args) {
          /*ApplicationContext ac = new AnnotationConfigApplicationContext(JavaConfig.class);
          IUserService bean = ac.getBean(IUserService.class);
          User user = new User();
          user.setName("灰灰");
          user.setAge(18);
          *//*System.out.println(bean.addUser(user));
          System.out.println(bean.addUserInfo("huihui", "123456"));*//*
          System.out.println(bean.tx(user, "huihui", "123456"));*/
          // 获取目标对象
          final IUserService target = new UserServicImpl();
          // 获取代理对象
          IUserService proxy = (IUserService) Proxy.newProxyInstance(JavaConfig.class.getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {
              public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                  Connection conn = null;
                  try {
                      conn = DbUtils.getConnection();
                      conn.setAutoCommit(false);
                      method.invoke(target, args[0], args[1], args[2]);// 目标对象执行
                      System.out.println("执行成功 ... ... ");
                      conn.commit();
                  } catch (Exception e) {
                      e.printStackTrace();
                      System.out.println("执行失败,数据回滚 ... ");
                      conn.rollback();
                  } finally {
                      conn.close();
                  }
                  return null;
              }
          });
          User user = new User();
          user.setName("灰灰");
          user.setAge(18);
          try {
              proxy.transaction(user, "huihui", "123456");
          } catch (Exception e) {
              e.printStackTrace();
          }
      }
  
  }
  
- 添加【JavaConfigMain】
  package com.gupao;
  
  import com.gupao.pojo.User;
  import com.gupao.service.IUserService;
  import org.springframework.context.ApplicationContext;
  import org.springframework.context.annotation.AnnotationConfigApplicationContext;
  
  public class JavaConfigMain {
  
      public static void main(String[] args) throws Exception {
          ApplicationContext ac = new AnnotationConfigApplicationContext(JavaConfig.class);
          IUserService bean = ac.getBean(IUserService.class);
          User user = new User();
          user.setName("令狐");
          user.setAge(18);
          bean.transaction(user, "linghu", "123456");
      }
  
  }
  
1.5 Spring 中的事务实现
- 新建 Maven 工程,添加依赖
  <dependencies>
      <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-orm</artifactId>
          <version>5.1.17.RELEASE</version>
      </dependency>
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context</artifactId>
          <version>5.1.17.RELEASE</version>
      </dependency>
      <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
      <!-- 如果Mysql是8.0的就用这个驱动 -->
      <!--<dependency>
              <groupId>mysql</groupId>
              <artifactId>mysql-connector-java</artifactId>
              <version>8.0.16</version>
          </dependency>-->
      <!-- 如果Mysql是5.7的就用这个驱动 -->
      <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
          <version>5.1.38</version>
      </dependency>
      <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
      <dependency>
          <groupId>org.aspectj</groupId>
          <artifactId>aspectjweaver</artifactId>
          <version>1.9.1</version>
      </dependency>
      <!-- https://mvnrepository.com/artifact/commons-logging/commons-logging -->
      <dependency>
          <groupId>commons-logging</groupId>
          <artifactId>commons-logging</artifactId>
          <version>1.2</version>
      </dependency>
      <!-- https://mvnrepository.com/artifact/log4j/log4j -->
      <dependency>
          <groupId>log4j</groupId>
          <artifactId>log4j</artifactId>
          <version>1.2.17</version>
      </dependency>
      <!-- https://mvnrepository.com/artifact/logkit/logkit -->
      <dependency>
          <groupId>logkit</groupId>
          <artifactId>logkit</artifactId>
          <version>1.0.1</version>
      </dependency>
      <!-- https://mvnrepository.com/artifact/avalon-framework/avalon-framework -->
      <dependency>
          <groupId>avalon-framework</groupId>
          <artifactId>avalon-framework</artifactId>
          <version>4.1.5</version>
      </dependency>
  
  </dependencies>
  
- 新建【User】
  package com.gupao.pojo;
  
  public class User {
  
      private Integer id;
  
      private String userName;
  
      private Integer age;
  
      public Integer getId() {
          return id;
      }
  
      public void setId(Integer id) {
          this.id = id;
      }
  
      public String getUserName() {
          return userName;
      }
  
      public void setUserName(String userName) {
          this.userName = userName;
      }
  
      public Integer getAge() {
          return age;
      }
  
      public void setAge(Integer age) {
          this.age = age;
      }
  
      public User(Integer id, String userName, Integer age) {
          this.id = id;
          this.userName = userName;
          this.age = age;
      }
  
      public User(String userName, Integer age) {
          this.userName = userName;
          this.age = age;
      }
  }
  
- 新建【IUserDao】
  package com.gupao.dao;
  
  import com.gupao.pojo.User;
  
  public interface IUserDao {
  
      public Integer addUser(User user) throws Exception;
  
      public Integer updateUser(User user) throws Exception;
  
  }
  
- 新建【UserDaoImpl】
  package com.gupao.dao.impl;
  
  import com.gupao.dao.IUserDao;
  import com.gupao.pojo.User;
  import org.springframework.beans.factory.annotation.Autowired;
  import org.springframework.jdbc.core.JdbcTemplate;
  import org.springframework.stereotype.Repository;
  
  @Repository
  public class UserDaoImpl implements IUserDao {
  
      @Autowired
      private JdbcTemplate template;
  
      private String sql;
  
      public Integer addUser(User user) throws Exception {
          sql = "insert into users(name, age) values(?, ?)";
          return template.update(sql, user.getUserName(), user.getAge());
      }
  
      public Integer updateUser(User user) throws Exception {
          sql = "update users set name=?, age=? where id=?";
          return template.update(sql, user.getUserName(), user.getAge(), user.getId());
      }
  
  }
  
- 新建【IUserService】
  package com.gupao.service;
  
  import com.gupao.pojo.User;
  
  public interface IUserService {
  
      public Integer addUser(User user) throws Exception;
  
      public Integer updateUser(User user) throws Exception;
  
      public void transaction() throws Exception;
  }
  
- 新建【UserServiceImpl】

  package com.gupao.service.impl;
  
  import com.gupao.dao.IUserDao;
  import com.gupao.pojo.User;
  import com.gupao.service.IUserService;
  import org.springframework.beans.factory.annotation.Autowired;
  import org.springframework.stereotype.Service;
  
  @Service
  public class UserServiceImpl implements IUserService {
  
      @Autowired
      private IUserDao dao;
  
      public Integer addUser(User user) throws Exception {
          return dao.addUser(user);
      }
  
      public Integer updateUser(User user) throws Exception {
          return dao.updateUser(user);
      }
  
      public void transaction() throws Exception {
          User user = new User("清扬", 18);
          addUser(user);
          user.setId(1);
          user.setUserName("零一");
          updateUser(user);
      }
  
  }
  
- 【Resource】下新建【db.properties】
  jdbc_driver=com.mysql.jdbc.Driver
  jdbc_url=jdbc:mysql://localhost:3306/test?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF-8
  jdbc_username=root
  jdbc_password=123456
  
- 【Resource】下新建【applicationContext.xml】
  <beans xmlns="http://www.springframework.org/schema/beans"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns:p="http://www.springframework.org/schema/p"
         xmlns:context="http://www.springframework.org/schema/context"
         xmlns:aop="http://www.springframework.org/schema/aop"
         xmlns:tx="http://www.springframework.org/schema/tx"
         xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd">
  
      <context:component-scan base-package="com.gupao.*" />
  
      <!-- 加载数据配置文件 -->
      <context:property-placeholder location="db.properties" />
  
      <!-- 配置数据源 -->
      <bean class="org.springframework.jdbc.datasource.DriverManagerDataSource" id="dataSource">
          <property name="driverClassName" value="${jdbc_driver}" />
          <property name="url" value="${jdbc_url}" />
          <property name="username" value="${jdbc_username}" />
          <property name="password" value="${jdbc_password}" />
      </bean>
  
      <!-- 配置JdcbTemplate -->
      <bean class="org.springframework.jdbc.core.JdbcTemplate">
          <constructor-arg name="dataSource" ref="dataSource" />
      </bean>
  </beans>
  
- 新建【JavaConfig】
  package com.gupao;
  
  import com.gupao.service.IUserService;
  import org.springframework.context.ApplicationContext;
  import org.springframework.context.support.ClassPathXmlApplicationContext;
  
  public class JavaConfig {
  
      public static void main(String[] args) throws Exception {
          ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
          IUserService bean = ac.getBean(IUserService.class);
          bean.transaction();
      }
  
  }
 
1.5.1 基于 xml 文件
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd">

    <context:component-scan base-package="com.gupao.*" />

    <!-- 加载数据配置文件 -->
    <context:property-placeholder location="db.properties" />

    <!-- 配置数据源 -->
    <bean class="org.springframework.jdbc.datasource.DriverManagerDataSource" id="dataSource">
        <property name="driverClassName" value="${jdbc_driver}" />
        <property name="url" value="${jdbc_url}" />
        <property name="username" value="${jdbc_username}" />
        <property name="password" value="${jdbc_password}" />
    </bean>

    <!-- 配置JdcbTemplate -->
    <bean class="org.springframework.jdbc.core.JdbcTemplate">
        <constructor-arg name="dataSource" ref="dataSource" />
    </bean>

    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <tx:advice id="txAdvice" transaction-manager="txManager">
        <!-- the transactional semantics... -->
        <tx:attributes>
            <!-- all methods starting with 'get' are read-only -->
            <tx:method name="tran*" propagation="REQUIRED" isolation="DEFAULT"/>
            <!-- other methods use the default transaction settings (see below) -->
            <tx:method name="*"/>
        </tx:attributes>
    </tx:advice>

    <aop:config>
        <aop:pointcut id="tx" expression="execution(* com.gupao.service..*.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="tx"/>
    </aop:config>
</beans>
  
1.5.2 基于注解
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd">

    <context:component-scan base-package="com.gupao.*" />

    <!-- 加载数据配置文件 -->
    <context:property-placeholder location="db.properties" />

    <!-- 配置数据源 -->
    <bean class="org.springframework.jdbc.datasource.DriverManagerDataSource" id="dataSource">
        <property name="driverClassName" value="${jdbc_driver}" />
        <property name="url" value="${jdbc_url}" />
        <property name="username" value="${jdbc_username}" />
        <property name="password" value="${jdbc_password}" />
    </bean>

    <!-- 配置JdcbTemplate -->
    <bean class="org.springframework.jdbc.core.JdbcTemplate">
        <constructor-arg name="dataSource" ref="dataSource" />
    </bean>

    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!-- 开启事务的注解支持 -->
    <tx:annotation-driven transaction-manager="txManager" />
</beans>
  
- 添加【@Transactional】注解
package com.gupao.service.impl;

import com.gupao.dao.IUserDao;
import com.gupao.pojo.User;
import com.gupao.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class UserServiceImpl implements IUserService {

    @Autowired
    private IUserDao dao;

    public Integer addUser(User user) throws Exception {
        return dao.addUser(user);
    }

    public Integer updateUser(User user) throws Exception {
        return dao.updateUser(user);
    }

    @Transactional
    public void transaction() throws Exception {
        User user = new User("清扬", 18);
        addUser(user);
        user.setId(1);
        user.setUserName("零一");
        updateUser(user);
    }

}

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

方寸之间不太闲

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值