十六、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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM