今日内容
  • Spring中的JdbcTemplate
  • 作业:Spring基于AOP的事务控制
  • Spring中的事务控制
    • 基于XML的
    • 基于注解的
一、JdbcTemplate
1、JdbcTemplate的概述和入门
持久层总图
  • JdbcTemplate的作用
    • 用于和数据库交互,实现对表的CRUD操作
  • 如何获取该对象
  • 对象中的常用方法
  1. package com.itheima.jdbcTemplate;
  2. import org.springframework.jdbc.core.JdbcTemplate;
  3. import org.springframework.jdbc.datasource.DriverManagerDataSource;
  4. import java.sql.DriverManager;
  5. /**
  6. * JdbcTemplate的最基本用法
  7. */
  8. public class JdbcTemplateDemo1 {
  9. public static void main(String[] args) {
  10. //准备数据源:c3p0、dbcp都可,今天介绍Spring的内置数据源
  11. DriverManagerDataSource ds = new DriverManagerDataSource();
  12. ds.setDriverClassName("com.mysql.jdbc.Driver");
  13. ds.setUrl("jdbc:mysql://localhost:3306/eesy");
  14. ds.setUsername("root");
  15. ds.setPassword("root");
  16. //1.创建JdbcTemplate对象
  17. JdbcTemplate jt = new JdbcTemplate();//可以加带数据源的构造方法
  18. //给jt设置数据源
  19. jt.setDataSource(ds);
  20. //2.执行操作
  21. jt.execute("insert into account(name,money) values('ccc',1000)");
  22. }
  23. }
2、JdbcTemplate在spring的ioc中使用
配置在类中修改比较麻烦,需要配置到配置文件中
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans
  5. http://www.springframework.org/schema/beans/spring-beans.xsd">
  6. <!--配置JdbcTemplate-->
  7. <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
  8. <property name="dataSource" ref="dataSource"></property>
  9. </bean>
  10. <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
  11. <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
  12. <property name="url" value="jdbc:mysql://localhost:3306/eesy"></property>
  13. <property name="username" value="root"></property>
  14. <property name="password" value="root"></property>
  15. </bean>
  16. </beans>
  1. package com.itheima.jdbcTemplate;
  2. import org.springframework.context.ApplicationContext;
  3. import org.springframework.context.support.ClassPathXmlApplicationContext;
  4. import org.springframework.jdbc.core.JdbcTemplate;
  5. import org.springframework.jdbc.datasource.DriverManagerDataSource;
  6. import java.sql.DriverManager;
  7. /**
  8. * JdbcTemplate的最基本用法
  9. */
  10. public class JdbcTemplateDemo1 {
  11. public static void main(String[] args) {
  12. //1.获取容器
  13. ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
  14. //2.获取对象
  15. JdbcTemplate jt = ac.getBean("jdbcTemplate",JdbcTemplate.class);
  16. //2.执行操作
  17. jt.execute("insert into account(name,money) values('ccc',1000)");
  18. }
  19. }
3、JdbcTemplate的CRUD操作
JdbcTemplate和queryRunner的区别
  1. package com.itheima.jdbcTemplate;
  2. import com.itheima.domain.Account;
  3. import org.springframework.context.ApplicationContext;
  4. import org.springframework.context.support.ClassPathXmlApplicationContext;
  5. import org.springframework.jdbc.core.BeanPropertyRowMapper;
  6. import org.springframework.jdbc.core.JdbcTemplate;
  7. import org.springframework.jdbc.core.RowMapper;
  8. import java.sql.ResultSet;
  9. import java.sql.SQLException;
  10. import java.util.List;
  11. /**
  12. * JdbcTemplate的CRUD操作
  13. */
  14. public class JdbcTemplateDemo3 {
  15. public static void main(String[] args) {
  16. //1.获取容器
  17. ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
  18. //2.获取对象
  19. JdbcTemplate jt = ac.getBean("jdbcTemplate",JdbcTemplate.class);
  20. //2.可带参数的执行操作(单表)
  21. //保存
  22. //jt.update("insert into account(name,money) values (?,?)","ssss",333f);
  23. //更新
  24. //jt.update("update account set name=?,money=? where id=?","ssss",333f,5);
  25. //删除
  26. //jt.update("delete from account where id=?",1);
  27. //查询所有
  28. //queryRunner提供的
  29. //List<Account> accounts = jt.query("select * from account where money > ?",new AccountRowMapper(),100f);
  30. //Spring提供的
  31. /*List<Account> accounts1 = jt.query("select * from account where money > ?",new BeanPropertyRowMapper<Account>(Account.class),100f);
  32. for (Account account : accounts1) {
  33. System.out.println(account);
  34. }*/
  35. //查询一个
  36. /*List<Account> account = jt.query("select * from account where id = ?",new BeanPropertyRowMapper<Account>(Account.class),1);
  37. System.out.println(account.isEmpty()?"没有内容":account.get(0));*/
  38. //使用聚合函数查询,返回一行一列,但不加groupby子句
  39. //int count = jt.queryForObject("select count(*) from account where money >= ?",Integer.class,100f);
  40. Long count = jt.queryForObject("select count(*) from account where money >= ?",Long.class,100f);
  41. //大数据,常用long接收
  42. System.out.println(count);
  43. }
  44. }
  45. /**
  46. * 定义Account的封装策略
  47. */
  48. class AccountRowMapper implements RowMapper<Account> {
  49. /**
  50. * 把结果集中的数据封装到Account中,然后由Spring把每个Account加入到集合中
  51. * @param resultSet
  52. * @param i
  53. * @return
  54. * @throws SQLException
  55. */
  56. @Override
  57. public Account mapRow(ResultSet resultSet, int i) throws SQLException {
  58. Account account = new Account();
  59. account.setId(resultSet.getInt("id"));
  60. account.setName(resultSet.getString("name"));
  61. account.setMoney(resultSet.getFloat("money"));
  62. return account;
  63. }
  64. }
