【问题标题】:find by id in spring data jpa Base Repository在 spring data jpa Base Repository 中按 id 查找
【发布时间】:2018-05-22 08:04:39
【问题描述】:

我正在尝试在我的 Spring Data JPA 类的 BaseRepository 中实现一个通用的 findByIdsIn 方法,以便实现该接口的所有类都可以使用该功能。 我对 Spring Data JPA 很陌生,所以我不确定这是否可能以及如何实现它。

这是我到目前为止的代码。 findByIdsIn 是我想要实现的功能。

import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.data.repository.Repository;

import java.io.Serializable;
import java.util.List;
import java.util.Optional;

@NoRepositoryBean
public interface BaseRepository<T, ID extends Serializable> extends Repository<T, ID> {
    List<T> findAll( );
    Optional<T> findById(ID id);
    List<T> findByIdsIn(List<ID> ids); // This is the functionality I'd like to implement.
}

大家有什么建议吗? 非常感谢!

【问题讨论】:

    标签: java database spring repository spring-data-jpa


    【解决方案1】:

    默认情况下,SimpleJpaRepository 是基本存储库操作的实现。您应该实现并编写一个扩展SimpleJpaRepository 的类。作为此实现的泛型类型,传递接口SimpleJpaRepository 中传递的两种类型的参数。以下是您的要求的示例实现:

    import org.springframework.data.jpa.repository.support.SimpleJpaRepository;
    import org.springframework.transaction.annotation.Transactional;
    
    import javax.persistence.EntityManager;
    import java.io.Serializable;
    import java.util.Optional;
    
    public class BaseRepositoryImpl <T, ID extends Serializable>
            extends SimpleJpaRepository<T, ID>  implements BaseRepository<T, ID> {
    
        private final EntityManager entityManager;
    
        public BaseRepositoryImpl(Class<T> domainClass, EntityManager entityManager) {
            super(domainClass, entityManager);
            this.entityManager = entityManager;
        }
    
        @Override
       public  List<T> findByIdsIn(List<ID> ids) {
            List<T> entities = entityManager.createQuery(
            "FROM"+this.getDomainClass()+" WHERE id IN ("+CommonUtils.concat(ids,',')+")").getResultList(); // concatenation code is not tested hence u need to fix it 
            return entities;
        }
    }
    

    此外,您将需要覆盖默认实现,即 SimpleJpaRepository 与您的实现,即BaseRepositoryImpl

    import org.springframework.data.jpa.repository.JpaRepository;
    import org.springframework.data.jpa.repository.support.JpaRepositoryFactory;
    import org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean;
    import org.springframework.data.repository.core.RepositoryMetadata;
    import org.springframework.data.repository.core.support.RepositoryFactorySupport;
    
    import javax.persistence.EntityManager;
    import java.io.Serializable;
    
    public class BaseRepositoryFactoryBean<R extends JpaRepository<T, I>, T,
            I extends Serializable> extends JpaRepositoryFactoryBean<R, T, I> {
    
        @Override
        protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) {
            return new BaseRepositoryFactory(entityManager);
        }
    
        private static class BaseRepositoryFactory<T, I extends Serializable>
                extends JpaRepositoryFactory {
    
            private final EntityManager entityManager;
    
            public BaseRepositoryFactory(EntityManager entityManager) {
                super(entityManager);
                this.entityManager = entityManager;
            }
    
            @Override
            protected Object getTargetRepository(RepositoryMetadata metadata) {
                return new BaseRepositoryImpl<T, I>((Class<T>) metadata.getDomainType(), entityManager);
            }
    
            @Override
            protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
                return BaseRepositoryImpl.class;
            }
        }
    }
    

    最后,通过使用@EnableJpaRepositories 注释并指定您的类,在Spring 配置中配置您的BaseRepositoryFactoryBean,如下所示。这将告诉 JPA 要调用哪个 RepositoryFactoryBean ,而哪个 RepositoryFactoryBean 又会告诉整个使用哪个 JPA 存储库,并使用其 Impl 类对其实现进行初始化。

    @EnableJpaRepositories(basePackages = {"com.test.jpa.custom.repository"},
            repositoryFactoryBeanClass = BaseRepositoryFactoryBean.class)
    class Configuration{}
    

    现在您可以使用BaseRepositoryfindByIdsIn 将在您的整个应用程序中使用。

    【讨论】:

    • 我已尝试放置足够的代码来帮助您创建自定义存储库。但是也应该有一些有用的链接来详细解释为什么你需要这么多步骤
    • 谁投了反对票,你能帮我理解这篇文章的问题吗?
    【解决方案2】:

    我刚刚找到了一个令我满意的解决方案:

    @NoRepositoryBean
    public interface BaseRepository<T, ID extends Serializable> extends Repository<T, ID> {
        List<T> findAll( );
        Optional<T> findById(ID id);
        @Query("SELECT t FROM #{#entityName} t WHERE t.id IN :ids")
        List<T> findByIdsIn(@Param("ids") List<ID> ids);
    }
    

    不过,如果有更优雅的解决方案,我很乐意让其他人做出贡献。

    【讨论】:

    • 不需要向 JPA 注册 BaseRepository 吗?
    • @jimmy 你能接受这个问题的答案吗?
    猜你喜欢
    • 1970-01-01
    • 2014-08-31
    • 1970-01-01
    • 2019-12-06
    • 2020-01-14
    • 1970-01-01
    • 1970-01-01
    • 2014-02-03
    • 1970-01-01
    相关资源
    最近更新 更多