在Spring数据jpa Base Repository中通过id查找

时间:2017-12-08 05:22:13

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

我正在尝试在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.
}

你们有什么建议吗? 非常感谢!

2 个答案:

答案 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{}

现在您可以使用BaseRepositoryfindByIdsIn可在整个申请中使用。