实际项目开发时,entity包下会有很多实体类,每个实体类都会对应数据库的一张表,那么咱们有必须对Spring Data JPA进行封装,避免专门为每个实体类实现Repository层和Service层。我们把所有实体类都涉及的一些通用操作封装起来,在父类中实现。
项目结构图如下:

实现步骤如下:
1.设计所有实体类的父类
package com.oracle.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.Column;
import javax.persistence.MappedSuperclass;
@MappedSuperclass
@Data
@NoArgsConstructor
@AllArgsConstructor
public class BaseEntity {
protected Integer version; //乐观锁
@Column(length = 32)
protected String createTime; //表示该记录的创建时间
@Column(length = 32)
protected String modifyTime; //表示该记录的最后一次修改时间
@Column(insertable = false,columnDefinition = "boolean default false")
protected boolean flag; //表示该记录是否是已经被删除的记录。
}
让Students继承BaseEntity
package com.oracle.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.io.Serializable;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity //表示这个类对应数据库中的一张表
public class Students extends BaseEntity implements Serializable,Cloneable {
//既然是表,就必须有主键
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY) //使用数据库默认的主键生成策略
private int sid; //主键
@Column(length = 20) //规定学生的姓名不超过20个字符
private String sname; //姓名,默认是占用255个字符。
@Column(length = 2)
private String gender; //性别
@Column(length = 32)
private String date; //出生日期
private String school; //所在学校
private String major; //所学的专业
private boolean status; //状态 1:在籍 0:辍学
}
2.设计所有实体的类父业务逻辑接口
package com.oracle.repository;
import com.oracle.entity.BaseEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.NoRepositoryBean;
/*
* JpaRepository继承PagingAndSortingRepository,实现一组JPA规范相关的方法,比如CRUD
* JpaSpecificationExecutor比较特殊,不属于Repository体系,实现一组JPA Criteria查询相关的方法,
* 可以实现复杂的条件查询和模糊查询
* */
/**
* 所有业务逻辑接口的父类泛型接口
* @param <T> 对应业务逻辑的类型
* @param <ID> 业务逻辑类型的主键类型
*/
@NoRepositoryBean
public interface BaseRepository<T extends BaseEntity,ID> extends JpaRepository<T, ID>, JpaSpecificationExecutor, CrudRepository<T,ID> {
}
3.学生业务逻辑接口继承自父业务逻辑接口
package com.oracle.repository;
import com.oracle.entity.Students;
import org.springframework.data.jpa.repository.JpaRepository;
public interface StudentsRepository extends BaseRepository<Students,Integer> {
//对于特殊需求的方法,这里需要单独来定义了。
}
4.定义所有服务层的父接口 该父接口封装了所有通用方法。
package com.oracle.service;
/*
* BaseService里面,封装了所有服务层的一些公共的操作,CRUD。
*
* */
import com.oracle.entity.BaseEntity;
import com.oracle.repository.BaseRepository;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import java.io.Serializable;
import java.util.List;
/**
*
* @param <T> 表示具体的类型
* @param <I> 表示该类型的主键类型
* @param <R> 表示该类型的Repository层的实现类型。
*/
public interface BaseService<T extends BaseEntity, I extends Serializable, R extends BaseRepository<T, I>> {
//针对所有的服务层都那些公共方法呢。
//1.查询所有
List<T> findAll();
//2.根据主键查询单个对象。
T getOne(I id);
//3.查询分页记录。
Page<T> findAllByPager(Pageable pageable);
//4.添加单个对象
T save(T obj);
//5.修改单个对象
T update(T obj);
//6.根据主键删除单个对象。
void deleteById(I id);
//7.批量添加
List<T> saveList(List<T> list);
//8.批量删除
void batchDelete(List<T> list);
}
5.定义父服务层接口的实现类 该类实现了所有通用方法。
package com.oracle.service.impl;
import cn.hutool.core.date.DateTime;
import com.oracle.entity.BaseEntity;
import com.oracle.repository.BaseRepository;
import com.oracle.service.BaseService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import javax.transaction.Transactional;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
public class BaseServiceImpl<T extends BaseEntity, I extends Serializable, R extends BaseRepository<T, I>> implements BaseService<T, I, R> {
@Autowired
protected R dao;
@Transactional
@Override
public List<T> findAll() {
return dao.findAll();
}
@Transactional
@Override
public T getOne(I id) {
return dao.getOne(id);
}
@Transactional
@Override
public Page<T> findAllByPager(Pageable pageable) {
return dao.findAll(pageable);
}
@Transactional(rollbackOn = Exception.class)
@Override
public T save(T obj) {
System.out.println("开始执行BaseServiceImpl-->save()");
Date d = new Date();
DateTime dt = DateTime.of(d);
obj.setCreateTime(dt.toString("yyyy-MM-dd HH:mm:ss"));
System.out.println("createTime is :"+obj.getCreateTime());
return dao.save(obj);
}
@Transactional(rollbackOn = Exception.class)
@Override
public T update(T obj) {
Date d = new Date();
DateTime dt = DateTime.of(d);
obj.setModifyTime(dt.toString("yyyy-MM-dd HH:mm:ss"));
return dao.save(obj);
}
@Transactional(rollbackOn = Exception.class)
@Override
public void deleteById(I id) {
dao.deleteById(id);
}
@Override
public List<T> saveList(List<T> list) {
//设置插入时间
for(T obj: list){
Date d = new Date();
DateTime dt = DateTime.of(d);
obj.setCreateTime(dt.toString("yyyy-MM-dd HH:mm:ss"));
}
return dao.saveAll(list);
}
@Override
public void batchDelete(List<T> list) {
dao.deleteInBatch(list);
}
}
6.分别定义StudentsService和StudentsServiceImpl
package com.oracle.service;
import com.oracle.entity.Students;
import com.oracle.repository.StudentsRepository;
import java.util.List;
public interface StudentsService extends BaseService<Students,Integer, StudentsRepository> {
}
package com.oracle.service.impl;
import com.oracle.entity.Students;
import com.oracle.repository.StudentsRepository;
import com.oracle.service.StudentsService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
@Service
public class StudentsServiceImpl extends BaseServiceImpl<Students,Integer,StudentsRepository> implements StudentsService {
}
7.编写测试类测试
package com.oracle.service;
import com.oracle.entity.Students;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
@RunWith(SpringRunner.class)//指定Junit4使用Spring提供的测试环境
@SpringBootTest
public class StudentsServiceTest {
@Resource
private StudentsService studentsService;
//测试保存单个学生对象
@Test
public void testSaveStudents() {
Students s = new Students();
s.setSname("令狐冲");
s.setGender("男");
s.setMajor("独孤九剑");
s.setSchool("西安交通大学");
s.setDate("2002-10-10");
s.setStatus(true);
studentsService.save(s);
System.out.println(s);
}
@Test
public void testQueryStudentsBySid() {
//查询黄药师
Students s = studentsService.getOne(1);
System.out.println(s);
}
//更新学生资料
@Test
public void testUpdateStudents() {
//更新黄药师的专业为九阴真经
Students s = studentsService.getOne(1);
s.setMajor("九阴真经");
studentsService.update(s);
System.out.println(s);
}
//查询所有学生
@Test
public void testQueryAllStudents() {
}
//删除学生
@Test
public void testDeleteStudentsBySid() {
}
//批量添加学生
@Test
public void testAddBatchStudents() {
List<Students> studentsList = new ArrayList<Students>();
Students s1 = new Students(100, "欧阳锋", "男", "1999-10-01", "石河子大学", "蛤蟆功", true);
Students s2 = new Students(100, "南帝", "男", "1999-10-01", "大理学院", "一阳指", true);
Students s3 = new Students(100, "洪七公", "男", "1999-10-01", "乞丐", "降龙十八掌", true);
studentsList.add(s1);
studentsList.add(s2);
studentsList.add(s3);
studentsService.saveList(studentsList);
}
}