← 返回首页
SpringBoot基础教程(二十一)
发表时间:2020-10-22 12:00:27
Spring Data JPA的封装

实际项目开发时,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);
    }
}