如何在Spring Boot中实现Generic JPA Repository – 可以为任何实体/类类型自动连接到spring服务

以下是扩展Spring PagingAndSortingRepository的示例Generic Repository实现,

@NoRepositoryBean public interface GenericRepository extends PagingAndSortingRepository { public List findByNamedQuery( String name ); public List findByNamedQueryAndParams( String name, Map params ); public T findOneByNamedQuery( String name ); public T findOneByNamedQueryAndParams( String name, Map params ); 

}

工厂Bean类,

 public class GenericRepositoryFactoryBean<R extends JpaRepository, T, I extends Serializable> extends JpaRepositoryFactoryBean { @SuppressWarnings( "rawtypes" ) protected RepositoryFactorySupport createRepositoryFactory( EntityManager em ) { return new MyRepositoryFactory(em); } private static class MyRepositoryFactory extends JpaRepositoryFactory { private final EntityManager em; public MyRepositoryFactory( EntityManager em ) { super(em); this.em = em; } @SuppressWarnings( "unchecked" ) protected Object getTargetRepository( RepositoryMetadata metadata ) { return new GenericRepositoryImpl((Class) metadata.getDomainType(), em); } protected Class getRepositoryBaseClass( RepositoryMetadata metadata ) { return GenericRepositoryImpl.class; } } } 

实施class,

 public final class GenericRepositoryImpl extends SimpleJpaRepository implements GenericRepository { private final EntityManager em; private final Class domainClass; public GenericRepositoryImpl( Class domainClass, EntityManager entityManager ) { super(domainClass, entityManager); this.em = entityManager; this.domainClass = domainClass; } @Override public List findByNamedQuery( final String name ) { validate(name); return this.em.createNamedQuery(name, domainClass).getResultList(); } @Override public T findOneByNamedQuery( String name ) { validate(name); return this.em.createNamedQuery(name, domainClass).getSingleResult(); } @Override public List findByNamedQueryAndParams( String name, Map params ) { validate(name, params); final TypedQuery query = this.em.createQuery(name, domainClass); setParams(query, params); return query.getResultList(); } } 

因此,当我尝试将GenericRepository Autowire转换为不同类型的服务(如Customer.java,Message.java等)时,它需要至少一种bean类型的接口GenericRepository。 如果我为客户和消息类型创建单独的存储库,则此方法有效。 没有创建多个存储库,我无法实现这一点。

 @Service @Transactional( noRollbackFor = Exception.class ) public class CustomerService { @Autowired private GenericRepository cr; works fine with just one entity type @Autowired private GenericRepository cr; throws exception 

如果有100个或更多实体类,那么我最终会创建100个存储库,这很糟糕。 如果有更好的方法,请告诉我。

对于我所读到的内容,更容易告诉新的接口方法@Query注释要做什么,不要打扰自己使用BeanFactory或impl …

  @Repository public interface GenericRepository extends JpaRepository { @Query(value = "SELECT c FROM customers c WHERE c.name = :name") public List findByNamedQuery( String name ); ... } 

在Spring Data JPA存储库中使用generics

如果这不适合你并且你说你的代码适用于一个存储库但是当你添加第二个时失败我首先想到的是尝试将bean的范围设置为原型,但这只是一个推测。 我很抱歉,如果我没有真正的帮助,不要恨我太多^^