JPA 事务未在方法结束时提交

Posted

技术标签:

【中文标题】JPA 事务未在方法结束时提交【英文标题】:JPA Transaction not commiting at the end of method 【发布时间】:2016-08-30 02:02:29 【问题描述】:

我有两种方法:

1:
@Transactional
public Long add(Long clientId) 
    Contact contact = new Contact();
    contact.setClientId(clientId);
    contact.setValue('test@test.com');
    contact.setType('EMAIL');
    contact.setDateStart(new Date());
    // autowired repo
    return contactRepository.saveAndFlush(contact);


2:
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void emailsValidator(Long clientId) 
    Specification<Client> spec = ClientSearchSpecification.getByClientIdWithActiveEmails(clientId);
    List<Client> clientList = clientRepository.findAll(spec);


SearchSpecification:
 public static Specification<Client> getByClientIdWithActiveEmails(Long clientId) 
    return (root, query, cb) -> 
        query.distinct(true);
        Join<Client, Contact> clientContactJoin = (Join) root.fetch(Client_.contactList);
        List<Predicate> predicates = new ArrayList<>();
        predicates.add(cb.equal(root.get(AbstractEntity_.id), clientId));
        predicates.add(cb.equal(clientContaktJoin.get(Contakt_.type), 'EMAIL'));
        predicates.add(cb.lessThan(clientContaktJoin.get(Contakt_.dateStart), cb.currentTimestamp()));
        return cb.and(predicates.toArray(new Predicate[predicates.size()]));
    ;

主要方法:

@RequestMapping(value = "/clientId/contact/add", method = RequestMethod.POST, produces = "application/json; charset=UTF-8")
public void addContact(@PathVariable(value = "clientId") Long clientId) 
    contactService.add(clientId);
    errorValidationService.emailsValidator(clientId);

我的数据库属性:

hibernate.transaction.auto_close_session: true
hibernate.connection.autocommit: true
org.hibernate.flushMode: COMMIT

问题 - DB 在执行步骤 2 时不包含来自步骤 1 的新实体。仅在所有 rest 调用完成后才提交对象。如何在第 1 步提交实体,以便在第 2 步中选择并加入它?

【问题讨论】:

能否贴出调用这两种方法的代码? 【参考方案1】:

原来我在存储库接口中使用了两个不同的@Transaction 实现:

@Transactional
public interface ClientRepository extends JpaRepository<Client, Long>, JpaSpecificationExecutor<Client>

我用过:

import javax.transaction.Transactional;

我应该使用:

import org.springframework.transaction.annotation.Transactional;

这意味着 spring @Transaction 的设置没有被应用,它不能在方法结束时提交自己,它只在调用结束时提交。

【讨论】:

【参考方案2】:

您无需承诺选择您的数据(在同一事务中)。

这里的问题是你说过第 2 步需要是 `NOT_SUPPORTED,这意味着第 1 步必须先提交,然后第 2 步才能看到它插入的任何数据。

尝试将第 1 步的传播更改为REQUIRES_NEW,以确保在进入第 2 步之前提交。

【讨论】:

已经试过了。是的,我可以从步骤 1 中获取所有包含加载实体的 beanList 集合。但是,我不需要所有实体集合,这就是为什么我有自己的搜索条件,例如:cr_date > current_timestamp 和 type = 'something'。当我将任何@Transactions 放在第二种方法上时,Hibernate 会忽略我过滤后的搜索条件,并按该 ID 返回所有链接数据。 你能提供更多关于你如何调用这两种方法的信息吗?它们在同一个物体上吗?您对这些方法的调用者有什么 @Transactional 注释?如果可能,请发布更多代码。

以上是关于JPA 事务未在方法结束时提交的主要内容,如果未能解决你的问题,请参考以下文章

SQL 错误“在批处理结束时检测到不可提交的事务”,数据库上没有事务

没有 JPA @Transaction 和 save() 啥时候提交完成?

JPA数据懒加载LAZY配合事务@Transactional使用

尽管正确打印出所有输出,但程序未在 Java 中以退出代码 0 结束

事务未在春季批处理项目编写器中回滚

Capybara会议未在测试结束时结束