spring基础05-事务
5 事务
5.1 搭建事务操作环境(以银行转账为例)
-
创建数据库,一个表t_acount,仨字段 id,username,money
-
创建service,dao,完成对象创建和注入关系
- service里面注入dao,dao里面注入jdbcTemoplate,jdbcTemplate里面注入Datesource
- 略
-
dao创建俩方法,一个多钱的,一个少钱的
-
@Repository public class UserDaoImpl implements UserDao{ @Autowired private JdbcTemplate jdbcTemplate; @Override public void addMoney() { String sql="update t_acount set money=money+? where username=?"; jdbcTemplate.update(sql,100,"张大壮"); } @Override public void reduceMoney() { String sql="update t_acount set money=money-? where username=?"; jdbcTemplate.update(sql,100,"李二狗"); } }
-
-
service创建转账方法
-
@Service public class UserService { @Autowired private UserDao userDao; public void acountMoney(){ userDao.addMoney(); //来一个异常 int x=10/0; userDao.reduceMoney(); } }
-
-
测试类
-
@Test public void test1(){ ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean-base.xml"); UserService userService = context.getBean("userService", UserService.class); userService.acountMoney(); }
-
问题:不满足原子性
比如service的方法中,两次转账之间发生一个异常
5.2 事务管理
-
事务应该添加在service层
-
在sping中做事务管理操作有两种
- 一种是编程式事务管理,和声明式事务管理用
-
声明式事务管理 底层用的就是AOP
- 注解方法
- xml配置文件方法
-
spring事务管理的API
- 提供一个接口,代表事务管理器,这个接口针对不同的矿建提供不同的实现类
5.3 声明式事务管理(注解)
5.3.1 具体实现
-
spring中配置事务管理器 ,人话:xml创建事务管理器类的对象
-
想看完全注解的,去5.5
-
<!--创建事务管理器--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <!--注入数据源--> <property name="dataSource" ref="druidDataSource"></property> </bean>
-
-
spring配置文件中,开启事务注解
-
略,同之前在xml中天健aop,context的空间一样,添加一个tx
-
开启事务注解
-
<!--开启事务注解--> <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
-
-
在service类上面,或者类里的方法上面添加事务注解
-
@Transactional
-
@Service public class UserService { @Autowired private UserDao userDao; @Transactional public void acountMoney(){ userDao.addMoney(); int x=10/0; userDao.reduceMoney(); } }
-
5.3.2 @Transaction注解
所有的参数
-
Propagation 事务传播行为
-
多个事务方法(改变数据库内容的方法)直接进行调用,这个过程中事务是如何进行管理的
-
/** * The transaction propagation type. * @see org.springframework.transaction.interceptor.TransactionAttribute#getPropagationBehavior() */ Propagation propagation() default Propagation.REQUIRED;
-
常用的就前俩
-
-
-
ioslation 事务隔离级别
- 为了解决事务的隔离性:保证多事务操作之间不会产生影响
-
timeout 超时时间
- 事务需要在一个规定时间内提交,提交不上就会rollback,
- 默认值-1,不超时,可以自己设置,单位为s
-
readOnly 是否只读
- 设置成true之后,就不能做修改操作了
- 默认false
-
rollbackFor 回滚
- 设置事务出现了哪些异常时进行事务回滚
-
noRollbackFor 不会滚
- 设置出现了哪些异常时不回滚
5.4 声明式事务管理(XML)
一键略过,但是面试可能问。。。
<!--1创建事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--注入数据源-->
<property name="dataSource" ref="druidDataSource"></property>
</bean>
<!--2 配置通知-->
<tx:advice id="txaddvice">
<!--配置事务的一些相关参数-->
<tx:attributes>
<!--指定在哪种规则的方法上面添加事务-->
<tx:method name="accountMoney"/><!--全匹配-->
<tx:method name="acount*"/><!--正则匹配-->
</tx:attributes>
</tx:advice>
<!--3 切入点和切面-->
<aop:config>
<!--配置切入点-->
<aop:pointcut id="pt" expression="execution(* com.zhang.service.UserService.*(..))"/>
<!--配置切面-->
<aop:advisor advice-ref="txaddvice" pointcut-ref="pt"></aop:advisor>
</aop:config>
5.5 声明式事务管理(完全注解)
1.创建配置类,使用配置类代替配置文件
@Configuration//这是个配置类
@ComponentScan(basePackages = "com.zhang")//组件扫描o
@EnableTransactionManagement//开启事务管理
public class TxConfig {
//创建数据库的连接池
@Bean
public DruidDataSource getDruidDataSOurce(){
DruidDataSource dataSource=new DruidDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql:///user_db?useUnicode=true&characterEncodign=UTF-8&serverTimezone=UTC");
dataSource.setUsername("root");
dataSource.setPassword("xxxx");
return dataSource;
}
@Bean
public JdbcTemplate getJbdcTemplate(DataSource dataSource){
JdbcTemplate jdbcTemplate=new JdbcTemplate();
//注入datasource
//方法1:空参,然后直接调用上面的方法
//jdbcTemplate.setDataSource(getDruidDataSOurce());
//这里IOC容器不会创建多个datasource
//方法2:
//带参数DataSource dS ,然后把dS传进去
jdbcTemplate.setDataSource(dataSource);
//到IOC容器中根据类型自动找到,Datasource对象
return jdbcTemplate;
}
//创建事务管理器
@Bean
public DataSourceTransactionManager getDataSourceTransactionManager(DataSource dataSource){
DataSourceTransactionManager dstm = new DataSourceTransactionManager();
dstm.setDataSource(dataSource);
return dstm;
}
}
赶紧开始看springboot吧,,这些就都不用写了
6 Spring5新功能
整个Spring 5 是基于jdk8开发,兼容jdk9
很多过时的方法都删除了,
6.1 使用log4j2
- spring5 自带了通用的日志封装
- 也可以整合log4j等三方工具
- 已经移除了Log4jConfigListener,官方建议使用Log4j
配置文件名是固定的log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--日志级别以及优先级排序: (优先级低,显示内容少) OFF>FATAL>ERROR > WARN > INFO > DEBUG > TRACE > ALL 优先级高,显示详细 -->
<!--Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出-->
<configuration status="INFO">
<!--先定义所有的appender-->
<appenders>
<!--这个输出控制台的配置-->
<console name="Console" target="SYSTEM_OUT">
<!--输出日志的格式-->
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} 【%t】 %-5level %logger{36} - %msg%n"/>
</console>
</appenders>
<!--然后定义logger,只有定义了logger并引入的appender,appender才会生效-->
<!--root:用于指定项目的根日志,如果没有单独指定Logger,则会使用root作为默认的日志输出-->
<loggers>
<root level="info">
<appender-ref ref="Console"/>
</root>
</loggers>
</configuration>
6.2 @Nullable注解
@Nullable注解可以使用在方法上面,属性上面,参数上麦你,表示方法返回可以为欧空,属性值可以为空,参数值可以为空
6.3 核心容器支持函数风格创建对象 (Lamda)
原因:spring管理的对象都是spring自己创建的,如果是new了一个对象,那么spring是不知道的,就无法管理
需要在spring中注册
@Test
public void test3(){
//1.创建GenericApplicationContext对象
GenericApplicationContext context = new GenericApplicationContext();
//2.调用共context的方法对象注册
context.refresh();
context.registerBean(UserDaoImpl.class,()->new UserDaoImpl() {});//第一个参数就是@Nullable的,可以指定beanname
//context.registerBean("user111",UserDaoImpl.class,()->new UserDaoImpl() {});
//3.获取在spring注册的对象
UserDaoImpl user = (UserDaoImpl) context.getBean("com.zhang.dao.UserDaoImpl");
//UserDaoImpl user = (UserDaoImpl) context.getBean("user111");//上面如果指定了,就可以直接使用
System.out.println(user);
}
6.4 测试Junit5
6.4.1 整合JUnit4
-
引入依赖
- spring-test
-
创建测试类,使用注解方式
-
@RunWith(SpringJUnit4ClassRunner.class)//指定单元测试矿建 @ContextConfiguration("classpath:bean-base.xml")//加载配置文件 public class Junit4Test { @Autowired private UserService userService;//等用于之前的遗传classpathxml...context...getbean...userService; @Test public void test1(){ userService.acountMoney(); } }
6.4.2 整合JUnit5
-
引入JUnit5 jar包
-
@ExtendWith(SpringExtension.class) @ContextConfiguration("classpath:bean-base.xml") //或者是使用这个使用复合注解替代上面的俩 @SpringJUnitConfig(locations = "bean-base.xml") public class Junit5Test { @Autowired private UserService userService;//等用于之前的遗传classpathxml...context...getbean...userService; @Test public void test1(){ userService.acountMoney(); } }
本文来自博客园,作者:荧惑微光,转载请注明原文链接:https://www.cnblogs.com/yinghuoweiguang/p/16095929.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!