java 在spring数据jpa Base Repository中按id查找

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/47708210/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 09:46:03  来源:igfitidea点击:

find by id in spring data jpa Base Repository

javadatabasespringrepositoryspring-data-jpa

提问by Jimmy

I'm trying to implement a generic findByIdsInmethod in the BaseRepositoryof my Spring Data JPA class so that the functionality can be used by all the classes that implement that interface. I'm pretty new to Spring Data JPA so I'm not sure if that is possible and how to implement it.

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

Here's the code I have so far. The findByIdsInis the functionality I'd like to implement.

这是我到目前为止的代码。这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.
}

Do you guys have any suggestions? Many thanks!

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

采纳答案by Jimmy

I've just found a solution I'm satisfied with:

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

@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);
}

I'm happy for other people to contribute if there are more elegant solutions, though.

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

回答by Vinay Prajapati

By default, SimpleJpaRepositoryis the implementations for basic repository operations. You should implement and write a class extending SimpleJpaRepository. As generic types to this implementation pass two types of parameter as passed in the interface SimpleJpaRepository. Below is a sample implementation of your requirement:

默认情况下,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;
    }
}

Also, you will need to override default implementation i.e. SimpleJpaRepositorywith your implementation i.e. BaseRepositoryImpl

此外,您将需要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;
        }
    }
}

Finally, configure your BaseRepositoryFactoryBeanin Spring configuration by using @EnableJpaRepositoriesannotation and specifying your class as below. This will tell JPA which RepositoryFactoryBean to call and which in turn tell which JPA repository to use throughout and initialize it with its implementation using its Impl class.

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

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

Now you could use BaseRepositoryand findByIdsInwill be available for usage throughout your application.

现在您可以使用BaseRepository并且findByIdsIn可以在整个应用程序中使用。