Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Data: Override save method

I'm considering spring data for a project. Is it possible to override the per default generated save method? And if yes, how?

like image 422
beginner_ Avatar asked Oct 23 '12 17:10

beginner_


People also ask

How does JpaRepository save work?

The save operation performs a merge on the underlying EntityManager . This on its own doesn't perform any SQL but just returns a managed version of the entity. If that isn't already loaded into the EntityManager it might do this or it might identify the entity as a new one and make it a managed entity.

What is difference between CrudRepository and JpaRepository?

CrudRepository mainly provides CRUD operations. PagingAndSortingRepository provide methods to perform pagination and sorting of records. JpaRepository provides JPA related methods such as flushing the persistence context and deleting of records in batch.

What is the difference between save and saveAndFlush?

Save and saveAndFlush both can be used for saving entities. They both are both belong to the Spring data library. save may or may not write your changes to the DB straight away. When we call saveAndFlush system are enforcing the synchronization of your model state with the DB.


1 Answers

Simply create your custom interface as usual and declare there the methods you want to ovverride with the same signature of the one exposed by CrudRepository (or JpaRepository, etc.). Suppose you have a MyEntity entity and a MyEntityRepository repository and you want to override the default auto-generated save method of MyEntityRepository which takes an only entity instance, then define:

public interface MyEntityRepositoryCustom {   <S extends MyEntity> S save(S entity); } 

and implement this method as you like in your MyEntityRepositoryImpl, as usual:

@Transactional public class MyEntityRepositoryImpl implements MyEntityRepositoryCustom {   public <S extends MyEntity> S save(S entity) {     // your implementation   } } 

And then, as usual, let MyEntityRepository extend MyEntityRepositoryCustom.

Doing this, Spring Data JPA will call the save method of your MyEntityRepositoryImpl instead of the default implementation. At least this works for me with the delete method in Spring Data JPA 1.7.2.


"ambiguous reference" error

As reported by some of the commenters, probably starting from a certain Spring Data JPA version or javac version (I can't say when it started to fail, but I know for sure that it worked before) the javac compiler began to give a compilation error on the overridden method: "ambiguous reference". Eclipse JDT does not return this error and code works at runtime, in fact I opened Bug 463770 for this reason: either it's a javac bug or a JDT bug that does not conform to javac. This said, Lucas has posted the workaround below, which at a first sight might seem to be identical to the one described above. Actually, the difference stands on the MyEntityRepositoryCustom, declaration which must include the generic type <S>, even if it's apparently useless. So, if you encounter this error change the custom interface declaration as:

public interface MyEntityRepositoryCustom<S> {   <S extends MyEntity> S save(S entity); } 

and let the standard repository interface implement MyEntityRepositoryCustom<MyEntity> rather than just MyEntityRepositoryCustom.

However, if you don't want to generify your custom interface, you can extract a separate fragment interface particulary for the save method 2. Then the solution looks as follows:

public interface MyEntityRepositoryCustom {   // custom methods }  public interface CustomizedSaveRepository<T> {   <S extends T> S save(S entity); }  @Transactional public class MyEntityRepositoryImpl implements MyEntityRepositoryCustom,  CustomizedSaveRepository<MyEntity> {      @Override   public MyEntity save(MyEntity entity) {     // your implementation for CustomizedSaveRepository#save   }    // implementations of MyEntityRepositoryCustom } 
like image 71
Mauro Molinari Avatar answered Oct 03 '22 10:10

Mauro Molinari