【问题标题】:Spring data - insert data depending on previous insertSpring data - 根据之前的插入插入数据
【发布时间】:2015-07-01 17:56:27
【问题描述】:

我需要将数据保存到 2 个表(一个实体和一个关联表)中。 我只是使用我的实体存储库中的save() 方法保存我的实体。 然后,为了表演,我需要将行插入到 native sql 中的关联表中。这些行对我之前保存的实体有参考。 问题来了:我得到一个关于外键的完整性约束异常。在第二个查询中不知道第一个保存的实体。

这是我的代码:

回购:

public interface DistributionRepository extends JpaRepository<Distribution, Long>, QueryDslPredicateExecutor<Distribution> {

    @Modifying
    @Query(value = "INSERT INTO DISTRIBUTION_PERIMETER(DISTRIBUTION_ID, SERVICE_ID) SELECT :distId, p.id FROM PERIMETER p "
        + "WHERE p.id in (:serviceIds) AND p.discriminator = 'SRV' ", nativeQuery = true)
    void insertDistributionPerimeter(@Param(value = "distId") Long distributionId, @Param(value = "serviceIds") Set<Long> servicesIds);
}

服务:

@Service
public class DistributionServiceImpl implements IDistributionService {

    @Inject
    private DistributionRepository distributionRepository;

    @Override
    @Transactional
    public DistributionResource distribute(final DistributionResource distribution) {

        // 1. Entity creation and saving
        Distribution created = new Distribution();
        final Date distributionDate = new Date();
        created.setStatus(EnumDistributionStatus.distributing);
        created.setDistributionDate(distributionDate);
        created.setDistributor(agentRepository.findOne(distribution.getDistributor().getMatricule()));
        created.setDocument(documentRepository.findOne(distribution.getDocument().getTechId()));
        created.setEntity(entityRepository.findOne(distribution.getEntity().getTechId()));
        created = distributionRepository.save(created);

        // 2. Association table 
        final Set<Long> serviceIds = new HashSet<Long>();
        for (final ServiceResource sr : distribution.getServices()) {
            serviceIds.add(sr.getTechId());
        }

        // EXCEPTION HERE
        distributionRepository.insertDistributionPerimeter(created.getId(), serviceIds);
    }
}

这两个查询似乎在不同的事务中,而我设置了 @Transactionnal 注释。我还尝试使用entityManager.createNativeQuery() 执行我的第二个查询并得到相同的结果...

【问题讨论】:

  • save()之后尝试flushing
  • 如果将 save() 替换为 saveAndFlush() 会怎样?
  • 也可以在相关插入到辅助表中定义一个触发器。
  • 谢谢大家,saveAndFlush() 完美运行!

标签: java sql spring spring-data native-sql


【解决方案1】:

在执行本机查询之前调用 entityManager.flush() 或改用 saveAndFlush

我建议使用您的具体情况

created = distributionRepository.saveAndFlush(created);

重要提示:您的“本地”查询必须使用相同的事务! (或者你需要一个现在的事务隔离级别)


你还写道:

我不太明白为什么默认情况下不执行刷新操作

刷新由 Hibernate 处理(可以配置,默认为“自动”)。这意味着休眠将在任何时间点刷新数据。但总是在您提交事务或通过 HIBERNATE 执行其他 SQL 语句之前。 - 所以通常这没问题,但在你的情况下,你用你的本地查询绕过休眠,所以休眠不会知道这个语句,因此它不会刷新它的数据。

另请参阅我的这个答案:https://stackoverflow.com/a/17889017/280244 关于这个主题

【讨论】:

  • 非常感谢,我不知道这种可能性。 saveAndFlush() 完美运行 =D 我真的不明白为什么默认情况下不执行刷新操作。我想这是为了内存性能。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-06-07
  • 2016-01-04
  • 1970-01-01
  • 1970-01-01
  • 2019-07-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多