一、前言
在我们的WEB
项目中,会写很多很多接口,对于增删改的接口来说,都大致相同。所以在我们的项目中就可以使用通用接口的形式实现增删改。
最终实现是以Entity
与 EntityManager
对数据库进行操作。
这里使用SpringBoot JPA
实现通用接口的 删除 功能。其它 Spring
等项目思路大致相同。
其它 :
我把实体类、SQL
、部分说明等放在了最后。
这里还要参考我的上一篇文章SpringBoot Jpa实体继承通用属性。
二、BaseController
实现
BaseController
是我们项目中实现通用接口的基础类。
Service
、Repository
都省略了接口类,测试的话自己写一下。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
|
public class BaseController<T extends BaseEntity, ID> {
@Resource(name = "baseService") private BaseService<T, ID> baseService;
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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| @Slf4j @Service(value = "baseService") public class BaseServiceImpl<T extends BaseEntity, ID> implements BaseService<T, ID> { @Autowired private BaseRepository<T, ID> baseRepository;
@Override public void setDomainClass(Class<T> domainClass) { baseRepository.setDomainClass(domainClass); }
@Override public ResultObj<String> del(ID id) { baseRepository.del(id); return ResultObj.getDefaultResponse("删除成功"); } }
|
Repository
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
|
@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
实体继承映射注解要加载实体的父类上,比如如下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
@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; }
|
@DynamicInsert 注解
@DynamicInsert
在实体类的父类上时,是不会对子类的属性产生效果的,对父类自己的属性也没有效果。
其它代码
接口
1 2 3 4 5 6 7 8 9 10 11
| @Api(value = "应用接口日志") @RestController @RequestMapping("appLogApi") public class AppLogApiController extends BaseController<AppLogApi, Long> {
@PostConstruct public void PostConstruct() { super.setDomainClass(AppLogApi.class); } }
|
实体
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
@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() { } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
@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; }
|
1 2 3 4 5 6 7 8
| 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生命周期的注解:
@PostConstruct
@PreDestroy
修饰一个非静态的void()
方法类似与init()
destory()
类似。写法有如下两种方式:
1 2 3 4
| @PostConstruct public void doA(){}
public @PostConstruct void doB(){}
|
加载顺序
与本文联系起来说
想要把实体AppLogApi.class
传参到BaseRepositoryImpl
中,就需要初始化bean
之后才可以调用bean
,但是@Autowired
注入是发生在A的构造方法执行完之后的。
所以要在生成对象时初始化AppLogApi.class
参数,就不能在构造函数中实现,这时候@PostContruct
的作用就体现出来了, @PostContruct
会在依赖注入完成后被自动调用。
Constructor > @Autowired > @PostConstruct
本文地址: SpringBoot使用JPA实现通用接口(增删查等)
推荐
SpringBoot Jpa实体继承通用属性
IDEA好用的插件
JAVA自定义注解
本文地址: https://github.com/maxzhao-it/blog/post/31330/