spring-data-jpa通用dao的扩展

时间:2021-01-06 20:32:03

虽然使用spring data jpa给开发带来了极大的简化,但对于追求更小更快的我们来说,要为每个实体都写一遍数据访问接口却仍显得过于繁琐。如果可以构建一个baseDao,里面配置好了基本的增删改查接口,其他的实体类来继承它,这样就会使我们的开发得到进一步的简化。

创建BaseRepository(baseDao)

@NoRepositoryBean //表示该接口不会创建这个接口的实例
public interface BaseRepository<T, ID extends Serializable> extends JpaRepository<T, ID> {
List<Object[]> listBySQL(String sql);

/**
* 保存实体
*
* @param entity 实体id
*/

public void add(Object entity);

/**
* 更新实体
*
* @param entity 实体id
*/

public void update(Object entity);

/**
* 删除实体
*
* @param entityClass 实体类
* @param entityid 实体id
*/

public <T> void delete(Class<T> entityClass, Object entityid);

/**
* 删除实体
*
* @param entityClass 实体类
* @param entityids 实体id数组
*/

public <T> void delete(Class<T> entityClass, Object[] entityids);

/**
* 获取实体
*
* @param <T>
* @param entityClass 实体类
* @param entityId 实体id
* @return
*/

public <T> T find(Class<T> entityClass, Object entityId);
}

创建实现类BaseRepositoryImpl

//Spring Data JPA都是调用SimpleJpaRepository来创建实例
public class BaseRepositoryImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, ID>
implements BaseRepository<T, ID> {


//用于操作数据库
private final EntityManager em;

//父类没有不带参数的构造方法,这里手动构造父类
public BaseRepositoryImpl(Class<T> domainClass, EntityManager entityManager) {
super(domainClass, entityManager);
this.em = entityManager;
}

//通过EntityManager来完成查询
@Override
public List<Object[]> listBySQL(String sql) {
return em.createNativeQuery(sql).getResultList();
}

@Override
public void add(Object entity) {
em.persist(entity);
}

@Override
public void update(Object entity) {
em.merge(entity);
}

@Override
public <T1> void delete(Class<T1> entityClass, Object entityid) {
delete(entityClass, new Object[]{entityid});
}

@Override
public <T1> void delete(Class<T1> entityClass, Object[] entityids) {
for (Object id : entityids) {
em.remove(em.getReference(entityClass, id));
}
}

@Override
public <T1> T1 find(Class<T1> entityClass, Object entityId) {
return em.find(entityClass, entityId);
}

}

创建一个自定义的工厂BaseRepositoryFactoryBean,在这个工厂中注册我们自己定义的BaseRepositoryImpl的实现。

public class BaseRepositoryFactoryBean<R extends JpaRepository<T, I>, T,
I extends Serializable> extends JpaRepositoryFactoryBean<R, T, I> {

/**
* 接到factory之后,把factory扔了spring data jpa
*/

@Override
protected RepositoryFactorySupport createRepositoryFactory(EntityManager em) {
return new BaseRepositoryFactory(em);
}

/**
* //创建一个内部类,该类不用在外部访问
* 他的作用是将我们的baseReposity的实现类扔给factorybean
*
* @param <T>
* @param <I>
*/


private static class BaseRepositoryFactory<T, I extends Serializable>
extends JpaRepositoryFactory {


private final EntityManager em;

public BaseRepositoryFactory(EntityManager em) {
super(em);
this.em = em;
}

/**
* 通过这两个方法来确定具体的实现类,也就是Spring Data Jpa具体实例化一个接口的时候会去创建的实现类。
*/

//设置具体的实现类是BaseRepositoryImpl
@Override
protected Object getTargetRepository(RepositoryInformation information) {
return new BaseRepositoryImpl<T, I>((Class<T>) information.getDomainType(), em);
}

//设置具体的实现类的class
@Override
protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
return BaseRepositoryImpl.class;
}
}
}

至此我们的扩展接口就算完成了,接下来只需要写自定义接口来实现它就好了。
创建StudentExtendsRepository实现BaseRepository

public interface StudentExtendsRepository extends BaseRepository<student, String> {
//扩展的自定义方法
public student findById(String id);
}

创建服务控制类BaseController

import cn.entity.student;
import cn.service.StudentExtendsRepository;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.List;

/**
* 继承通用dao Created by shiyufeng on 2017/2/13.
*/

@Transactional // 事务
@RestController
@EnableAutoConfiguration // 让 Spring Boot 根据应用所声明的依赖来对 Spring 框架进行自动配置
@EnableTransactionManagement // 开启注解事务管理,等同于xml配置文件中的 <tx:annotation-driven />
public class BaseController {

@Resource
private StudentExtendsRepository studentExtendsRepository;

@RequestMapping("findStudentByBase")
public String getStudent() {
student student1 = studentExtendsRepository.find(student.class, "001");
return student1.toString();
}

@RequestMapping("findStudentByBase2")
public String getStudentAll() {
List<student> student = studentExtendsRepository.findAll();
String a = "";
for (student studnet1 : student) {
a = a + studnet1.toString();
}
return a;
}

@RequestMapping("addStudent")
public void addStudent() {
student stu = new student();
// 自动生成id
stu.setGrade("三年级");
stu.setName("addStudent");
studentExtendsRepository.add(stu);
}

@RequestMapping("updateStudent")
public void updateStudent() {
student stu = new student();
stu.setId("4");
stu.setGrade("update三年级");
stu.setName("updateStudent");
studentExtendsRepository.update(stu);
}

@RequestMapping("delStudent")
public void delStudent() {
studentExtendsRepository.delete(student.class, "4");
}
}

启动服务,访问BaseController里的映射对数据库进行简单操作。