最近在看狂神Spring视频,后面看到事务部分,我在原来的基础上进行了业务层级的修改,由视频里的userMapperImpl修改成公司中常用的service层:
- service: UserService
- impl: UserServceImpl
发现事务没有生效。详情请往下看:
项目层级
Mapper
public interface UserMapper {
@Select("select * from user where id = #{id}")
User getById(Integer id);
@Insert("insert into user(id, userCode, userName) values(#{id}, #{userCode}, #{userName})")
Integer addUser(User user);
@Delete("deletes from user where id = #{id}")
Integer deleteById(Integer id);
@Select("select * from user")
List<User> selectList();
}
public class UserMapperImpl extends SqlSessionDaoSupport implements UserMapper {
@Override
public User getById(Integer id) {
return getSqlSession().getMapper(UserMapper.class).getById(id);
}
@Override
public Integer addUser(User user) {
return getSqlSession().getMapper(UserMapper.class).addUser(user);
}
@Override
public Integer deleteById(Integer id) {
return getSqlSession().getMapper(UserMapper.class).deleteById(id);
}
@Override
public List<User> selectList() {
User user = new User();
user.setId(1001);
user.setUserCode("xiaowang");
user.setUserName("小王");
UserMapper userMapper = getSqlSession().getMapper(UserMapper.class);
userMapper.addUser(user);
userMapper.deleteById(1001);
return userMapper.selectList();
}
}
Service
public interface UserService {
User getById(Integer id);
Integer addUser(User user);
Integer deleteById(Integer id);
List<User> selectList();
}
public class UserServiceImpl implements UserService {
private SqlSessionTemplate sqlSession;
private UserMapper userMapper;
public void setSqlSession(SqlSessionTemplate sqlSession) {
this.sqlSession = sqlSession;
this.userMapper = sqlSession.getMapper(UserMapper.class);
}
@Override
public User getById(Integer id) {
// UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
return userMapper.getById(id);
}
@Override
public Integer addUser(User user) {
return userMapper.addUser(user);
}
@Override
public Integer deleteById(Integer id) {
return userMapper.deleteById(id);
}
@Override
public List<User> selectList() {
User user = new User();
user.setId(1001);
user.setUserCode("xiaowang");
user.setUserName("小王");
userMapper.addUser(user);
userMapper.deleteById(1001);
return userMapper.selectList();
}
}
XML配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- dataSource -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver" />
<property name="username" value="root" />
<property name="password" value="123456" />
<property name="url" value="jdbc:mysql://127.0.0.1:3306/spring-mybatis" />
</bean>
<!-- SqlSessionFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configuration">
<bean class="org.apache.ibatis.session.Configuration">
<property name="mapUnderscoreToCamelCase" value="true" />
<property name="logImpl" value="org.apache.ibatis.logging.stdout.StdOutImpl" />
<property name="defaultStatementTimeout" value="28800" />
</bean>
</property>
<property name="mapperLocations" value="classpath*:com/lw/**/mapper/xml/*.xml" />
</bean>
<!-- SqlSessionTemplate: 就是我们使用的SqlSession -->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory" />
</bean>
<bean id="userService" class="com.lw.service.impl.UserServiceImpl" >
<property name="sqlSession" ref="sqlSession" />
</bean>
<bean id="userMapper" class="com.lw.mapper.UserMapperImpl">
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
<!-- 配置声明式事务:Spring事务 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<constructor-arg ref="dataSource" />
</bean>
<!-- 结合AOP实现事务的织入 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*" propagation="REQUIRED" />
</tx:attributes>
</tx:advice>
<!-- 配置事务切入 -->
<aop:config>
<aop:pointcut id="txPointCut" expression="execution(* com.lw.mapper.*.*(..)) || execution(* com.lw.service.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut" />
</aop:config>
</beans>
测试
@Test
public void test1() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserMapper userMapper = context.getBean("userMapper", UserMapper.class);
List<User> users = userMapper.selectList();
for (User user : users) {
System.out.println(user);
}
}
@Test
public void test2() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = context.getBean("userService", UserService.class);
List<User> users = userService.selectList();
for (User user : users) {
System.out.println(user);
}
}
事务失效情况
UserMapper中的delete方法故意写错,
当XML配置中的切入点只扫描mapper下的方法时:execution(* com.lw.mapper.*.*(..)),
test1事务生效回滚没有插入数据,test2在报错的情况下依旧是插入了新数据。
当修改切入点:execution(* com.lw.service.*.*(..)),test2事务生效回滚,没有插入新数据。
UserServiceImpl本质是调用了UserMapper,当切入点只配置:execution(* com.lw.mapper.*.*(..))时,为什么调用service的方法事务不会生效呢?