4、JdbcTemplate在Dao中的使用
  1. <!--配置账户的持久层-->
  2. <bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl">
  3. <property name="jdbcTemplate" ref="jdbcTemplate"></property>
  4. </bean>
  5. <!--配置JdbcTemplate-->
  6. <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
  7. <property name="dataSource" ref="dataSource"></property>
  8. </bean>
  1. package com.itheima.dao.impl;
  2. import com.itheima.dao.IAccountDao;
  3. import com.itheima.domain.Account;
  4. import org.springframework.jdbc.core.BeanPropertyRowMapper;
  5. import org.springframework.jdbc.core.JdbcTemplate;
  6. import java.util.List;
  7. /**
  8. * 账户的持久层实现类
  9. */
  10. public class AccountDaoImpl implements IAccountDao {
  11. private JdbcTemplate jdbcTemplate;
  12. public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
  13. this.jdbcTemplate = jdbcTemplate;
  14. }
  15. @Override
  16. public Account findAccounById(Integer accountId) {
  17. List<Account> accounts = jdbcTemplate.query("select * from account where id = ?",new BeanPropertyRowMapper<Account>(Account.class),accountId);
  18. return accounts.isEmpty()?null:accounts.get(0);
  19. }
  20. @Override
  21. public Account findAccountByName(String accounName) {
  22. List<Account> accounts = jdbcTemplate.query("select * from account where name = ?",new BeanPropertyRowMapper<Account>(Account.class),accounName);
  23. if (accounts.isEmpty()){
  24. return null;
  25. }
  26. if (accounts.size()>1){
  27. throw new RuntimeException("结果集不一致");
  28. }
  29. return accounts.get(0);
  30. }
  31. @Override
  32. public void updateAccount(Account account) {
  33. jdbcTemplate.update("update account set name=?,money=? where id=?",account.getName(),account.getMoney(),account.getId());
  34. }
  35. }
  1. package com.itheima.jdbcTemplate;
  2. import com.itheima.dao.IAccountDao;
  3. import com.itheima.domain.Account;
  4. import org.springframework.context.ApplicationContext;
  5. import org.springframework.context.support.ClassPathXmlApplicationContext;
  6. import org.springframework.jdbc.core.JdbcTemplate;
  7. /**
  8. * JdbcTemplate的最基本用法
  9. */
  10. public class JdbcTemplateDemo4 {
  11. public static void main(String[] args) {
  12. //1.获取容器
  13. ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
  14. //2.获取对象
  15. IAccountDao accountDao =ac.getBean("accountDao",IAccountDao.class);
  16. Account account = accountDao.findAccounById(5);
  17. System.out.println(account);
  18. account.setMoney(10000f);
  19. accountDao.updateAccount(account);
  20. }
  21. }
