【问题标题】:How to handle DataIntegrityVilolationException while saving a list in Spring Data JPA?在 Spring Data JPA 中保存列表时如何处理 DataIntegrityVilolationException?
【发布时间】:2015-12-17 21:52:41
【问题描述】:

我在 Spring Boot 应用程序中使用 Spring Data JPA 和 MYSQL。在那里,我正在保存一个对字段具有唯一约束的实体列表。在实体列表中,有一个实体会由于唯一约束而引发 DataIntegrityViolationException。我注意到在这种情况下没有一个实体被持久化,即使是那些不违反唯一约束的实体。 在这种情况下,理想的方法应该是什么,以便那些不违反唯一性的实体得到持久化? 当然我可以迭代列表并一一保存。事实上这就是 SimpleJpaRepository 在下面所做的。

@Transactional
public <S extends T> List<S> save(Iterable<S> entities) {

    List<S> result = new ArrayList<S>();

    if (entities == null) {
        return result;
    }

    for (S entity : entities) {
        result.add(save(entity));
    }

    return result;
}

我的代码 - 实体:

@Entity
@Table(uniqueConstraints = @UniqueConstraint(columnNames = { "name" }, name = "uq_name"))
public class SampleContent {
    @Id
    @GeneratedValue
    private Long id;

    private String name;
    //getter setters 
}

存储库:

public interface SampleContentRepository extends JpaRepository<SampleContent, Serializable>{

}

JUnit 测试:

@Test
public void testCreate(){
    List<SampleContent> sampleContentList =  new ArrayList<>();
    SampleContent sampleContent1 = new SampleContent();
    sampleContent1.setName("dd");
    SampleContent sampleContent2 = new SampleContent();
    sampleContent2.setName("Roy");
    SampleContent sampleContent3 = new SampleContent();
    sampleContent3.setName("xx");
    sampleContentList.add(sampleContent1);
    sampleContentList.add(sampleContent2);
    sampleContentList.add(sampleContent3);
    try{
        this.sampleContentRepository.save(sampleContentList);
    }catch(DataIntegrityViolationException e){
        System.err.println("constraint violation!");
    }
}

表中已经存在一个名为“Roy”的实体。因此,整个事务失败,@Transactional 回滚。

【问题讨论】:

  • 它应该是这样工作的

标签: spring hibernate spring-data-jpa


【解决方案1】:

我认为您可以使用后续步骤:

  1. 将现有实体从数据库加载到集合中
  2. 基于name 覆盖equalshashCode 方法
  3. 打电话Set::addAll你们这些反派(或者一个一个加)
  4. Set 保存到数据库

也许它不是最理想的,因为它迫使您进行select * 查询。但我认为这比将实体一个一个地保存到数据库更有效。

根据this article,您可以使用名称作为您的业务密钥,这有很多好处。

【讨论】:

  • 这是一种方法。但正如你所指出的,这将是次优的。我的表中可以有一百万条记录。我正在使用的实体具有等于和覆盖的哈希码,我将它们放入一个集合中。我想知道,是否有任何方法可以捕获约束违规异常并继续处理其他实体。我认为除了遍历整个列表之外别无他法。谢谢:)
  • 您始终可以创建类似select distinct name from table where name in (:your_list_of_names_to_add) 的查询。然后从先前选择的结果中过滤出具有名称的集合项。希望您不必从数据库中加载大量数据。
猜你喜欢
  • 2017-03-15
  • 1970-01-01
  • 1970-01-01
  • 2013-08-26
  • 2015-06-06
  • 1970-01-01
  • 2021-01-08
  • 1970-01-01
  • 2019-09-30
相关资源
最近更新 更多