最近在写自己的一个应用小项目时,ORM采用了Spring Data JPA,项目运行起来之初一些正常。但测试到事务的时候出现事务失效问题,后来查出是配置问题,问题出在采用<context:component-scan>扫描项目类时,未处理好组件范围的处理。
下面记录一下整个问题解决过程,权当笔记,希望能帮到遇到类似问题的同学:
首先贴出一下我的JPA配置
视图层配置
此配置单表操作正常,为测试事务有效性,人为在业务层组件中抛出运行时异常,
@Override
@Transactional
public ApiResult saveUser(SysUser sysUser) {
SysRole role = new SysRole();
role.setRoleName("Role1");
role.setSort(1);
sysRoleRepository.save(role);
if (role.getRoleId() < 0) //此处人为产生运行时异常
throw new RuntimeException("save role failure!");
sysUserRepository.save(sysUser);
if (sysUser.getUserId() > 0) {
throw new RuntimeException("save user failure!");
}
return new ApiResult(ApiResult.SUCC, "save successful");
}
其实在视图层配置项中我也将@Controller层进行了排除,但事务依旧失效。很奇怪。
再观察数据库时发现角色表数据已经添加了一条记录,但用户表数据未插入成功,事务失败!
发现这种情况其实在采用spring注解的项目中比较常见,是在配置的时候未在意组件扫描范围引起。在spring先扫描@Service及@Component组件后,再扫描@Controller时范围过大。处理方式也非常简单。只需要在扫描@Controller组件时避免再次扫描@Service及@Repository即可。
将视图层稍加修改一下(红色斜体部分):
<context:component-scan base-package="com.itnews.android.modules" [b]use-default-filters="false"[/b][i][color=#FF0000][/color][/i]>
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
加上此配置后,再运行,则可以发现事务正常。
加上这处配置的作用是关闭默认对@Service及@Component的子注解@Service、@Reposity扫描。
下面记录一下整个问题解决过程,权当笔记,希望能帮到遇到类似问题的同学:
首先贴出一下我的JPA配置
视图层配置
此配置单表操作正常,为测试事务有效性,人为在业务层组件中抛出运行时异常,
@Override
@Transactional
public ApiResult saveUser(SysUser sysUser) {
SysRole role = new SysRole();
role.setRoleName("Role1");
role.setSort(1);
sysRoleRepository.save(role);
if (role.getRoleId() < 0) //此处人为产生运行时异常
throw new RuntimeException("save role failure!");
sysUserRepository.save(sysUser);
if (sysUser.getUserId() > 0) {
throw new RuntimeException("save user failure!");
}
return new ApiResult(ApiResult.SUCC, "save successful");
}
其实在视图层配置项中我也将@Controller层进行了排除,但事务依旧失效。很奇怪。
再观察数据库时发现角色表数据已经添加了一条记录,但用户表数据未插入成功,事务失败!
发现这种情况其实在采用spring注解的项目中比较常见,是在配置的时候未在意组件扫描范围引起。在spring先扫描@Service及@Component组件后,再扫描@Controller时范围过大。处理方式也非常简单。只需要在扫描@Controller组件时避免再次扫描@Service及@Repository即可。
将视图层稍加修改一下(红色斜体部分):
<context:component-scan base-package="com.itnews.android.modules" [b]use-default-filters="false"[/b][i][color=#FF0000][/color][/i]>
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
加上此配置后,再运行,则可以发现事务正常。
加上这处配置的作用是关闭默认对@Service及@Component的子注解@Service、@Reposity扫描。