5、JdbcDaoSupport的使用以及Dao的两种编写方式
不同dao的重复代码
使用注解配置和使用JdbcDaoSupport冲突
  1. /**
  2. * 账户的持久层实现类
  3. */
  4. @Repository
  5. public class AccountDaoImpl2 implements IAccountDao {
  6. @Autowired
  7. private JdbcTemplate jdbcTemplate;
  8. /*public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
  9. this.jdbcTemplate = jdbcTemplate;
  10. }*/
  11. @Override
  12. public Account findAccounById(Integer accountId) {
  13. List<Account> accounts = jdbcTemplate.query("select * from account where id = ?",new BeanPropertyRowMapper<Account>(Account.class),accountId);
  14. return accounts.isEmpty()?null:accounts.get(0);
  15. }
  1. package com.itheima.dao.impl;
  2. import org.springframework.jdbc.core.JdbcTemplate;
  3. import javax.sql.DataSource;
  4. /**
  5. * 此类用于抽取dao中的重复代码
  6. */
  7. public class JdbcDaoSupport {
  8. private JdbcTemplate jdbcTemplate;
  9. public JdbcTemplate getJdbcTemplate() {
  10. return jdbcTemplate;
  11. }
  12. public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
  13. this.jdbcTemplate = jdbcTemplate;
  14. }
  15. public DataSource getDateSource() {
  16. return dateSource;
  17. }
  18. public void setDateSource(DataSource dateSource) {
  19. //this.dateSource = dateSource;
  20. if(jdbcTemplate == null){
  21. jdbcTemplate = createJdbcTemplate(dateSource);
  22. }
  23. }
  24. private JdbcTemplate createJdbcTemplate(DataSource dateSource) {
  25. return new JdbcTemplate(dateSource);//支持构造函数和set方法
  26. }
  27. private DataSource dateSource;
  28. }
  1. /**
  2. * 账户的持久层实现类
  3. */
  4. public class AccountDaoImpl extends JdbcDaoSupport implements IAccountDao {
  5. /*private JdbcTemplate jdbcTemplate;
  6. public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
  7. this.jdbcTemplate = jdbcTemplate;
  8. }*/
  9. @Override
  10. public Account findAccounById(Integer accountId) {
  11. List<Account> accounts = getJdbcTemplate() .query("select * from account where id = ?",new BeanPropertyRowMapper<Account>(Account.class),accountId);
  12. return accounts.isEmpty()?null:accounts.get(0);
  13. }
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans
  5. http://www.springframework.org/schema/beans/spring-beans.xsd">
  6. <!--配置账户的持久层-->
  7. <bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl">
  8. <property name="dateSource" ref="dataSource"></property>
  9. </bean>
  10. <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
  11. <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
  12. <property name="url" value="jdbc:mysql://localhost:3306/eesy"></property>
  13. <property name="username" value="root"></property>
  14. <property name="password" value="root"></property>
  15. </bean>
  16. </beans>
二、作业:AOP实现事务控制
1、基于XML的AOP实现事务控制
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:aop="http://www.springframework.org/schema/aop"
  5. xsi:schemaLocation="http://www.springframework.org/schema/beans
  6. http://www.springframework.org/schema/beans/spring-beans.xsd
  7. http://www.springframework.org/schema/aop
  8. http://www.springframework.org/schema/aop/spring-aop.xsd">
  9. <!-- 配置Service -->
  10. <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
  11. <!-- 注入dao对象 -->
  12. <property name="accountDao" ref="accountDao"></property>
  13. </bean>
  14. <!--配置dao对象-->
  15. <bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl">
  16. <!--注入QueryRunner-->
  17. <property name="runner" ref="runner"></property>
  18. <!--注入ConnectionUtils-->
  19. <property name="connectionUtils" ref="connectionUtils"></property>
  20. </bean>
  21. <!--配置QueryRunner对象-->
  22. <!--不再提供Connection对象,没有数据源,不会从数据源中获取连接-->
  23. <bean id="runner" class="org.apache.commons.dbutils.QueryRunner" scope="prototype"></bean>
  24. <!--配置数据源-->
  25. <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
  26. <!--连接数据库的必备信息-->
  27. <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
  28. <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/eesy02"></property>
  29. <property name="user" value="root"></property>
  30. <property name="password" value="root"></property>
  31. </bean>
  32. <!--配置Connection的工具类-ConnectionUtils-->
  33. <bean id="connectionUtils" class="com.itheima.utils.ConnectionUtils">
  34. <!--注入数据源的配置-->
  35. <property name="dataSource" ref="dataSource"></property>
  36. </bean>
  37. <!--配置事务管理器-->
  38. <bean id="txManager" class="com.itheima.utils.TransactionManager">
  39. <!--注入ConnectionUtils-->
  40. <property name="connectionUtils" ref="connectionUtils"></property>
  41. </bean>
  42. <!--配置AOP-->
  43. <aop:config>
  44. <aop:aspect id="txAdvice" ref="txManager">
  45. <!--配置通用的切入点表达式-->
  46. <aop:pointcut id="pt1" expression="execution(* com.itheima.service.impl.*.*(..))"/>
  47. <!--配置前置通知:开启事务-->
  48. <aop:before method="beginTransaction" pointcut-ref="pt1"></aop:before>
  49. <!--配置后置通知:提交事务-->
  50. <aop:after-returning method="commit" pointcut-ref="pt1"></aop:after-returning>
  51. <!--配置异常通知:回滚事务-->
  52. <aop:after-throwing method="rollback" pointcut-ref="pt1"></aop:after-throwing>
  53. <!--配置最终通知:释放连接-->
  54. <aop:after method="release" pointcut-ref="pt1"></aop:after>
  55. </aop:aspect>
  56. </aop:config>
  57. </beans>
2、基于注解的AOP实现事务控制及问题分析1
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:aop="http://www.springframework.org/schema/aop"
  5. xmlns:context="http://www.springframework.org/schema/context"
  6. xsi:schemaLocation="http://www.springframework.org/schema/beans
  7. http://www.springframework.org/schema/beans/spring-beans.xsd
  8. http://www.springframework.org/schema/aop
  9. http://www.springframework.org/schema/aop/spring-aop.xsd
  10. http://www.springframework.org/schema/context
  11. http://www.springframework.org/schema/context/spring-context.xsd">
  12. <!--配置Spring创建容器时要扫描的包-->
  13. <context:component-scan base-package="com.itheima"></context:component-scan>
  14. <!-- 配置Service -->
  15. <!--配置QueryRunner对象-->
  16. <!--不再提供Connection对象,没有数据源,不会从数据源中获取连接-->
  17. <bean id="runner" class="org.apache.commons.dbutils.QueryRunner" scope="prototype"></bean>
  18. <!--配置数据源-->
  19. <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
  20. <!--连接数据库的必备信息-->
  21. <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
  22. <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/eesy02"></property>
  23. <property name="user" value="root"></property>
  24. <property name="password" value="root"></property>
  25. </bean>
  26. <!--开启Spring对注解aop的支持-->
  27. <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
  28. </beans>
  1. package com.itheima.utils;
  2. import org.aspectj.lang.annotation.*;
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.stereotype.Component;
  5. import java.sql.SQLException;
  6. /**
  7. * 和事务管理相关的工具类,包含开启事务、提交事务、回滚事务和释放连接
  8. */
  9. @Component("txManager")
  10. public class TransactionManager {
  11. //获取当前线程上的Connection
  12. @Autowired
  13. private ConnectionUtils connectionUtils;
  14. @Pointcut("execution(* com.itheima.*.*(..))")
  15. private void pt1(){}
  16. /**
  17. * 开启事务
  18. */
  19. @Before("pt1")
  20. public void beginTransaction(){
  21. try {
  22. connectionUtils.getThreadConnection().setAutoCommit(true);
  23. } catch (Exception e) {
  24. e.printStackTrace();
  25. }
  26. }
  27. /**
  28. * 提交事务
  29. */
  30. @AfterReturning("pt1")
  31. public void commit(){
  32. try {
  33. connectionUtils.getThreadConnection().commit();
  34. } catch (Exception e) {
  35. e.printStackTrace();
  36. }
  37. }
  38. /**
  39. * 回滚事务
  40. */
  41. @AfterThrowing("pt1")
  42. public void rollback(){
  43. try {
  44. connectionUtils.getThreadConnection().rollback();
  45. } catch (Exception e) {
  46. e.printStackTrace();
  47. }
  48. }
  49. /**
  50. * 释放连接
  51. */
  52. @After("pt1")
  53. public void release(){
  54. try {
  55. connectionUtils.getThreadConnection().close();//并不是真正关闭连接,而是还回连接池中
  56. connectionUtils.removeConnection();//进行线程的解绑
  57. } catch (Exception e) {
  58. e.printStackTrace();
  59. }
  60. }
  61. }
  1. package com.itheima.utils;
  2. import org.springframework.beans.factory.annotation.Autowired;
  3. import org.springframework.stereotype.Component;
  4. import javax.sql.DataSource;
  5. import java.sql.Connection;
  6. import java.sql.SQLException;
  7. /**
  8. * 连接的工具类,用于从数据源中获取一个连接,并且实现和线程的绑定
  9. */
  10. @Component("connectionUtils")
  11. public class ConnectionUtils {
  12. private ThreadLocal<Connection> tl = new ThreadLocal<Connection>();
  13. @Autowired
  14. private DataSource dataSource;
  15. /**
  16. * 获取当前线程上的连接
  17. */
  18. public Connection getThreadConnection(){
  19. try {
  20. //1.先从ThreadLocal上获取
  21. Connection conn = tl.get();
  22. //2.判断当前线程上是否有连接
  23. if (conn == null){
  24. //3.从数据源中获取一个连接,并且和线程绑定,存入ThreadLocal中
  25. conn = dataSource.getConnection();
  26. tl.set(conn);
  27. }
  28. //4.返回当前线程上的连接
  29. return conn;
  30. } catch (Exception e) {
  31. throw new RuntimeException(e);
  32. }
  33. }
  34. /**
  35. * 把连接和线程解绑
  36. */
  37. public void removeConnection(){
  38. tl.remove();
  39. }
  40. }
3、基于注解的AOP实现事务控制及问题分析2
  1. package com.itheima.service.impl;
  2. import com.itheima.dao.IAccountDao;
  3. import com.itheima.domain.Account;
  4. import com.itheima.service.IAccountService;
  5. import com.itheima.utils.TransactionManager;
  6. import org.springframework.beans.factory.annotation.Autowired;
  7. import org.springframework.stereotype.Service;
  8. import java.util.List;
  9. /**
  10. * 账户的业务层实现类
  11. * 事务控制应当在业务层
  12. */
  13. @Service("accountService")
  14. public class AccountServiceImpl implements IAccountService {
  15. /**
  16. * 每次获取连接,无法实现事务控制
  17. */
  18. @Autowired
  19. private IAccountDao accountDao;
  20. @Override
  21. public List<Account> findAllAccount() {
  22. return accountDao.findAllAccount();
  23. }
  24. @Override
  25. public Account findAccountById(Integer accountId) {
  26. //2.执行操作
  27. return accountDao.findAccountById(accountId);
  28. }
  29. @Override
  30. public void saveAccount(Account account) {
  31. accountDao.saveAccount(account);
  32. }
  33. @Override
  34. public void updateAccount(Account account) {
  35. accountDao.updateAccount(account);
  36. }
  37. @Override
  38. public void deleteAccount(Integer accountId) {
  39. accountDao.deleteAccount(accountId);
  40. }
  41. @Override
  42. public void transfer(String sourceName, String targetName, Float money) {
  43. System.out.println("transfer开始执行");
  44. //2.1根据名称查询转出账户
  45. Account source = accountDao.findAccountByName(sourceName);
  46. //2.2根据名称查询转入账户
  47. Account target = accountDao.findAccountByName(targetName);
  48. //2.3转出账户金额减少
  49. source.setMoney(source.getMoney() - money);
  50. //2.4.转入账户金额增加
  51. target.setMoney(target.getMoney() + money);
  52. //int i = 1 / 0;
  53. //2.5.更新转出账户
  54. accountDao.updateAccount(source);
  55. //2.6.更新转入账户
  56. accountDao.updateAccount(target);
  57. //3.提交事务
  58. //txManager.commit();
  59. }
  60. }
  1. package com.itheima.utils;
  2. import org.aspectj.lang.ProceedingJoinPoint;
  3. import org.aspectj.lang.annotation.*;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.stereotype.Component;
  6. import java.sql.SQLException;
  7. /**
  8. * 和事务管理相关的工具类,包含开启事务、提交事务、回滚事务和释放连接
  9. */
  10. @Component("txManager")
  11. public class TransactionManager {
  12. //获取当前线程上的Connection
  13. @Autowired
  14. private ConnectionUtils connectionUtils;
  15. @Pointcut("execution(* com.itheima.*.*(..))")
  16. private void pt1(){}
  17. /**
  18. * 开启事务
  19. */
  20. public void beginTransaction(){
  21. try {
  22. connectionUtils.getThreadConnection().setAutoCommit(true);
  23. } catch (Exception e) {
  24. e.printStackTrace();
  25. }
  26. }
  27. /**
  28. * 提交事务
  29. */
  30. @AfterReturning("pt1")
  31. public void commit(){
  32. try {
  33. connectionUtils.getThreadConnection().commit();
  34. } catch (Exception e) {
  35. e.printStackTrace();
  36. }
  37. }
  38. /**
  39. * 回滚事务
  40. */
  41. public void rollback(){
  42. try {
  43. connectionUtils.getThreadConnection().rollback();
  44. } catch (Exception e) {
  45. e.printStackTrace();
  46. }
  47. }
  48. /**
  49. * 释放连接
  50. */
  51. public void release(){
  52. try {
  53. connectionUtils.getThreadConnection().close();//并不是真正关闭连接,而是还回连接池中
  54. connectionUtils.removeConnection();//进行线程的解绑
  55. } catch (Exception e) {
  56. e.printStackTrace();
  57. }
  58. }
  59. @Around("pt1")
  60. public Object aroundAdvice(ProceedingJoinPoint pjp){
  61. Object rtValue = null;
  62. try {
  63. //1.获取参数
  64. Object[] args = pjp.getArgs();
  65. //2.开启事务
  66. this.beginTransaction();
  67. //3.执行方法
  68. rtValue = pjp.proceed(args);
  69. //4.提交事务
  70. this.commit();
  71. //返回结果
  72. return rtValue;
  73. } catch (Throwable e) {
  74. //5.回滚事务
  75. this.rollback();
  76. throw new RuntimeException(e);
  77. } finally {
  78. //6.释放资源
  79. this.release();
  80. }
  81. }
  82. }
使用环绕通知可以解决回滚数据不改变@Around("pt1")
三、Spring中的事务控制
1、spring中事务控制的一组API
2、spring事务控制的代码准备
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans
  5. http://www.springframework.org/schema/beans/spring-beans.xsd">
  6. <!--配置业务层-->
  7. <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
  8. <property name="accountDao" ref="accountDao"></property>
  9. </bean>
  10. <!--配置账户的持久层-->
  11. <bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl">
  12. <!-- <property name="jdbcTemplate" ref="jdbcTemplate"></property>-->
  13. <property name="dataSource" ref="dataSource"></property>
  14. </bean>
  15. <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
  16. <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
  17. <property name="url" value="jdbc:mysql://localhost:3306/eesy"></property>
  18. <property name="username" value="root"></property>
  19. <property name="password" value="root"></property>
  20. </bean>
  21. </beans>
  1. import java.util.List;
  2. /**
  3. * 使用Junit单元测试:测试我们的配置
  4. */
  5. @RunWith(SpringJUnit4ClassRunner.class)
  6. @ContextConfiguration(locations = {"classpath:bean.xml"})
  7. public class AccountServiceTest {
  8. @Autowired
  9. private IAccountService as;
  10. @Test
  11. public void testTransfer(){
  12. as.transfer("aaa","bbb",100f);
  13. }
  14. }
3、spring基于XML的声明式事务控制-配置步骤
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:aop="http://www.springframework.org/schema/aop"
  5. xmlns:tx="http://www.springframework.org/schema/tx"
  6. xsi:schemaLocation="
  7. http://www.springframework.org/schema/beans
  8. http://www.springframework.org/schema/beans/spring-beans.xsd
  9. http://www.springframework.org/schema/tx
  10. http://www.springframework.org/schema/tx/spring-tx.xsd
  11. http://www.springframework.org/schema/aop
  12. http://www.springframework.org/schema/aop/spring-aop.xsd">
  13. <!--配置业务层-->
  14. <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
  15. <property name="accountDao" ref="accountDao"></property>
  16. </bean>
  17. <!--配置账户的持久层-->
  18. <bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl">
  19. <!-- <property name="jdbcTemplate" ref="jdbcTemplate"></property>-->
  20. <property name="dataSource" ref="dataSource"></property>
  21. </bean>
  22. <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
  23. <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
  24. <property name="url" value="jdbc:mysql://localhost:3306/eesy"></property>
  25. <property name="username" value="root"></property>
  26. <property name="password" value="root"></property>
  27. </bean>
  28. <!--Spring中基于XML的声明式事务配置步骤
  29. 1、配置事务管理器
  30. 2、配置事务的通知
  31. 此时需要导入事务的约束:tx名称空间和约束,同时也需要aop的
  32. 使用tx:advice标签配置事务通知
  33. 属性:
  34. id:给事务通知起一个唯一标识
  35. transaction-manager:给事务通知提供一个事务管理器引用
  36. 3、配置AOP中的通用切入点表达式
  37. 4、建立事务通知和切入点表达式的对应关系
  38. 5、配置事务的属性
  39. 在事务的通知tx:advice标签的内部配置
  40. -->
  41. <!--配置事务管理器-->
  42. <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  43. <property name="dataSource" ref="dataSource"></property>
  44. </bean>
  45. <!--配置事务通知的标签-->
  46. <tx:advice id="txAdvice" transaction-manager="transactionManager">
  47. <!--配置事务的属性-->
  48. <tx:attributes>
  49. <!--标识transfer是业务层接口的方法,其需要一些属性
  50. isolation="" 指定事务的隔离级别,默认是default,表示是数据库的默认隔离级别
  51. no-rollback-for="" 用于指定一个异常,当产生该异常时,事务不会滚 ,产生其他异常时,事务回滚。没有默认值,表示任何异常都回滚
  52. propagation="" 用于指定事务的传播行为,默认是REQUIRED,表示一定会有事务,增删改的选择,查询方法可以选择SUPPORT
  53. read-only="" 指定事务是否只读,只有查询才能设置为true,默认为false表示读写
  54. rollback-for="" 用于指定一个异常,当产生异常时,事务回滚。产生其他异常时,事务不回滚,没有默认值,表示任何异常都会滚
  55. timeout="" 指定事务的超时时间,默认值是-1,表示永不超时,如果指定了数值,以秒为单位
  56. -->
  57. <tx:method name="*" read-only="false" propagation="REQUIRED"/>
  58. <!--指定查询方法-->
  59. <tx:method name="find*" propagation="SUPPORTS" read-only="true"></tx:method>
  60. </tx:attributes>
  61. </tx:advice>
  62. <!--配置AOP-->
  63. <aop:config>
  64. <!--配置切入点表达式-->
  65. <aop:pointcut id="pt1" expression="execution(* com.itheima.*.*(..))"/>
  66. <!--建立切入点表达式和事务通知的对应关系-->
  67. <aop:advisor advice-ref="txAdvice" pointcut-ref="pt1"></aop:advisor>
  68. </aop:config>
  69. </beans>
4、spring基于注解的声明式事务控制
先把IOC改为注解
修改名称空间
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:aop="http://www.springframework.org/schema/aop"
  5. xmlns:tx="http://www.springframework.org/schema/tx"
  6. xmlns:context="http://www.springframework.org/schema/context"
  7. xsi:schemaLocation="http://www.springframework.org/schema/beans
  8. http://www.springframework.org/schema/beans/spring-beans.xsd
  9. http://www.springframework.org/schema/tx
  10. http://www.springframework.org/schema/tx/spring-tx.xsd
  11. http://www.springframework.org/schema/aop
  12. http://www.springframework.org/schema/aop/spring-aop.xsd
  13. http://www.springframework.org/schema/context
  14. http://www.springframework.org/schema/context/spring-context.xsd">
  15. <!--配置业务层-->
  16. <!--配置spring创建容器时要扫描的包-->
  17. <context:component-scan base-package="com.itheima"></context:component-scan>
  18. <!--配置JdbcTemplate-->
  19. <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
  20. <property name="dataSource" ref="dataSource"></property>
  21. </bean>
  22. <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
  23. <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
  24. <property name="url" value="jdbc:mysql://localhost:3306/eesy02"></property>
  25. <property name="username" value="root"></property>
  26. <property name="password" value="root"></property>
  27. </bean>
  28. <!--Spring中基于注解的声明式事务配置步骤
  29. 1、配置事务管理器
  30. 2、开启Spring对注解事务的支持
  31. 3、在需要事务支持的地方使用@Transactional注解
  32. 4、建立事务通知和切入点表达式的对应关系
  33. 5、配置事务的属性
  34. 在事务的通知tx:advice标签的内部配置
  35. -->
  36. <!--配置事务管理器-->
  37. <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  38. <property name="dataSource" ref="dataSource"></property>
  39. </bean>
  40. <!--开启Spring对注解事务的支持-->
  41. <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
  42. </beans>
  1. package com.itheima.service.impl;
  2. import com.itheima.dao.IAccountDao;
  3. import com.itheima.domain.Account;
  4. import com.itheima.service.IAccountService;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.stereotype.Service;
  7. import org.springframework.transaction.annotation.Propagation;
  8. import org.springframework.transaction.annotation.Transactional;
  9. @Service("accountService")
  10. @Transactional(propagation = Propagation.SUPPORTS,readOnly = true)//只读型事务控制
  11. public class AccountServiceImpl implements IAccountService {
  12. @Autowired
  13. private IAccountDao accountDao;
  14. @Override
  15. public Account findAccountById(Integer accountId) {
  16. return accountDao.findAccountById(accountId);
  17. }
  18. //需要的是读写型事务控制
  19. @Transactional(propagation = Propagation.REQUIRED,readOnly = false)//读写型
  20. //xml一劳永逸
  21. @Override
  22. public void transfer(String sourceName, String targetName, Float money) {
  23. System.out.println("transfer开始执行");
  24. //2.1根据名称查询转出账户
  25. Account source = accountDao.findAccountByName(sourceName);
  26. //2.2根据名称查询转入账户
  27. Account target = accountDao.findAccountByName(targetName);
  28. //2.3转出账户金额减少
  29. source.setMoney(source.getMoney() - money);
  30. //2.4.转入账户金额增加
  31. target.setMoney(target.getMoney() + money);
  32. //2.5.更新转出账户
  33. accountDao.updateAccount(source);
  34. //2.6.更新转入账户
  35. accountDao.updateAccount(target);
  36. //int i = 1 / 0;
  37. //3.提交事务
  38. //txManager.commit();
  39. }
  40. }
  1. /**
  2. * 账户的持久层实现类
  3. */
  4. @Repository("accountDao")
  5. public class AccountDaoImpl implements IAccountDao {
  6. @Autowired
  7. private JdbcTemplate jdbcTemplate;
  8. public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
  9. this.jdbcTemplate = jdbcTemplate;
  10. }
5、spring基于纯注解的声明式事务控制
注解IOC和注解事务进行整合
  1. jdbc.driver=com.mysql.jdbc.Driver
  2. jdbc.url=jdbc:mysql://localhost:3306/eesy02
  3. jdbc.username=root
  4. jdbc.password=root
  5. package config;
  6. import org.springframework.beans.factory.annotation.Value;
  7. import org.springframework.context.annotation.Bean;
  8. import org.springframework.jdbc.core.JdbcTemplate;
  9. import org.springframework.jdbc.datasource.DriverManagerDataSource;
  10. import javax.sql.DataSource;
  11. /**
  12. * 和连接数据库相关的配置类
  13. */
  14. public class JdbcConfig {
  15. @Value("${jdbc.driver}")
  16. private String driver;
  17. @Value("${jdbc.url}")
  18. private String url;
  19. @Value("${jdbc.username}")
  20. private String username;
  21. @Value("${jdbc.password}")
  22. private String password;
  23. /**
  24. * 创建JdbcTemplate对象
  25. * @param dataSource
  26. * @return
  27. */
  28. //进入容器需要bean注解
  29. @Bean(name="jdbcTemplate")
  30. public JdbcTemplate createJdbcTemplate(DataSource dataSource){
  31. return new JdbcTemplate(dataSource);
  32. }
  33. /**
  34. * 创建一个数据源对象
  35. * @return
  36. */
  37. @Bean(name="dataSource")
  38. public DataSource createDatasouce(){
  39. DriverManagerDataSource ds = new DriverManagerDataSource();
  40. ds.setDriverClassName(driver);
  41. ds.setUrl(url);
  42. ds.setUsername(username);
  43. ds.setPassword(password);
  44. return ds;
  45. }
  46. }
  1. package config;
  2. import org.springframework.context.annotation.Bean;
  3. import org.springframework.jdbc.datasource.DataSourceTransactionManager;
  4. import org.springframework.transaction.PlatformTransactionManager;
  5. import javax.sql.DataSource;
  6. /**
  7. * 和事务相关的配置类
  8. */
  9. public class TransactionConfig {
  10. /**
  11. * 用于创建事务管理器对象
  12. * @param dataSource
  13. * @return
  14. */
  15. @Bean(name="transactionManager")
  16. public PlatformTransactionManager createTransactionManager(DataSource dataSource){
  17. return new DataSourceTransactionManager(dataSource);
  18. }
  19. }
  1. package config;
  2. import org.springframework.context.annotation.ComponentScan;
  3. import org.springframework.context.annotation.Configuration;
  4. import org.springframework.context.annotation.Import;
  5. import org.springframework.context.annotation.PropertySource;
  6. import org.springframework.transaction.annotation.EnableTransactionManagement;
  7. /**
  8. * Spring的配置类,相当于bean.xml
  9. */
  10. @Configuration
  11. @ComponentScan("com.itheima")
  12. @Import({JdbcConfig.class,TransactionConfig.class})
  13. @PropertySource("jdbcConfig.properties")
  14. @EnableTransactionManagement //开启事务注解的支持
  15. public class SpringConfiguration {
  16. }
6、spring编程式事务控制-了解
实际开发中,不常使用
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans
  5. http://www.springframework.org/schema/beans/spring-beans.xsd">
  6. <!--配置业务层-->
  7. <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
  8. <property name="accountDao" ref="accountDao"></property>
  9. <property name="transactionTemplate" ref="transactionTemplate"></property>
  10. </bean>
  11. <!--配置账户的持久层-->
  12. <bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl">
  13. <!-- <property name="jdbcTemplate" ref="jdbcTemplate"></property>-->
  14. <property name="dataSource" ref="dataSource"></property>
  15. </bean>
  16. <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
  17. <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
  18. <property name="url" value="jdbc:mysql://localhost:3306/eesy02"></property>
  19. <property name="username" value="root"></property>
  20. <property name="password" value="root"></property>
  21. </bean>
  22. <!--配置事务管理器-->
  23. <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  24. <property name="dataSource" ref="dataSource"></property>
  25. <!--注入连接池数据源-->
  26. </bean>
  27. <!--配置事务模板对象-->
  28. <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
  29. <property name="transactionManager" ref="transactionManager"></property>
  30. </bean>
  31. </beans>
7、spring5新特性的介绍
修改jdk版本


Spring04:JdbcTemplate及事务控制(AOP、XML、注解)的更多相关文章

  1. Spring jdbctemplate和事务管理器 全注解配置 不使用xml

    /** * spring的配置类,相当于bean.xml */@Configuration//@Configuration标注在类上,相当于把该类作为spring的xml配置文件中的<beans ...

  2. 28Spring_的事务管理_银行转账业务加上事务控制_基于注解进行声明式事务管理

    将applicationContext.xml 和 AccountServiceImpl 给备份一个取名为applicationContext2.xml 和 AccountServiceImpl2.j ...

  3. Spring的事务控制-基于xml方式

    介绍:该程序模拟了转账操作,即Jone减少500元,tom增加500元 1.导入坐标 <dependency> <groupId>junit</groupId> & ...

  4. 使用Spring实现AOP(XML+注解)

    一.Spring对AOP的支持 AOP并不是Spring框架特有的,Spring只是支持AOP编程的框架之一,每一个框架对AOP的支持各有特点,有些AOP能够对方法的参数进行拦截,有些AOP对方法进行 ...

  5. Spring第八篇【XML、注解实现事务控制】

    前言 本博文主要讲解Spring的事务控制,如何使用Spring来对程序进行事务控制-. 一般地,我们事务控制都是在service层做的..为什么是在service层而不是在dao层呢??有没有这样的 ...

  6. Spring的事务控制-基于注解的方式

    模拟转账操作,即Jone减少500,tom增加500 如果有疑问请访问spring事务控制-基于xml方式 1.创建数据表 2.创建Account实体类 public class Account { ...

  7. 阶段3 2.Spring_10.Spring中事务控制_1 基于XML的AOP实现事务控制

    新建项目 首先把依赖复制进来 aop必须引入.aspectjweaver 复制src下的所有内容 复制到我们的新项目里面 factory文件夹删掉 删除后测试类必然就报错 配置文件 beanFacto ...

  8. Java实战之03Spring-05Spring中的事务控制(基于AOP)

    五.Spring中的事务控制(基于AOP) 1.Spring中事务有关的接口 1.1.明确: JavaEE体系进行分层开发,事务处理位于业务层,Spring提供了分层设计业务层的事务处理解决方案 1. ...

  9. spring基于XML的声明式事务控制

    <?xml version="1.0" encoding="utf-8" ?><beans xmlns="http://www.sp ...

  10. SpringBoot系列: JdbcTemplate 事务控制

    ============================Spring JdbcTemplate 事务控制============================之前使用 JDBC API 操作, 经常 ...

随机推荐

  1. Elasticsearch:Elasticsearch HQ 介绍

  2. Beats:通过Metricbeat实现外部对Elastic Stack的监控

  3. SonarQube 之 gitlab-plugin 配合 gitlab-ci 完成每次 commit 代码检测

    转载自:https://cloud.tencent.com/developer/article/1010601 1.背景介绍 我们知道使用 SonarQube 可以在日常开发中检测代码质量,除了使用 ...

  4. C#-02 传入参数的一些用法2

    C#_02 参数应用2 一.关于 "ref" 局部变量和 "ref" 返回 在前面已经明白了 ref 关键词传递一个对象引用给方法调用,这样在方法中对对象修改过 ...

  5. vue中的v-if查找数组中最后一个,给他加上新的样式

    vue: var app=new Vue({ el:".xiaomi", data: { typeInfo: [{img:"image/type/phone_1.webp ...

  6. 自己动手写ls命令——Java版

    自己动手写ls命令--Java版 介绍 在前面的文章Linux命令系列之ls--原来最简单的ls这么复杂当中,我们仔细的介绍了关于ls命令的使用和输出结果,在本篇文章当中我们用Java代码自己实现ls ...

  7. C语言之走迷宫深度和广度优先(利用堆栈和队列)

    完成以下迷宫 利用二维数组储存每一个数组里的值,若是不能走则为1,若是可行就是0,走过了就设为2. 一般是再复制一个数组,用来记录. 堆栈的思想就是将一个点的上下左右都遍历一遍,若可行进栈,跳出遍历, ...

  8. 成功 解决 @keyup.enter=“search()“ 在el-input 组件中不生效的问题

    1.问题描述 在输入框中.输入内容.点击回车.没有效果 问题代码 2.问题解决思路 查看官网的解释说明: 要使用.native修饰符 3.问题解决 修改后的代码 修改后的效果

  9. 【React】学习笔记(二)——组件的生命周期、React脚手架使用

    原教程视频:ttps://www.bilibili.com/video/BV1wy4y1D7JT?p=2&spm_id_from=pageDriver 目录 一.组件的生命周期 1.1.生命周 ...

  10. 跟我学Python图像处理丨图像特效处理:毛玻璃、浮雕和油漆特效

    摘要:本文讲解常见的图像特效处理,从而让读者实现各种各样的图像特殊效果,并通过Python和OpenCV实现. 本文分享自华为云社区<[Python图像处理] 二十四.图像特效处理之毛玻璃.浮雕 ...