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
find by id in spring data jpa Base Repository
提问by Jimmy
I'm trying to implement a generic findByIdsIn
method in the BaseRepository
of 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.
我正在尝试findByIdsIn
在BaseRepository
我的 Spring Data JPA 类中实现一个通用方法,以便实现该接口的所有类都可以使用该功能。我对 Spring Data JPA 还很陌生,所以我不确定这是否可行以及如何实现它。
Here's the code I have so far. The findByIdsIn
is 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, SimpleJpaRepository
is 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.
SimpleJpaRepository
with 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 BaseRepositoryFactoryBean
in Spring configuration by using @EnableJpaRepositories
annotation 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 BaseRepository
and findByIdsIn
will be available for usage throughout your application.
现在您可以使用BaseRepository
并且findByIdsIn
可以在整个应用程序中使用。