美文网首页
Spring JPA自定义Repository,以及遇到的问题

Spring JPA自定义Repository,以及遇到的问题

作者: 李逍遥JK | 来源:发表于2017-07-11 19:51 被阅读1034次

    第一次在简书发文章,原来是在csdn,但是感觉csdn上的文章参差不齐,因此试试简书吧。最近两天在做新项目,用的是Spring-Boot。Dao层用的是Spring-JPA。下面就分享下做法和遇到的问题。
      先说说问题吧,在代码中我都注释了(用了注意:):

    问题:1.继承JpaRepositoryFactoryBean出错。

    原因:JpaRepositoryFactoryBean,因为子类的构造函数中默认的第一行有一条隐式语句super(),该语句会访问父类中的空参数构造函数,除非父类中没有空参数的构造函数,那么子类构造函数的第一行必须显式调用父类的构造函数,即super(int x,…) 。查看源码,确实父类JpaRepositoryFactoryBean确实没有空参数的构造函数

    public class JpaRepositoryFactoryBean<T extends Repository<S, ID>, S, ID extends Serializable> extends TransactionalRepositoryFactoryBeanSupport<T, S, ID> {
        private EntityManager entityManager;
    
       public JpaRepositoryFactoryBean(Class<? extends T> repositoryInterface) {
            super(repositoryInterface);
        }
    
      @PersistenceContext
       public void setEntityManager(EntityManager entityManager) {
            this.entityManager = entityManager;
        }
    
       public void setMappingContext(MappingContext<?, ?> mappingContext) {
            super.setMappingContext(mappingContext);
        }
       protected RepositoryFactorySupport doCreateRepositoryFactory() {
            return this.createRepositoryFactory(this.entityManager);
        }
    
       protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) {
            return new JpaRepositoryFactory(entityManager);
        }
    
       public void afterPropertiesSet() {
            Assert.notNull(this.entityManager, "EntityManager must not be null!");
            super.afterPropertiesSet();
        }
    }
    

    问题:2.编译时报错No property find found for type XX的问题。

    (此处中的found只是的方法根据JPA规则去掉excute之后的关键词,比如你的方法名是excuteUpadte,则此处是find update)。百度下,发现网上的解决办法有很多,比如:修改Spring的validator,然后clean project再编译。试过没有用。在一本书上获得了解决办法:在入口类上加上注解 java @EnableJpaRepositories(repositoryFactoryBeanClass = CustomRepositoryFactoryBean.class)
    具体如下:

    @EnableJpaRepositories(repositoryFactoryBeanClass = CustomRepositoryFactoryBean.class)
    @SpringBootApplication
    public class SyngisMapApplication {
    
     //1.首先,定义自己的Repository类实现Repository借口:
    /*
     * 定义自定义Repository接口
     * Created by Tomas on 2017/7/11.
     */
    //@NoRepositoryBean指明当前接口不是我们领域类的接口(如PersonRepository)
    @NoRepositoryBean
    public interface CustomRepository<T, ID extends Serializable> extends PagingAndSortingRepository<T, ID> {//注释:1
    
       //简单的定义了一些除了curd之外的方法
        public void store(Object... item);
        public void update(Object... item);
        public int executeUpdate(String qlString, Object... values);
        public int executeUpdate(String qlString, Map<String, Object> params);
        public int executeUpdate(String qlString, List<Object> values);
    }
    

    1.我们自定义的接口实现PagingAndSortingRepository接口,使自定义具有分页功能
    2.定义接口实现

    /*
     * Created by Tomas on 2017/7/11.
     */
    public class CustomRepositoryImpl <T, ID extends Serializable> extends SimpleJpaRepository<T, ID> implements CustomRepository<T, ID> {//注解:1
    
    
        private final EntityManager entityManager = null;</br>
    
        //让数据操作方法中可以使用entityManager
        //CustomRepositoryImpl构造函数,需要当前处理的领域模型和entitymanager作为构造函数参数
        public CustomRepositoryImpl(Class<T> domainClass, EntityManager entityManager){
            super(domainClass, entityManager);
        }
    
        //下面是一些数据操作方法
        @Override
        public void store(Object... item) {
    
        }
    
        @Override
        public void update(Object... item) {
    
        }
    
        @Override
        public int executeUpdate(String qlString, Object... values) {
            return 0;
        }
    
        @Override
        public int executeUpdate(String qlString, Map<String, Object> params) {
            return 0;
        }
    
        @Override
        public int executeUpdate(String qlString, List<Object> values) {
            return 0;
        }
    }
    

    注解
    1.首先要实现CustomRepository接口,继承SimpleJpaRepository让我们可以使用其提供的方法
    2.自定义RepositoryFactoryBean。自定义JpaRepositoryFactoryBean替代默认的RepositoryFactoryBean,我们会获得一个RepositoryFactory,它会注册我们自定义Repository的实现。

    package com.wlw.dao;
    RepositoryFactoryBean<T, S, ID> {
    
        //重写createRepositoryFactory方法,用当前的CustomRepositoryFactory创建实例
        @Override
        protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) {
            return new CustomRepositoryFactory (entityManager);
        }
        //创建CustomRepositoryFactory,并继承 JpaRepositoryFactory
        private static class CustomRepositoryFactory extends JpaRepositoryFactory{
    
            //参见问题1
            //注意:这里一定要写CustomRepositoryFactoryBean的构造函数,否则会报错。
            public CustomRepositoryFactory (EntityManager entityManager){
                super(entityManager);
            }
            //重写getTargetRepository方法并且获得当前自定义的Repository实现
            @Override
            protected <T, ID extends Serializable>SimpleJpaRepository<?, ?> getTargetRepository(RepositoryInformation information, EntityManager entityManager){
                return new CustomRepositoryImpl<T, ID>((Class<T>)information.getDomainType(), entityManager);
            }
          
            //重写getRepositoryBaseClas方法并且获得当前自定义的Repository的实现类型
            @Override
            protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata){
                return CustomRepositoryImpl.class;
            }
        }
    }
    

    4.使用时,我们只需要实现自定义的CustomRepository接口就能使用自定义的查询方法

    /*
     * 查询RecArea数据Dao层借口
     * Created by Tomas on 2017/7/11.
     */
    @Repository
    public interface QueryRecAreaDao extends CustomRepository<SysUser,String>{
    }
    

    5.最后一定要注意CustomRepository和CustomRepositoryImpl的命名规则;今天先写到这,明天继续。。。
    继续昨天的:
    今天主要有几个问题,都是有关SpringBootJpa

    相关文章

      网友评论

          本文标题:Spring JPA自定义Repository,以及遇到的问题

          本文链接:https://www.haomeiwen.com/subject/ctimhxtx.html