zoukankan      html  css  js  c++  java
  • 十六、springboot整合Spring-data-jpa(二)之通用DAO接口与添加自定义方法

    @NoRepositoryBean:Spring Data Jpa在启动时就不会去实例化BaseRepository这个接口

    1.通用接口:

    import org.springframework.data.jpa.repository.JpaRepository;
    import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
    import org.springframework.data.repository.NoRepositoryBean;
    
    /**
     * 通用DAO接口
     * 
     */
    @NoRepositoryBean
    public interface DAOInterface<T> extends JpaRepository<T, Long>, JpaSpecificationExecutor<T> {
        
    }

    2.添加自定义方法:

    2.1自定义Repository接口

    @NoRepositoryBean
    public interface BaseRepository<T, ID extends Serializable> 
        extends PagingAndSortingRepository<T, ID> {
    
        boolean support(String modelType);
    
    }
    • 添加BaseRepository接口
    • BaseRepository继承了PagingAndSortingRepository,这样可以保证所有Repository都有基本的增删改查以及分页等方法。
    • BaseRepository上添加@NoRepositoryBean标注,这样Spring Data Jpa在启动时就不会去实例化BaseRepository这个接口
    • 添加support(String modelType)方法,表示该Repository的领域对象是否为modelType类型

    2.2实现BaseRepository接口

    public class BaseRepositoryImpl<T, ID extends Serializable> 
        extends SimpleJpaRepository<T, ID> 
        implements BaseRepository<T, ID> {
    
        private final Class<T> domainClass;
    
        public BaseRepositoryImpl(Class<T> domainClass, EntityManager entityManager) {
            super(domainClass, entityManager);
            this.domainClass = domainClass;
        }
    
        @Override
        public boolean support(String modelType) {
            return domainClass.getName().equals(modelType);
        }
    
    }

    定义好自定义的方法后,我们现在通过一个基本的Repository类来实现该方法:

    首先添加BaseRepositoryImpl类,继承SimpleJpaRepository类,使其拥有Jpa Repository的基本方法。

    我们发现Repository有两个构造函数:

    • SimpleJpaRepository(JpaEntityInformation entityInformation, EntityManager entityManager)
    • SimpleJpaRepository(Class domainClass, EntityManager em)

    这里我们实现第二个构造函数,拿到domainClassEntityManager两个对象。因为我们要实现的是知道某个Repository是否支持某个领域对象的类型,因此在实现构造函数时我们将domainClass的信息保留下来。

    最后实现support方法,其参数是领域对象的类型,将其和domainClass对比,如果相等,则该Repository支持该类型的领域对象:

    2.3创建自定义RepositoryFactoryBean

     接下来我们来创建一个自定义的RepositoryFactoryBean来代替默认的RepositoryFactoryBeanRepositoryFactoryBean负责返回一个RepositoryFactory,Spring Data Jpa 将使用RepositoryFactory来创建Repository具体实现,这里我们用BaseRepositoryImpl代替SimpleJpaRepository作为Repository接口的实现。这样我们就能够达到为所有Repository添加自定义方法的目的。

    public class BaseRepositoryFactoryBean<R extends JpaRepository<T, I>, T, I extends Serializable> 
        extends JpaRepositoryFactoryBean<R, T, I> {
    
        @Override
        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;
            }
    
            @Override
            protected Object getTargetRepository(RepositoryMetadata metadata) {
                return new BaseRepositoryImpl<T, I>((Class<T>) metadata.getDomainType(), em);
            }
    
            @Override
            protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
                return BaseRepositoryImpl.class;
            }
        }
    }

    2.4配置Jpa factory class

    最后,我们需要配置Jpa使用我们自定义的BaseRepositoryFactoryBean。Spring支持使用标注进行配置,我们在com.tmy.App中添加标注@EnableJpaRepositories(repositoryFactoryBeanClass = BaseRepositoryFactoryBean.class)

    @SpringBootApplication
    @EnableJpaRepositories(repositoryFactoryBeanClass = BaseRepositoryFactoryBean.class)
    public class App {
    
        public static void main( String[] args ){
            SpringApplication.run(App.class, args);
        }
    }

    这样我们就为所有Repository添加了自定义的方法。

    2.5测试

    我们添加了一个TestController进行测试。进入根目录,执行mvn spring-boot:run可以运行我们的应用。

    应用启动后,分别访问http://localhost:8080/test?type=blog&id=1http://localhost:8080/test?type=article&id=1,我们将看到article和blog两个不同的对象。

    TestController中,我们通过依赖式注入获取到所有Repository的列表。当用户访问/test,系统将根据传进来的type遍历所有Repository,找到对应的Repository,再调用findOne(id)方法找到对应的对象。这样我们就不需要一个一个的去获取Repository实例,当领域对象越来越多时,通过这种方式是一种更加高效的对象管理方法。

    @RestController
    public class TestController {
    
        @Autowired
        private List<BaseRepository> repositories;
    
        @RequestMapping(value = "/test", method=RequestMethod.GET)
        public Object getEntry(@RequestParam(value="type", required = true) String type,
                @RequestParam(value="id", required=true) Integer id){
            if(type.equals("article")){
                type = Article.class.getName();
            }else if (type.equals("blog")) {
                type = Blog.class.getName();
            }
            for (BaseRepository baseRepository : repositories) {
                if(baseRepository.support(type)){
                    return baseRepository.findOne(id);
                }
            }
            return null;
        }
    
    }

    参考:

      https://www.tianmaying.com/tutorial/spring-jpa-custom-all

  • 相关阅读:
    【JZOJ4876】【NOIP2016提高A组集训第10场11.8】基因突变
    【JZOJ4869】【NOIP2016提高A组集训第9场11.7】平均数
    【JZOJ4868】【NOIP2016提高A组集训第9场11.7】Simple
    【JZOJ4861】【NOIP2016提高A组集训第7场11.4】推冰块
    【JZOJ4860】【NOIP2016提高A组集训第7场11.4】分解数
    【JZOJ4859】【NOIP2016提高A组集训第7场11.4】连锁店
    【JZOJ4359】【GDKOI2016】魔卡少女
    【JZOJ4848】【GDOI2017模拟11.3】永恒的契约
    【JZOJ4855】【NOIP2016提高A组集训第6场11.3】荷花池塘
    Java编程的逻辑 (16)
  • 原文地址:https://www.cnblogs.com/soul-wonder/p/9051649.html
Copyright © 2011-2022 走看看