javascript
Spring Data JPA: 实现自定义Repository
一、前言
由于項目中的 實體(entity)默認都是繼承一個父類(包含一些公共的屬性,比如創(chuàng)建時間,修改時間,是否刪除,主鍵id)。為了實現(xiàn)邏輯刪除,一般會自己實現(xiàn)RepositoryFactoryBean 和?Repository。但是由于多個團隊開發(fā)的結(jié)果,表的結(jié)構(gòu)沒有同一,也就是會出現(xiàn)有的表沒有基礎(chǔ)父類對應的字段,這樣就會導致自定義的jpa repository操作這些表就會出錯。
二、最開始實現(xiàn)
默認父類
import java.io.Serializable; import java.sql.Timestamp;import javax.persistence.Column; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.MappedSuperclass;import org.hibernate.annotations.GenericGenerator;@MappedSuperclass public abstract class AbsIdEntity implements Serializable {private static final long serialVersionUID = 7988377299341530426L;@Id@GenericGenerator(name="uuid", strategy="uuid")@GeneratedValue(generator="uuid")@Column(name="id")protected String id;@Column(name = "creationtime")protected Timestamp creationTimestamp = new Timestamp(System.currentTimeMillis());@Column(name = "lastmodifiedtime")protected Timestamp modificationTimestamp = new Timestamp(System.currentTimeMillis());@Column(name = "dr")protected int dr;// 是否刪除。0:未刪除;1:已刪除/*** 主鍵,對應id字段*/public String getId() { return id; }public void setId(String id) { this.id = id; }/*** 創(chuàng)建日期,對應ts_insert字段*/public Timestamp getCreationTimestamp() { return creationTimestamp; }public void setCreationTimestamp(Timestamp creationTimestamp) { this.creationTimestamp = creationTimestamp; }/*** 修改日期,對應ts_update字段*/public Timestamp getModificationTimestamp() { return modificationTimestamp; }public void setModificationTimestamp(Timestamp modificationTimestamp) { this.modificationTimestamp = modificationTimestamp; }/*** 是否刪除,對應dr字段* @return*/public int getDr() {return dr;}public void setDr(int dr) {this.dr = dr;}} View Code自定義Repository接口
- 添加BaseDao接口
- BaseDao繼承了JpaSpecificationExecutor、CrudRepository,這樣可以保證所有Repository都有基本的增刪改查以及分頁等方法。
- 在BaseDao上添加@NoRepositoryBean標注,這樣Spring Data Jpa在啟動時就不會去實例化BaseDao這個接口
然后,使所有Repository接口都繼承BaseDao
實現(xiàn)BaseRepository
定義好自定義的方法后,我們現(xiàn)在通過一個基本的Repository類來實現(xiàn)該方法:
首先添加BaseDaoImpl類,繼承SimpleJpaRepository類,使其擁有Jpa Repository的基本方法。
我們發(fā)現(xiàn)Repository有兩個構(gòu)造函數(shù):
- SimpleJpaRepository(JpaEntityInformation entityInformation, EntityManager entityManager)
- SimpleJpaRepository(Class domainClass, EntityManager em)
這里我們實現(xiàn)第二個構(gòu)造函數(shù),拿到domainClass和EntityManager兩個對象。因為我們要實現(xiàn)的是知道某個Repository是否支持某個領(lǐng)域?qū)ο蟮念愋?#xff0c;因此在實現(xiàn)構(gòu)造函數(shù)時我們將domainClass的信息保留下來。
import java.io.Serializable; import java.sql.Timestamp;import javax.persistence.EntityManager;import org.springframework.data.jpa.repository.support.JpaEntityInformation; import org.springframework.data.jpa.repository.support.SimpleJpaRepository; import org.springframework.transaction.annotation.Transactional;import com.yyjz.icop.base.dao.BaseDao;@Transactional public class BaseDaoImpl<T extends AbsIdEntity> extends SimpleJpaRepository<T, Serializable> implements BaseDao<T> {@SuppressWarnings("unused")private final EntityManager entityManager;public BaseDaoImpl(Class<T> domainClass, EntityManager entityManager) {super(domainClass, entityManager);this.entityManager = entityManager;}public BaseDaoImpl(JpaEntityInformation<T, Serializable> information, EntityManager entityManager) {super(information, entityManager);this.entityManager = entityManager;}@Overridepublic <S extends T> S save(S entity) {entity.setModificationTimestamp(new Timestamp(System.currentTimeMillis()));return super.save(entity);}/*** 只做邏輯刪除*/@Overridepublic void delete(T entity) {entity.setDr(1);save(entity);}@Overridepublic void delete(Serializable id) {T entity = findOne(id);entity.setDr(1);this.save(entity);}} View CodeRepositoryFactoryBean 實現(xiàn)
接下來我們來創(chuàng)建一個自定義的BaseDaoFactoryBean來代替默認的RepositoryFactoryBean。RepositoryFactoryBean負責返回一個RepositoryFactory,Spring Data Jpa 將使用RepositoryFactory來創(chuàng)建Repository具體實現(xiàn),這里我們用BaseDaoImpl代替SimpleJpaRepository作為Repository接口的實現(xiàn)。這樣我們就能夠達到為所有Repository添加或修改自定義方法的目的。
import xxx.AbsIdEntity; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.support.JpaRepositoryFactory; import org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean; import org.springframework.data.jpa.repository.support.SimpleJpaRepository; import org.springframework.data.repository.core.RepositoryInformation; import org.springframework.data.repository.core.RepositoryMetadata; import org.springframework.data.repository.core.support.RepositoryFactorySupport;import javax.persistence.EntityManager; import java.io.Serializable;public class BaseDaoFactoryBean<R extends JpaRepository<T, Serializable>, T extends AbsIdEntity> extends JpaRepositoryFactoryBean<R, T, Serializable> {@Overrideprotected RepositoryFactorySupport createRepositoryFactory(final EntityManager entityManager) {return new JpaRepositoryFactory(entityManager) {protected SimpleJpaRepository<T, Serializable> getTargetRepository(RepositoryInformation information, EntityManager entityManager) {return new BaseDaoImpl((Class<T>) information.getDomainType(), entityManager);}@Overrideprotected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {return BaseDaoImpl.class;}};} } View Codejpa 配置文件
<!-- Spring Data Jpa配置 --> <jpa:repositories base-package="com.xxx"transaction-manager-ref="transactionManager"entity-manager-factory-ref="entityManagerFactory"factory-class="xxx.BaseDaoFactoryBean"><!-- 自定義RepositoryFactoryBean --> </jpa:repositories>三、改進之后
由于有的表沒有默認父類AbsIdEntity對應的字段,導致生成?Repository 在操作表的時候會報錯。需要修改的就是RepositoryFactoryBean的實現(xiàn)邏輯。對于繼承了AbsIdEntity的實體類,返回自定義的BaseRepository(也就是BaseDaoImpl),否則就返回SimpleJpaRepository。注意自定義RepositoryFactoryBean的泛型也做了修改。
import xxx.AbsIdEntity; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.support.JpaRepositoryFactory; import org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean; import org.springframework.data.jpa.repository.support.SimpleJpaRepository; import org.springframework.data.repository.core.RepositoryInformation; import org.springframework.data.repository.core.RepositoryMetadata; import org.springframework.data.repository.core.support.RepositoryFactorySupport;import javax.persistence.EntityManager; import java.io.Serializable;public class BaseDaoFactoryBean<R extends JpaRepository<T, Serializable>, T> extends JpaRepositoryFactoryBean<R, T, Serializable> {@Overrideprotected RepositoryFactorySupport createRepositoryFactory(final EntityManager entityManager) {return new JpaRepositoryFactory(entityManager) {protected SimpleJpaRepository<T, Serializable> getTargetRepository(RepositoryInformation information, EntityManager entityManager) {Class<T> domainClass = (Class<T>) information.getDomainType();if(AbsIdEntity.class.isAssignableFrom(domainClass)) {return new BaseDaoImpl(domainClass, entityManager);} else { return new SimpleJpaRepository(domainClass, entityManager);}}@Overrideprotected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {return metadata.getDomainType().isAssignableFrom(AbsIdEntity.class) ? BaseDaoImpl.class : SimpleJpaRepository.class;}};} } View Code至此,完成了適配。
?
生活不止眼前的bug,還有詩和遠方。。。
轉(zhuǎn)載于:https://www.cnblogs.com/hujunzheng/p/6494671.html
總結(jié)
以上是生活随笔為你收集整理的Spring Data JPA: 实现自定义Repository的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 五代机都在模仿F22,为何不参考歼20
- 下一篇: docker mysql命令大全_Doc