Spring Data: Override save method

前端 未结 11 1228
温柔的废话
温柔的废话 2020-11-27 05:30

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

相关标签:
11条回答
  • 2020-11-27 05:43

    The solution from @ytterrr works but for older Spring Data versions, for Spring Data 2.1 at least, this is the way to not just override any repository method but also access to the underlying features (access to the entity manager to persist, delete, find...):

    public interface MyEntityRepositoryCustom {
      <S extends MyEntity> S save(S entity);
    }
    
    public class MyEntityRepositoryImpl implements MyEntityRepositoryCustom {
    
        final JpaEntityInformation<MyEntity, ?> entityInformation;
        EntityManager em;
    
        public MyEntityRepositoryImpl(EntityManager entityManager) {
            this.entityInformation = JpaEntityInformationSupport.getEntityInformation(MyEntity.class, entityManager);
            this.em = entityManager;
        }
    
        /**
         * @see org.springframework.data.jpa.repository.support.SimpleJpaRepository
         */
        @Transactional
        public <S extends MyEntity> S save(S entity) {
    
            // do your logic here
    
            if (entityInformation.isNew(entity)) {
                em.persist(entity);
                return entity;
            } else {
                return em.merge(entity);
            }
        }
    }
    
    0 讨论(0)
  • 2020-11-27 05:44

    Didn't get this to work nicely so I put my required logic into a service class and left the repositories save method untouched.

    0 讨论(0)
  • 2020-11-27 05:44

    What works for me (Spring boot 2.x Java 11), even if not perfectly clean. It compiles with IDE and Maven and Gradle. The above solution by Lucas does not work for me for the JpaRepository.

    public interface MyRepo extends JpaRepository<MyType, Long>, MyRepoCustom{
    
       //Implemented in MyRepoCustom
       public MyType save(MyType mytypeEntity);
    }
    

    The custom interface (repeats the declaration, which is not nice):

    public interface MyRepoCustom{
        public MyType save(MyType mytypeEntity);
    }
    

    The custom Impl:

    @Repository
    public class MyRepoImpl implements MyRepoCustom{
        @PersistenceContext
        private EntityManager em;
    
        @Transactional
        public MyType save(MyType mytypeEntity) {
           //type safe implementation
        }
    }
    
    0 讨论(0)
  • 2020-11-27 05:50

    I guess you extend SimpleJpaRepository :

    public class **CustomSimpleJpaRepository** extends SimpleJpaRepository {
    
    @Transactional
    public <S extends T> S save(S entity) { //do what you want instead }
    }
    

    Then make sure this is used instead of the default SimpleJpaRepository by extending:

    public class CustomJpaRepositoryFactory extends JpaRepositoryFactory {
    
        protected <T, ID extends Serializable> JpaRepository<?, ?> getTargetRepository(RepositoryMetadata metadata, EntityManager entityManager) {
    
          Class<?> repositoryInterface = metadata.getRepositoryInterface();
          JpaEntityInformation<?, Serializable> entityInformation = getEntityInformation(metadata.getDomainType());
    
          SimpleJpaRepository<?, ?> repo = isQueryDslExecutor(repositoryInterface) ? new QueryDslJpaRepository(
                entityInformation, entityManager) : new CustomSimpleJpaRepository(entityInformation, entityManager);
        repo.setLockMetadataProvider(lockModePostProcessor.getLockMetadataProvider());
    
          return repo;
      }
    }
    

    Not done yet, we also need to have your own factory bean to use it in the config xml:

    public class CustomRepositoryFactoryBean <T extends JpaRepository<S, ID>, S, ID extends Serializable> extends JpaRepositoryFactoryBean<T, S, ID> {
    
    protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) {
        return new **CustomJpaRepositoryFactory**(entityManager);
    }
    

    }

    the config:

    <jpa:repositories base-package="bla.bla.dao" factory-class="xxxx.**CustomRepositoryFactoryBean**"/>
    

    Hope it helps.

    0 讨论(0)
  • 2020-11-27 06:03

    To provide override of default generated save method you need to use aggregation of Spring Data repository implementation inside your own custom repository implementation.

    Repository interface:

    public interface UserRepository extends CrudRepository<User, String>{
    
    }
    

    Your repository implementation:

    @Repository("customUserRepository")
    public class CustomUserRepository implements UserRepository {
    
        @Autowired
        @Qualifier("userRepository") // inject Spring implementation here
        private UserRepository userRepository;
    
        public User save(User user) {
            User user = userRepository.save(entity);
            // Your custom code goes here
            return user;
        }
    
        // Delegate other methods here ...
    
        @Override
        public User findOne(String s) {
            return userRepository.findOne(s);
        }
    }
    

    Then use your custom implementation in your service:

    @Autowired
    @Qualifier("customUserRepository")
    private UserRepository userRepository;
    
    0 讨论(0)
提交回复
热议问题