Tuesday, April 19, 2016

How to properly use Locking or Transactions to prevent duplicates using Spring Data

Leave a Comment

What is the best way to check if a record exists and if it doesn't, create it (avoiding duplicates)?

Keep in mind that this is a distributed application running across many application servers.

I'm trying to avoid these:

A simple example:

Person.java

@Entity public class Person {     @Id    @GeneratedValue    private long id;     private String firstName;     private String lastName;     //Getters and Setters Omitted  } 

PersonRepository.java

public interface PersonRepository extends CrudRepository<Person, Long>{     public Person findByFirstName(String firstName);  } 

Some Method

public void someMethod() {         Person john = new Person();         john.setFirstName("John");         john.setLastName("Doe");         if(personRepo.findByFirstName(john.getFirstName()) == null){             personRepo.save(john);         }else{             //Don't Save Person         }    } 

Clearly as the code currently stands, there is a chance that the Person could be inserted in the database in between the time I checked if it already exists and when I insert it myself. Thus a duplicate would be created.

How should I avoid this?

Based on my initial research, perhaps a combination of

But the exact configuration is what I'm unsure of. Any guidance would be greatly appreciated. To reiterate, this application will be distributed across multiple servers so this must still work in a highly-available, distributed environment.

1 Answers

Answers 1

For Inserts: if you want to prevent same recordsto be persisted, than you may want to take some precoutions on DB side. In your example, if firstname should be unique, then define a unique index on that column, or a agroup of colunsd that should be unique, and let the DB handle the check, you just insert & get exception if you're inserting a record that's already inserted.

For updates: use @Version (javax.persistence.Version) annotation like this:

@Version private long version; 

Define a version column in tables, Hibernate or any other ORM will automatically populate the value & also verison to where clause when entity updated. So if someone try to update the old entity, it prevent this. Be careful, this doesn't throw exception, just return update count as 0, so you may want to check this.

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment