如何在Spring Boot中实现Generic JPA Repository - 可以为任何实体/类类型自动连接到spring服务 [英] How to implement Generic JPA Repository in Spring Boot - Which can be autowired into spring services for any entity/class type

查看:1312
本文介绍了如何在Spring Boot中实现Generic JPA Repository - 可以为任何实体/类类型自动连接到spring服务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Here is the sample Generic Repository implementation which extends the spring PagingAndSortingRepository,

@NoRepositoryBean
public interface GenericRepository<T, ID extends Serializable> extends PagingAndSortingRepository<T, ID> {

  public List<T> findByNamedQuery( String name );
  public List<T> findByNamedQueryAndParams( String name, Map<String, Object> params );
  public T findOneByNamedQuery( String name );
  public T findOneByNamedQueryAndParams( String name, Map<String, Object> params );

}

工厂Bean类,

public class GenericRepositoryFactoryBean<R extends JpaRepository<T, I>, T, I extends Serializable> extends
    JpaRepositoryFactoryBean<R, T, I> {

   @SuppressWarnings( "rawtypes" )
   protected RepositoryFactorySupport createRepositoryFactory( EntityManager em )
   {
    return new MyRepositoryFactory(em);
   }

   private static class MyRepositoryFactory<T, I extends Serializable> 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<T, I>((Class<T>) metadata.getDomainType(), em);
    }

    protected Class<?> getRepositoryBaseClass( RepositoryMetadata metadata )
    {
        return GenericRepositoryImpl.class;
    }
  }
}

实施班,

public final class GenericRepositoryImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, ID> implements
    GenericRepository<T, ID> {

  private final EntityManager em;
  private final Class<T> domainClass;

  public GenericRepositoryImpl( Class<T> domainClass, EntityManager entityManager )
  {
      super(domainClass, entityManager);
      this.em = entityManager;
      this.domainClass = domainClass;
  }

  @Override
  public List<T> 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<T> findByNamedQueryAndParams( String name, Map<String, Object> params )
   {
      validate(name, params);
      final TypedQuery<T> query = this.em.createQuery(name, domainClass);
      setParams(query, params);
      return query.getResultList();
   }

}

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

So when i try to Autowire GenericRepository into services for different types like Customer.java, Message.java etc it is throwing requires at least one bean type of interface GenericRepository. This works if when I create individual repositories for both customer and message type. Without creating multiple repositories, i am not able to implement this.

@Service
@Transactional( noRollbackFor = Exception.class )
public class CustomerService {

@Autowired
private GenericRepository<Customer, Serializable> cr; works fine with just one entity type

@Autowired
private GenericRepository<Message, Serializable> cr; throws exception

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

If have 100 or more entity classes, then i end up creating 100's of repositories and which is bad. Please let me know if there is a better way to do this.

推荐答案

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

For what I've read it will be easier to tell the new interface methods what to do by @Query annotation and do not bother yourself with BeanFactory or impl...

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

在Spring Data JPA存储库中使用泛型

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

If that's not applicable for you and you are saying that your code works with one repository but fails when you add second my first thought is to try and set the scope of the bean to prototype but that is just a speculation. I am sorry if i didn't really help, don't hate me too much ^^

这篇关于如何在Spring Boot中实现Generic JPA Repository - 可以为任何实体/类类型自动连接到spring服务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