Spring Data JPA中通過(guò)Repository接口自動(dòng)實(shí)現(xiàn)了基本的ORM層操作,但在很多時(shí)候,僅僅基本的方法是不夠的。經(jīng)過(guò)對(duì)比網(wǎng)上的方法及源碼,實(shí)現(xiàn)了Repository添加自定義方法的辦法。
首先我們來(lái)添加一個(gè)自定義的接口:
添加BaseRepository接口
BaseRepository繼承了JpaRepository、JpaSpecificationExecutor,這樣可以保證所有Repository都有基本的增刪改查以及條件查詢等方法。
在BaseRepository上添加@NoRepositoryBean標(biāo)注,這樣Spring Data Jpa在啟動(dòng)時(shí)就不會(huì)去實(shí)例化BaseRepository這個(gè)接口
添加logicDelete(ID id);方法,表示該Repository的邏輯刪除功能
@NoRepositoryBean
public interface BaseRepository <T, ID extends Serializable> extends JpaRepository<T, ID>, JpaSpecificationExecutor<T>
{
? ? T logicDelete(ID id);
}
然后,使所有Repository接口都繼承BaseRepository
實(shí)現(xiàn)BaseRepository接口
定義好自定義的方法后,我們現(xiàn)在通過(guò)一個(gè)基本的Repository類來(lái)實(shí)現(xiàn)該方法:
首先添加BaseRepositoryImpl類,繼承SimpleJpaRepository類,使其擁有Jpa Repository的基本方法。
再實(shí)現(xiàn)logicDelete方法,其參數(shù)是領(lǐng)域?qū)ο蟮念愋?,將其和domainClass對(duì)比,如果相等,則該Repository支持該類型的領(lǐng)域?qū)ο螅?/p>
public class BaseRepositoryImpl<T, ID extends Serializable>?
? ? extends SimpleJpaRepository<T, ID>
? ? implements BaseRepository<T, ID> {
public BaseRepositoryImpl(JpaEntityInformation<T, ?> entityInformation, EntityManager entityManager) {
????super(entityInformation, entityManager);
}
public BaseRepositoryImpl(Class<T> domainClass, EntityManager em) {
????this(JpaEntityInformationSupport.getEntityInformation(domainClass, em), em);
}
private void setDeleteStatus(T entity) {
????????setStatus(entity, Dictionary.BUSINESS_STATUS_DELETE);
}
@Override
@Transactional(rollbackFor = Throwable.class)
public T logicDelete(ID id) {
????????T entity = findOne(id);
????????setDeleteStatus(entity);
????????return save(entity);
}
}
創(chuàng)建自定義RepositoryFactoryBean
接下來(lái)我們來(lái)創(chuàng)建一個(gè)自定義的RepositoryFactoryBean來(lái)代替默認(rèn)的RepositoryFactoryBean。RepositoryFactoryBean負(fù)責(zé)返回一個(gè)RepositoryFactory,Spring Data Jpa 將使用RepositoryFactory來(lái)創(chuàng)建Repository具體實(shí)現(xiàn),這里我們用BaseRepositoryImpl代替SimpleJpaRepository作為Repository接口的實(shí)現(xiàn)。這樣我們就能夠達(dá)到為所有Repository添加自定義方法的目的。
public class BaseRepositoryFactoryBean, T, I extends Serializable>
? ? extends JpaRepositoryFactoryBean {
? ? @Override
? ? protected RepositoryFactorySupport createRepositoryFactory(EntityManager em) {
? ? ? ? return new MyRepositoryFactory(em);
? ? }
? ? private static class MyRepositoryFactory extends JpaRepositoryFactory {
? ? ? ? private final EntityManager em;
? ? ? ? public MyRepositoryFactory(EntityManager em) {
? ? ? ? ? ? super(em);
? ? ? ? ? ? this.em = em;
? ? ? ? }
? ? ? ? @Override
? ? ? ? protected Object getTargetRepository(RepositoryInformation information) {
? ? ? ? ? ? return new BaseRepositoryImpl((Class) information.getDomainType(), em);
? ? ? ? }
? ? ? ? @Override
? ? ? ? protected Class getRepositoryBaseClass(RepositoryMetadata metadata) {
? ? ? ? ? ? return BaseRepositoryImpl.class;
? ? ? ? }
? ? }
}
配置Jpa factory class
最后,我們需要配置Jpa使用我們自定義的BaseRepositoryFactoryBean。Spring支持使用標(biāo)注進(jìn)行配置,我們?cè)赾om.xxx.Application中添加標(biāo)注@EnableJpaRepositories,repositoryFactoryBeanClass指定Repository的工廠類, basePackages用于配置掃描Repositories所在的package及子package:
@SpringBootApplication
@EnableJpaRepositories(repositoryFactoryBeanClass = BaseRepositoryFactoryBean.class, basePackages ="com.xxx.xxx.repository")
@EnableTransactionManagement
public class Application {
? ? public static void main( String[] args ){
? ? ? ? SpringApplication.run(Application.class, args);
? ? }
}
這樣我們就為所有Repository添加了自定義的方法。