【问题标题】:JPA Transaction not commiting at the end of methodJPA 事务未在方法结束时提交
【发布时间】: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 步中选择并加入它?

【问题讨论】:

  • 能否贴出调用这两种方法的代码?

标签: spring hibernate commit flush transactional


【解决方案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 注释?如果可能,请发布更多代码。
    猜你喜欢
    • 2015-03-19
    • 1970-01-01
    • 2011-03-13
    • 1970-01-01
    • 2015-04-29
    • 1970-01-01
    • 2015-07-24
    • 2016-03-31
    • 1970-01-01
    相关资源
    最近更新 更多