v一、前言
由于项目中的 实体(entity)默认都是继承一个父类(包含一些公共的属性,比如创建时间,修改时间,是否删除,主键id)。为了实现逻辑删除,一般会自己实现RepositoryFactoryBean 和 Repository。但是由于多个团队开发的结果,表的结构没有同一,也就是会出现有的表没有基础父类对应的字段,这样就会导致自定义的jpa repository操作这些表就会出错。
v二、最开始实现
默认父类
自定义Repository接口
- 添加BaseDao接口
- BaseDao继承了JpaSpecificationExecutor、CrudRepository,这样可以保证所有Repository都有基本的增删改查以及分页等方法。
- 在BaseDao上添加
@NoRepositoryBean
标注,这样Spring Data Jpa在启动时就不会去实例化BaseDao这个接口
然后,使所有Repository接口都继承BaseDao
实现BaseRepository
定义好自定义的方法后,我们现在通过一个基本的Repository类来实现该方法:
首先添加BaseDaoImpl类,继承SimpleJpaRepository类,使其拥有Jpa Repository的基本方法。
我们发现Repository有两个构造函数:
- SimpleJpaRepository(JpaEntityInformation entityInformation, EntityManager entityManager)
- SimpleJpaRepository(Class domainClass, EntityManager em)
这里我们实现第二个构造函数,拿到domainClass
和EntityManager
两个对象。因为我们要实现的是知道某个Repository是否支持某个领域对象的类型,因此在实现构造函数时我们将domainClass
的信息保留下来。
RepositoryFactoryBean 实现
接下来我们来创建一个自定义的BaseDaoFactoryBean来代替默认的RepositoryFactoryBean
。RepositoryFactoryBean
负责返回一个RepositoryFactory
,Spring Data Jpa 将使用RepositoryFactory
来创建Repository具体实现,这里我们用BaseDaoImpl代替SimpleJpaRepository
作为Repository接口的实现。这样我们就能够达到为所有Repository添加或修改自定义方法的目的。
jpa 配置文件
<!-- 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>
v三、改进之后
由于有的表没有默认父类AbsIdEntity对应的字段,导致生成 Repository 在操作表的时候会报错。需要修改的就是RepositoryFactoryBean的实现逻辑。对于继承了AbsIdEntity的实体类,返回自定义的BaseRepository(也就是BaseDaoImpl),否则就返回SimpleJpaRepository。注意自定义RepositoryFactoryBean的泛型也做了修改。
至此,完成了适配。