2015-09-21 37 views
1

我在使用MYSQL的Spring Boot应用程序中使用Spring Data JPA。在那里,我保存了一个实体列表,对某个字段有唯一的约束。在实体列表之外,由于唯一约束,有一个实体会抛出DataIntegrityViolationException。我注意到在这种情况下没有任何实体会持续存在,即使是那些不违反唯一约束的实体。 这种情况下理想的方法应该是什么,以便那些不违反独特get的实体持续存在? 当然,我可以迭代列表并逐一保存它们。实际上,这就是SimpleJpaRepository正在做的事情。如何在保存Spring Data JPA中的列表时处理DataIntegrityVilolationException?

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

+0

这就是它应该如何工作 –

回答

0

我认为你可以使用下面的步骤:从DB

  1. 加载现有实体到集
  2. 覆盖equalshashCode方法基于name
  3. 通话Set::addAll你antities(或只是将它们添加一个一个)
  4. 保存Set到DB

也许这是次优的,因为你迫使select *查询。但我认为将实体逐一保存到数据库会更有效。

参照this article您可以使用名称作为您的业务密钥,它有很多好处。

+0

这是做到这一点的一种方式。但正如你所指出的那样,这将是次优的。我的桌子上可以有一百万条记录。我正在使用的实体具有equals和hashcode覆盖,我将其放入Set中。我想知道,如果有什么方法可以捕获违反约束的异常并继续处理其他实体。我认为除了遍历整个列表外,没有别的办法。谢谢:) –

+0

你总是可以创建查询,如'从表名中选择不同名称(:your_list_of_names_to_add)'。然后从前面选择的结果中以名称筛选收集项目。希望你不需要从DB加载大量的数据。 – asm0dey

相关问题