问题
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;
}
My code - Entity :
@Entity
@Table(uniqueConstraints = @UniqueConstraint(columnNames = { "name" }, name = "uq_name"))
public class SampleContent {
@Id
@GeneratedValue
private Long id;
private String name;
//getter setters
}
Repository :
public interface SampleContentRepository extends JpaRepository<SampleContent, Serializable>{
}
JUnit test :
@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!");
}
}
There is an entity with name "Roy" already present in the table. So, the entire transaction fails and @Transactional rolls back.
回答1:
I think you can use next steps:
- Load existing entities from DB into Set
- Override
equals
andhashCode
methods based onname
- call
Set::addAll
you antities (or just add them one by one) - save that
Set
to DB
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.
来源:https://stackoverflow.com/questions/32691128/how-to-handle-dataintegrityvilolationexception-while-saving-a-list-in-spring-dat