在我们的一个项目中,我们遇到了一个问题,即Spring忽略了@Transactional
批注,然后由于以下错误而失败。
启动ApplicationContext时出错。显示条件报告 在启用“调试”的情况下重新运行您的应用程序。 2018-09-13 15:05:18,406 错误[main] org.springframework.boot.SpringApplication应用程序 运行失败的org.springframework.dao.InvalidDataAccessApiUsageException: 没有可用于当前线程的实际事务的EntityManager -无法可靠地处理“删除”呼叫;嵌套异常为javax.persistence.TransactionRequiredException:否EntityManager with 当前线程可用的实际事务-无法可靠地 在处处理“删除”呼叫 com.my.service.CacheAService.deleteShortTermCache(CacheAService.java:70) 〜[classes /:na]
我发现了类似的问题,但没有适用于此案的解决方案。
@EnableTransactionManagement
存在当我用CacheService
注释@Transactional
时,一切都会恢复。但是我试图理解为什么Spring会忽略@Transactional
上的CacheAService
。
我尝试记录Spring的事务拦截器,但是没有提到CacheA
。这是唯一被记录的相关内容。
2018-09-13 15:05:18,242 TRACE [main] 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;
}
}
编辑: 经过一番挖掘,我在日志中找到了这个。
2018-09-14 06:24:11,174 INFO [localhost-startStop-1] org.springframework.context.support.PostProcessorRegistrationDelegate $ BeanPostProcessorChecker 类型[com.my.service.CacheAService]的Bean'cacheAService'不是 有资格被所有BeanPostProcessor处理(例如: 不符合自动代理的条件
答案 0 :(得分:2)
我们发现此问题是由Spring Boot的自动配置引起的。由于自动配置已经设置了事务管理,因此我们的@EnableTransactionManagement
的自定义配置破坏了事务顾问的实例化。从我们的配置中删除@EnableTransactionManagement
可以解决此问题。
答案 1 :(得分:1)
尝试仅使用一个Transactional
注释(在类或方法中)。可能是@Transactional(readOnly = true)
的问题所在,因为您的交易不是只读的,所以我不确定Spring首选哪种Transactional
注释。尝试使用:
@Service
public class CacheAService implements CacheA {
@Autowired
private CacheARepository cacheARepository;
@Override
@Transactional
public void deleteShortTermCache() {
cacheARepository.deleteByValidity(CacheValidity.SHORT_TERM);
}
}
或
@Service
@Transactional
public class CacheAService implements CacheA {
@Autowired
private CacheARepository cacheARepository;
@Override
public void deleteShortTermCache() {
cacheARepository.deleteByValidity(CacheValidity.SHORT_TERM);
}
}