Java Spring忽略@Transactional注释
在我们的一个项目中,我们遇到了一个问题,Spring忽略了Java Spring忽略@Transactional注释,java,spring,hibernate,spring-boot,spring-data-jpa,Java,Spring,Hibernate,Spring Boot,Spring Data Jpa,在我们的一个项目中,我们遇到了一个问题,Spring忽略了@Transactional注释,然后由于以下错误而失败 启动ApplicationContext时出错。显示条件报告的步骤 在启用“调试”的情况下重新运行应用程序。2018-09-13 15:05:18,406 错误[main]org.springframework.boot.SpringApplication应用程序 运行失败的org.springframework.dao.InvalidDataAccessApiUsageExcep
@Transactional
注释,然后由于以下错误而失败
启动ApplicationContext时出错。显示条件报告的步骤
在启用“调试”的情况下重新运行应用程序。2018-09-13 15:05:18,406
错误[main]org.springframework.boot.SpringApplication应用程序
运行失败的org.springframework.dao.InvalidDataAccessApiUsageException:
当前线程没有实际事务可用的EntityManager
-无法可靠地处理“删除”调用;嵌套异常为javax.persistence.TransactionRequiredException:没有具有
当前线程可用的实际事务-无法可靠地执行
在上处理“删除”调用
com.my.service.CacheAService.deleteShortTermCache(CacheAService.java:70)
~[classes/:na]
我发现了类似的问题,但没有一个解决方案适用于这个案例
存在@EnableTransactionManagement
- 事务类实现一个接口
- 事务方法是公共的
- 不在内部调用事务方法
@Transactional
注释CacheService
时,一切都再次正常工作。但我试图理解为什么Spring会忽略CacheAService
上的@Transactional
我尝试记录Spring的事务拦截器,但没有提到CacheA
。这是唯一被记录的相关内容
2018-09-13 15:05:18242跟踪[主]
org.springframework.transaction.interceptor.TransactionInterceptor
不需要为创建事务
[org.springframework.data.jpa.repository.support.SimpleJpaRepository.deleteByValidity]:
此方法不是事务性的
下面是简化的代码。Spring的ContextRefreshedEvent
在应用程序启动期间调用代码
@Service
public class CacheService implements Cache {
@Autowired
private CacheA cacheAService;
@Autowired
private CacheB cacheBService;
@Override
public void clearCache() {
cacheAService.deleteShortTermCache();
cacheBService.deleteAll();
}
}
public interface CacheA {
void deleteShortTermCache();
}
@Service
@Transactional(readOnly = true)
public class CacheAService implements CacheA {
@Autowired
private CacheARepository cacheARepository;
@Override
@Transactional
public void deleteShortTermCache() {
cacheARepository.deleteByValidity(CacheValidity.SHORT_TERM);
}
}
public interface CacheB {
void deleteAll();
}
@Service
@Transactional(readOnly = true)
public class CacheBService implements CacheB {
@Autowired
private CacheBRepository cacheBRepository;
@Override
@Transactional
public void deleteAll {
cacheBRepository.deleteAll();
}
}
public enum CacheValidity {
SHORT_TERM,
LONG_TERM
}
@Repository
public interface CacheARepository extends JpaRepository<CacheItem, Integer> {
void deleteByValidity(CacheValidity validity);
}
public enum CacheItemKey {
AVAILABLE,
FUTURE,
AVAILABLE_UTM,
FUTURE_UTM,
REGION
}
@Entity
@Table(name = "cache_item")
public class CacheItem {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "cache_item_id_seq")
@SequenceGenerator(name = "cache_item_id_seq", sequenceName = "cache_item_id_seq", allocationSize = 1)
private Integer id;
@Column(nullable = false, unique = true)
@Enumerated(EnumType.STRING)
private CacheItemKey key;
@Column(nullable = false)
private String value;
@Column(name = "date_modified", nullable = false)
@Temporal(TemporalType.TIMESTAMP)
private Date dateModified;
@Column(nullable = false)
@Enumerated(EnumType.STRING)
private CacheValidity validity;
public Integer getId() {
return id;
}
public void setId(final Integer id) {
this.id = id;
}
public CacheItemKey getKey() {
return key;
}
public void setKey(final CacheItemKey key) {
this.key = key;
}
public String getValue() {
return value;
}
public void setValue(final String value) {
this.value = value;
}
public Date getDateModified() {
return dateModified;
}
public void setDateModified(final Date dateModified) {
this.dateModified = dateModified;
}
public CacheValidity getValidity() {
return validity;
}
public void setValidity(final CacheValidity validity) {
this.validity = validity;
}
}
@服务
公共类CacheService实现缓存{
@自动连线
专用CacheACacheAService;
@自动连线
专用CacheB cacheBService;
@凌驾
公共void clearCache(){
cacheAService.deleteShortTermCache();
cacheBService.deleteAll();
}
}
公共接口缓存{
void deleteShortTermCache();
}
@服务
@事务(只读=真)
公共类CacheAService实现CacheA{
@自动连线
私人缓存存储缓存存储;
@凌驾
@交易的
public void deleteShortTermCache(){
cacheARepository.deleteByValidity(CacheValidity.SHORT_TERM);
}
}
公共接口缓存{
void deleteAll();
}
@服务
@事务(只读=真)
公共类CacheBService实现CacheB{
@自动连线
私人缓存存储缓存存储;
@凌驾
@交易的
公共无效删除所有{
cacheBRepository.deleteAll();
}
}
公共枚举缓存有效性{
短期的,
长期的
}
@存储库
公共接口缓存存储扩展了JpaRepository{
无效deleteByValidity(CacheValidity-validity);
}
公共枚举缓存项密钥{
可用,
未来,,
可用的,
未来,
区域
}
@实体
@表(name=“缓存项”)
公共类缓存项{
@身份证
@GeneratedValue(策略=GenerationType.SEQUENCE,generator=“缓存项目id顺序”)
@SequenceGenerator(name=“cache\u item\u id\u seq”,sequenceName=“cache\u item\u id\u seq”,allocationSize=1)
私有整数id;
@列(nullable=false,unique=true)
@枚举(EnumType.STRING)
私钥;
@列(nullable=false)
私有字符串值;
@列(name=“date\u modified”,null=false)
@时态(TemporalType.TIMESTAMP)
修改私人日期;
@列(nullable=false)
@枚举(EnumType.STRING)
私钥有效性;
公共整数getId(){
返回id;
}
公共void setId(最终整数id){
this.id=id;
}
公共CacheItemKey getKey(){
返回键;
}
public void setKey(最终CacheItemKey){
this.key=key;
}
公共字符串getValue(){
返回值;
}
公共无效设置值(最终字符串值){
这个值=值;
}
公共日期getDateModified(){
修改返回日期;
}
公共作废setDateModified(最终日期已修改){
this.dateModified=dateModified;
}
公共缓存有效性getValidity(){
返回有效期;
}
公共无效设置有效性(最终缓存有效性){
有效性=有效性;
}
}
编辑:
经过一番挖掘,我在原木中发现了这个
2018-09-14 06:24:11174信息[localhost-startStop-1]
org.springframework.context.support.PostProcessorRegistrationLegate$BeanPostProcessorChecker
类型为[com.my.service.cacheAService]的Bean“cacheAService”不可用
有资格获得所有BeanPostProcessor的处理(例如:
不符合自动代理的条件)
尝试只使用一个
事务性注释(在类或方法中)。可能是,问题在于@Transactional(readOnly=true)
,因为您的事务不是只读的,所以我不能确定Spring更喜欢什么事务性
注释。尝试使用:
@Service
public class CacheAService implements CacheA {
@Autowired
private CacheARepository cacheARepository;
@Override
@Transactional
public void deleteShortTermCache() {
cacheARepository.deleteByValidity(CacheValidity.SHORT_TERM);
}
}
或
我们发现这个问题是由Spring Boot的自动配置引起的。由于自动配置已经设置了事务管理,我们对@EnableTransactionManagement
的自定义配置破坏了事务顾问的实例化。从配置中删除@EnableTransactionManagement
解决了这个问题。code ofCacheA
,CacheB
?我添加了接口。1deleteByValidity
应该用@Transactional
注释,因为它会触发修改操作。2.请尝试启用事务管理(proxyTargetCla)
@Service
@Transactional
public class CacheAService implements CacheA {
@Autowired
private CacheARepository cacheARepository;
@Override
public void deleteShortTermCache() {
cacheARepository.deleteByValidity(CacheValidity.SHORT_TERM);
}
}