我正在尝试在Spring Data JPA类的findByIdsIn
中实现通用BaseRepository
方法,以便所有实现该接口的类都可以使用该功能。
我是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.
}
你们有什么建议吗? 非常感谢!
答案 0 :(得分:1)
我刚刚找到了一个我满意的解决方案:
@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);
}
如果有更优雅的解决方案,我很乐意为其他人做出贡献。
答案 1 :(得分:0)
默认情况下,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;
}
}
}
最后,使用BaseRepositoryFactoryBean
注释并在下面指定您的类,在Spring配置中配置@EnableJpaRepositories
。这将告诉JPA哪个RepositoryFactoryBean要调用哪个,然后又告诉哪个JPA存储库在整个过程中使用,并使用其Impl类对其实现进行初始化。
@EnableJpaRepositories(basePackages = {"com.test.jpa.custom.repository"},
repositoryFactoryBeanClass = BaseRepositoryFactoryBean.class)
class Configuration{}
现在您可以使用BaseRepository
,findByIdsIn
可在整个申请中使用。