Creating a read-only repository with SpringData

后端 未结 6 423
后悔当初
后悔当初 2020-12-13 18:12

Is it possible to create read-only repositories using Spring Data?

I have some entities linked to views and some child entities for which I would like to provide a r

相关标签:
6条回答
  • 2020-12-13 18:51

    As far as we can see in documentation, this is possible by implementing org.springframework.data.repository.Repository.

    0 讨论(0)
  • 2020-12-13 18:59

    To expand on Oliver Gierke's answer, in the more recent versions of Spring Data you will need the @NoRepositoryBean annotation on your ReadOnlyRepository (parent interface) to prevent application start up errors:

    import org.springframework.data.repository.NoRepositoryBean;
    import org.springframework.data.repository.Repository;
    
    @NoRepositoryBean
    public interface ReadOnlyRepository<T, ID extends Serializable> extends Repository<T, ID> {
    
        T findOne(ID id);
    
        List<T> findAll();
    
    }
    
    0 讨论(0)
  • 2020-12-13 19:03

    This is for read-only PagingAndSortingRepository

    package com.oracle.odc.data.catalog.service.core.repository;
    
    import org.springframework.data.domain.Page;
    import org.springframework.data.domain.Pageable;
    import org.springframework.data.domain.Sort;
    import org.springframework.data.repository.NoRepositoryBean;
    import org.springframework.data.repository.PagingAndSortingRepository;
    import org.springframework.data.rest.core.annotation.RestResource;
    
    /**
     * Extension of {@link PagingAndSortingRepository} but without modification capabilities
     *
     * @author XYZ
     * @see Sort
     * @see Pageable
     * @see Page
     */
    @NoRepositoryBean
    public interface ReadOnlyPagingAndSortingRepository<T, ID> extends PagingAndSortingRepository<T, ID> {
    
        @Override
        @RestResource(exported=false)
        <S extends T> S save(S entity);
    
        @Override
        @RestResource(exported=false)
        <S extends T> Iterable<S> saveAll(Iterable<S> entities);
    
        @Override
        @RestResource(exported=false)
        void deleteById(ID id);
    
        @Override
        @RestResource(exported=false)
        void delete(T entity);
    
        @Override
        @RestResource(exported=false)
        void deleteAll(Iterable<? extends T> entities);
    
        @Override
        @RestResource(exported=false)
        void deleteAll();
    
    }
    

    If you try to POST or DELETE, you will get 405 (Method Not Allowed).

    0 讨论(0)
  • 2020-12-13 19:05

    For me the following worked. Using Oliver's solution, I was getting error Invocation of init method failed; nested exception is org.springframework.data.mapping.PropertyReferenceException: No property findOne found for type while starting up.

    @NoRepositoryBean
    public interface ReadOnlyRepository<T,ID> extends Repository<T, ID> {
        Optional<T> findById(ID var1);
        boolean existsById(ID var1);
        Iterable<T> findAll();
        Iterable<T> findAllById(Iterable<ID> var1);
        long count();
    }
    
    0 讨论(0)
  • 2020-12-13 19:06

    Yes, the way to go is to add a handcrafted base repository. You usually use something like this:

    public interface ReadOnlyRepository<T, ID extends Serializable> extends Repository<T, ID> {
    
      T findOne(ID id);
    
      Iterable<T> findAll();
    }
    

    You can now have you concrete repos extend that just defined one:

    public interface PersonRepository extends ReadOnlyRepository<Person, Long> {
    
      T findByEmailAddress(String emailAddress);
    }
    

    The crucial part defining the base repo is that the method declarations carry the very same signature as the methods declared in CrudRepository if that's the case we can still route the calls into the implementation bean backing the repository proxy. I've written a more detailed blog post about that topic in the SpringSource blog.

    0 讨论(0)
  • 2020-12-13 19:11

    Or if you want to make your own implementation or block this actions - you can do something like this (works withJava 8 and higher):

    import org.springframework.data.jpa.repository.JpaRepository;
    import org.springframework.data.repository.NoRepositoryBean;
    import org.springframework.lang.NonNull;
    
    import java.util.List;
    
    @NoRepositoryBean
    public interface ReadOnlyRepository<T, ID> extends JpaRepository<T, ID> {
    
        @Override
        @NonNull
        default <S extends T> S save(@NonNull S entity) {
            throw new RuntimeException("Action not allowed");
        }
    
        @Override
        @NonNull
        default <S extends T> List<S> saveAll(@NonNull Iterable<S> iterable) {
            throw new RuntimeException("Action not allowed.");
        }
    
        @Override
        @NonNull
        default <S extends T> S saveAndFlush(@NonNull S s) {
            throw new RuntimeException("Action not allowed.");
        }
    
        @Override
        default void delete(@NonNull T entity) {
            throw new RuntimeException("Action not allowed.");
        }
    
        @Override
        default void deleteAll() {
            throw new RuntimeException("Action not allowed.");
        }
    
        @Override
        default void deleteAll(@NonNull Iterable<? extends T> entities) {
            throw new RuntimeException("Action not allowed.");
        }
    
        @Override
        default void deleteAllInBatch() {
           throw new RuntimeException("Action not allowed.");
        }
    
        @Override
        default void deleteById(@NonNull ID id) {
           throw new RuntimeException("Action not allowed.");
        }
    
        @Override
        default void deleteInBatch(@NonNull Iterable<T> iterable) {
            throw new RuntimeException("Action not allowed.");
        }
    }
    

    Hope I help somebody (ノ^∇^)

    0 讨论(0)
提交回复
热议问题