Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Spring忽略@Transactional注释_Java_Spring_Hibernate_Spring Boot_Spring Data Jpa - Fatal编程技术网

Java Spring忽略@Transactional注释

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

在我们的一个项目中,我们遇到了一个问题,Spring忽略了
@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 of
CacheA
CacheB
?我添加了接口。1
deleteByValidity
应该用
@Transactional
注释,因为它会触发修改操作。2.请尝试启用事务管理(proxyTargetCla)
@Service
@Transactional
public class CacheAService implements CacheA {

    @Autowired
    private CacheARepository cacheARepository;

    @Override
    public void deleteShortTermCache() {
        cacheARepository.deleteByValidity(CacheValidity.SHORT_TERM);
    }
}