自定义Spring Data JPA存储库

Spring Data是一个非常方便的库。 但是,由于该项目是一个相当新的项目,因此功能不佳。 默认情况下,Spring Data JPA将基于SimpleJpaRepository提供DAO的实现。 在最近的项目中,我开发了一个定制的存储库基类,以便可以在其上添加更多功能。 您可以根据需要向该存储库基类添加特定于供应商的功能。

组态

您必须在spring bean配置文件中添加以下配置。 您必须指定一个新的存储库工厂类。 我们将在以后开发课程。

<jpa:repositories base-package='example.borislam.dao' 
factory-class='example.borislam.data.springData.DefaultRepositoryFactoryBean/>

只需开发一个扩展JpaRepository的接口即可。 您应该记得用@NoRepositoryBean对其进行注释。

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

定义自定义存储库基础实现类

下一步是开发定制的基础存储库类。 您可以看到我只是这个自定义基础存储库中的一个属性(即springDataRepositoryInterface)。 我只想对存储库接口的自定义行为的行为进行更多控制。 在下一篇文章中,我将展示如何添加此基础存储库类的更多功能。

@SuppressWarnings('unchecked')
@NoRepositoryBean
public class GenericRepositoryImpl<T, ID extends Serializable> 
 extends SimpleJpaRepository<T, ID>  implements GenericRepository<T, ID> , Serializable{
 
 private static final long serialVersionUID = 1L;

 static Logger logger = Logger.getLogger(GenericRepositoryImpl.class);
 
    private final JpaEntityInformation<T, ?> entityInformation;
    private final EntityManager em;
    private final DefaultPersistenceProvider provider;
     
    private  Class<?> springDataRepositoryInterface; 
 public Class<?> getSpringDataRepositoryInterface() {
  return springDataRepositoryInterface;
 }

 public void setSpringDataRepositoryInterface(
   Class<?> springDataRepositoryInterface) {
  this.springDataRepositoryInterface = springDataRepositoryInterface;
 }

 /**
     * Creates a new {@link SimpleJpaRepository} to manage objects of the given
     * {@link JpaEntityInformation}.
     * 
     * @param entityInformation
     * @param entityManager
     */
    public GenericRepositoryImpl (JpaEntityInformation<T, ?> entityInformation, EntityManager entityManager , Class<?> springDataRepositoryInterface) {
     super(entityInformation, entityManager);
     this.entityInformation = entityInformation;
     this.em = entityManager;
     this.provider = DefaultPersistenceProvider.fromEntityManager(entityManager);
     this.springDataRepositoryInterface = springDataRepositoryInterface;
     }

    /**
     * Creates a new {@link SimpleJpaRepository} to manage objects of the given
     * domain type.
     * 
     * @param domainClass
     * @param em
     */
    public GenericRepositoryImpl(Class<T> domainClass, EntityManager em) {
        this(JpaEntityInformationSupport.getMetadata(domainClass, em), em, null);  
    }
 
    public <S extends T> S save(S entity)
    {     
        if (this.entityInformation.isNew(entity)) {
            this.em.persist(entity);
            flush();
            return entity;
          }
  entity = this.em.merge(entity);
  flush();
        return entity;
    }

   
    public T saveWithoutFlush(T entity)
    {
      return 
       super.save(entity);
    }
    
    public List<T> saveWithoutFlush(Iterable<? extends T> entities)
    {
     List<T> result = new ArrayList<T>();
  if (entities == null) {
   return result;
  }

  for (T entity : entities) {
   result.add(saveWithoutFlush(entity));
  }
  return result;
    }
}

作为一个简单的示例,我只是覆盖了SimpleJPARepository的默认保存方法。 持久保存后,save方法的默认行为不会刷新。 我进行了修改,以使其在持久化后保持刷新状态。 另一方面,我添加了另一个名为saveWithoutFlush()的方法,以允许开发人员调用保存实体而无需刷新。

定义自定义存储库工厂bean

最后一步是创建一个工厂bean类和一个工厂类,以根据您自定义的基本存储库类来生成存储库。

public class DefaultRepositoryFactoryBean <T extends JpaRepository<S, ID>, S, ID extends Serializable>
  extends JpaRepositoryFactoryBean<T, S, ID> {
    /**
     * Returns a {@link RepositoryFactorySupport}.
     * 
     * @param entityManager
     * @return
     */
    protected RepositoryFactorySupport createRepositoryFactory(
            EntityManager entityManager) {

        return new DefaultRepositoryFactory(entityManager);
    }
}


/**
 * 
 * The purpose of this class is to override the default behaviour of the spring JpaRepositoryFactory class.
 * It will produce a GenericRepositoryImpl object instead of SimpleJpaRepository. 
 * 
 */
public  class DefaultRepositoryFactory extends JpaRepositoryFactory{
    
 private final EntityManager entityManager;
    private final QueryExtractor extractor;


    public DefaultRepositoryFactory(EntityManager entityManager) {
     super(entityManager);
        Assert.notNull(entityManager);
        this.entityManager = entityManager;
        this.extractor = DefaultPersistenceProvider.fromEntityManager(entityManager);
    }
    
    @SuppressWarnings({ 'unchecked', 'rawtypes' })
    protected <T, ID extends Serializable> JpaRepository<?, ?> getTargetRepository(
            RepositoryMetadata metadata, EntityManager entityManager) {

        Class<?> repositoryInterface = metadata.getRepositoryInterface();
       
        JpaEntityInformation<?, Serializable> entityInformation =
                getEntityInformation(metadata.getDomainType());

        if (isQueryDslExecutor(repositoryInterface)) {
            return new QueryDslJpaRepository(entityInformation, entityManager);
        } else {
            return new GenericRepositoryImpl(entityInformation, entityManager, repositoryInterface); //custom implementation
        }
    }
 
    @Override
    protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {

        if (isQueryDslExecutor(metadata.getRepositoryInterface())) {
            return QueryDslJpaRepository.class;
        } else {
            return GenericRepositoryImpl.class;
        }
    }
    
    /**
     * Returns whether the given repository interface requires a QueryDsl
     * specific implementation to be chosen.
     * 
     * @param repositoryInterface
     * @return
     */
    private boolean isQueryDslExecutor(Class<?> repositoryInterface) {

        return QUERY_DSL_PRESENT
                && QueryDslPredicateExecutor.class
                        .isAssignableFrom(repositoryInterface);
    }   
}

结论

现在,您可以向基础存储库类添加更多功能。 在您的程序中,您现在可以创建自己的存储库接口,以扩展GenericRepository而不是JpaRepository。

public interface MyRepository <T, ID extends Serializable>
  extends GenericRepository <T, ID> {
   void someCustomMethod(ID id);  
}

在下一篇文章中,我将向您展示如何向此GenericRepository添加休眠过滤器功能。

参考:编程和平”博客上的JCG合作伙伴 Boris Lam 自定义Spring Data JPA存储库


翻译自: https://www.javacodegeeks.com/2012/08/customizing-spring-data-jpa-repository.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值