JavaSpringBoot

SpringBoot使用JPA实现通用接口(增删查等)

2019-08-16  本文已影响12人  maxzhao_
title: SpringBoot使用JPA实现通用接口(增删查等)
date: 2019-08-16
author: maxzhao
tags:
  - JAVA
  - SpringBoot
  - JPA
  - Controller
  - EntityManager
categories:
  - SpringBoot
  - JPA
  - JAVA

一、前言

在我们的WEB项目中,会写很多很多接口,对于增删改的接口来说,都大致相同。所以在我们的项目中就可以使用通用接口的形式实现增删改。

最终实现是以EntityEntityManager对数据库进行操作。

这里使用SpringBoot JPA实现通用接口的 删除 功能。其它 Spring等项目思路大致相同。

其它 :

我把实体类、SQL、部分说明等放在了最后。

这里还要参考我的上一篇文章SpringBoot Jpa实体继承通用属性

二、BaseController实现

BaseController 是我们项目中实现通用接口的基础类。

ServiceRepository 都省略了接口类,测试的话自己写一下。

/**
 * BaseController
 * 基础的通用接口
 *
 * @author maxzhao
 * @date 2019-08-15 10:33
 */
public class BaseController<T extends BaseEntity, ID> {

    @Resource(name = "baseService")
    private BaseService<T, ID> baseService;
    /**
     * 这里是为了让继承此类的接口类,能传入当前接口操作的实体,然后通过 Service 传入 repository
     * 传入到 repository 之后 就可以使用 EntityManager 的通用方法了
     *
     * @param domainClass
     */
    public void setDomainClass(Class<T> domainClass) {
        baseService.setDomainClass(domainClass);
    }

    @ApiOperation(value = "/{id}", notes = "逻辑删除", response = ResultObj.class, httpMethod = "DELETE")
    @DeleteMapping(value = "{id}")
    @ResponseBody
    public ResultObj<String> del(@PathVariable(value = "id") ID id) {
        return baseService.del(id);
    }
}

Service

@Slf4j
@Service(value = "baseService")
public class BaseServiceImpl<T extends BaseEntity, ID> implements BaseService<T, ID> {
    @Autowired
    private BaseRepository<T, ID> baseRepository;
    /**
     * 这里是 domainClass 的跳板
     *
     * @param domainClass
     */
    @Override
    public void setDomainClass(Class<T> domainClass) {
        baseRepository.setDomainClass(domainClass);
    }

    @Override
    public ResultObj<String> del(ID id) {
        baseRepository.del(id);//这里到 repo 中模拟操作
        return ResultObj.getDefaultResponse("删除成功");
    }
}

Repository


/**
 * BaseRepositoryImpl
 *
 * @author maxzhao
 * @date 2019-08-15 11:11
 */
@Repository(value = "baseRepository")
@Transactional(readOnly = true)
public class BaseRepositoryImpl<T extends BaseEntity, ID> implements BaseRepository<T, ID> {
    @PersistenceContext
    private EntityManager entityManager;
    /**
     * 某个接口的实体类的类型
     */
    private Class<T> domainClass;

    @Override
    public void setDomainClass(Class<T> domainClass) {
        this.domainClass = domainClass;
    }

    @Override
    public Boolean del(ID id) {
        T entity = entityManager.find(domainClass, id);
        return true;
    }
}

至此,一个简单的、通用的删除接口就完成了。

删除是比较简单的,因为我做的项目一般都是逻辑删除,所有必须要自定义删除,而且想通用,就需要通用的实体属性,所以也就有了BaseEntity

BaseEntity 解读

这个类就是我前言中提到的通用实体属性的父类,这样就可以统一实体的通用属性,比如主键、逻辑删除状态、添加时间等。

@MappedSuperclass 实体继承映射注解要加载实体的父类上,比如如下代码:

/**
 * BaseEntity
 * 实体继承映射类基础,保存实体的通用属性
 *
 * @author maxzhao
 * @date 2019-08-15 09:39
 */
@Data
@Accessors(chain = true)
@MappedSuperclass//实体继承映射
public class BaseEntity implements Serializable {
    @Id
    @Column(name = "ID")
    @ApiModelProperty(value = "主键")
    private Long id;

    @Basic
    @Column(name = "DEL_STATUS")
    @ApiModelProperty(value = "状态 1启用 0 停用")
    private Integer delStatus;
}

其它代码

接口

@Api(value = "应用接口日志")
@RestController
@RequestMapping("appLogApi")
public class AppLogApiController extends BaseController<AppLogApi, Long> {

    @PostConstruct
    public void PostConstruct() {
        // 重点在这里,这是我能想出的比较简单的实现方法
        super.setDomainClass(AppLogApi.class);
    }
}

实体

/**
 * 应用接口日志
 *
 * @author author
 * @date 2019-7-23 15:38:57
 */
@Accessors(chain = true)
@Data
@Entity
@Table(name = "app_log_api", schema = "", catalog = "")
@ApiModel(value = "应用接口日志", description = "应用接口日志")
public class AppLogApi extends BaseEntity implements Serializable {
    private static final long serialVersionUID = -1L;

    @Basic
    @Column(name = "API")
    @ApiModelProperty(value = "请求地址")
    private String api;
    /******/
    public AppLogApi() {
    }
}
/**
 * BaseEntity
 * 实体集成映射类基础,保存实体的通用属性
 *
 * @author maxzhao
 * @date 2019-08-15 09:39
 */
@Data
@Accessors(chain = true)
@MappedSuperclass//实体集成映射
public class BaseEntity implements Serializable {
    @Id
    @Column(name = "ID")
    @ApiModelProperty(value = "主键")
    private Long id;

    @Basic
    @Column(name = "DEL_STATUS")
    @ApiModelProperty(value = "状态 1启用 0 停用")
    private Integer delStatus;
}
create table gt_boot.app_log_api
(
    id             bigint(64)    not null comment '主键'
        primary key,
    api            varchar(100)  null comment '请求地址',
    del_status    integer null 
)
    comment '应用接口日志';

@PostConstruct解读

从Java EE5规范开始,Servlet中增加了两个影响Servlet生命周期的注解:

修饰一个非静态的void()方法类似与init() destory()类似。写法有如下两种方式:

@PostConstruct
public void doA(){}

public @PostConstruct void doB(){}

加载顺序

[图片上传失败...(image-1b762b-1565938978247)]

与本文联系起来说

想要把实体AppLogApi.class传参到BaseRepositoryImpl中,就需要初始化bean之后才可以调用bean,但是@Autowired注入是发生在A的构造方法执行完之后的。

所以要在生成对象时初始化AppLogApi.class参数,就不能在构造函数中实现,这时候@PostContruct的作用就体现出来了,@PostContruct 会在依赖注入完成后被自动调用。

Constructor > @Autowired > @PostConstruct

本文地址:
SpringBoot使用JPA实现通用接口(增删查等)

推荐
SpringBoot Jpa实体继承通用属性
IDEA好用的插件
JAVA自定义注解

上一篇下一篇

猜你喜欢

热点阅读