本文介绍了在Spring Data JPA中保存列表时如何处理DataIntegrityVilolationException?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用MYSQL在Spring Boot应用程序中使用Spring Data JPA.我在那里保存了一个在字段上具有唯一约束的实体的列表.在实体列表之外,由于唯一约束,有一个实体将引发DataIntegrityViolationException.我注意到在这种情况下,没有任何实体可以持久化,即使那些没有违反唯一约束的实体也没有持久化.在这种情况下理想的方法应该是什么,以使那些不违反唯一性的实体得以持久化?当然,我可以迭代该列表并将其一一保存.实际上,这就是SimpleJpaRepository在下面执行的操作.

I am using Spring Data JPA in a Spring Boot Application, with MYSQL. There I am saving a list of entities with unique constraint over a field. Out of the list of entities, there is one entity that will throw DataIntegrityViolationException due to the unique constraint. I noticed that none of the entities get persisted in that case, even those that does not violate the unique constraint.What should be the ideal approach in this case so that those entities which do not violate the unique get persisted ?Of course I can iterate the list and save them one by one. In fact that is what SimpleJpaRepository is doing underneath.

@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回滚.

There is an entity with name "Roy" already present in the table. So, the entire transaction fails and @Transactional rolls back.

推荐答案

我认为您可以使用以下步骤:

I think you can use next steps:

  1. 将现有实体从数据库加载到Set
  2. 基于 name
  3. 覆盖 equals hashCode 方法
  4. 调用 Set :: addAll 您的抗体(或将它们一个一地添加)
  5. 设置保存到数据库
  1. Load existing entities from DB into Set
  2. Override equals and hashCode methods based on name
  3. call Set::addAll you antities (or just add them one by one)
  4. save that Set to DB

可能不是最理想的,因为它迫使您进行 select * 查询.但是我认为这比将实体一一保存到数据库要有效得多.

Maybe it's suboptimal because forces you to make select * query. But I think it's much more effective then saving entities one by one to DB.

根据本文,您可以将名称用作您的业务密钥,这有很多好处.

Accotding to this article you can use name as your business key, which has lots of benefits.

这篇关于在Spring Data JPA中保存列表时如何处理DataIntegrityVilolationException?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-24 12:35