Rafał Wrzeszcz
Rafał Wrzeszcz

Reputation: 2057

How to override Spring Data JPA repository base methods?

I have some entity type that needs additional logic on saving (to be precise, I want to save position at the moment of saving). I don't want to do it with any DB-specific features, like triggers, because I'm not sure what will be the data storage used in future.

So I would like to override save() method.

In Spring Data JPA documentation I can see two ways of providing own implementation for repository classes:

  1. Extend base repository class and tell Spring Data to use it.
  2. Defining an interface (in my case I assume PositionedRepository) with an implementation class (PositionedRepositoryImpl).

Problem with first way - I don't want to implement it for all repositories, only two entity types are positioned.

Problem with second way - I don't have access to base repository methods, so apart from position calculation I would need to somehow build all of the queries, normally provided by base repository.

Any way to extend base repository class just for specific repository types?

Upvotes: 3

Views: 11252

Answers (3)

justeene xie
justeene xie

Reputation: 41

you can :

public class CustomJpaRepository<T, ID extends Serializable> extends SimpleJpaRepository<T, ID> {
  private final JpaEntityInformation<T, ?> entityInformationWrap;
  private final EntityManager emWrap;
  public CustomJpaRepository(JpaEntityInformation entityInformation, EntityManager entityManager) {
    super(entityInformation, entityManager);
    entityInformationWrap=entityInformation;
    emWrap=entityManager;
  }

  @Override
  public <S extends T> S save(S entity) {
    //doing
  }

}

then main class add: @EnableJpaRepositories(repositoryBaseClass = CustomJpaRepository.class)

Upvotes: 4

Lino
Lino

Reputation: 19926

Don't do that logic in the repository itself. Think about repositories as a dumb layer between java and the database. It just passes data from end to the other.

Instead you should handle that case in a different layer. A more intelligent one. The business logic layer.

See this example:

@Service
public class MyEntityService{

     private final MyEntityRepository myEntityRepository;
     private final OtherEntityRepository otherEntityRepository;

     @Autowired
     public MyEntityService(MyEntityRepository myEntityRepository, 
                          OtherEntityRepository otherEntityRepository){
         this.myEntityRepository = myEntityRepository;
         this.otherEntityRepository = otherEntityRepository;
     }

     public void save(MyEntity myEntity){
          // do stuff with otherEntityRepository
          myEntitiyRepository.save(myEntity);
     }
}

Upvotes: 5

davidxxx
davidxxx

Reputation: 131324

As third option you can extend SimpleJpaRepository that implements JpaRepository and JpaSpecificationExecutor. In this way, you could benefit from the default implementation of JpaRepository while being the ability to override these methods.

For example :

@Repository
public class PositionedRepository extends SimpleJpaRepository<Positioned, Long>  {

    @Override
    public Positioned save(Positioned positioned) {
           ...
    }

}

As fourth option you can also define your own savePositioned() method that uses under the hood the JpaRepository.save().

Upvotes: 2

Related Questions