前言
上两篇文章中我们说了下怎么去做《通用Mapper》和《通用分页》,来简化单表操作下的DAO层的逻辑,然而我们的目标仅仅是这样么?显然不是,本章为你讲解项目中通用的service的抽离,用于简化你的业务逻辑层,愿你能在其中得到启发和深入思考。
思考
首先我们先思考一下,对于SERVICE层有哪些是可以被公共出来的东西?
好,我先来说几个:
- 对于单张表的增、删、改、查(单条查、批量查、分页查)功能
- 单张表的增、删、改、查功能相对应的缓存功能(缓存有很多方式:ehcache缓存、redis缓存等等)
- 对数状结构的表操作(树状结构比较常见,比如:后台权限用到的资源树表、地域城市表、组织架构表等等的业务场景)
- 很多的主功能业务表中可能会增加一个扩展字段用于存储附加属性,那如果我们把这种key->value结构关系单独抽离一个功能,来简化我们对这种附加属性的使用,是不是会更好呢(比如:在order表中,总是有一些并不是所有订单都会有的属性,这时我们可能会将这些属性存储在一个叫ext的字段中,格式可能是json格式的字符串也可能是key:value这种数据结构,但是想想这种方式的存储是不是很不利于结构化搜索,而且还要在主表上维护扩展属性的增删改查功能,抽离下公共功能的附加表是个很好的方式)
好了,上面说了几点关于业务逻辑层我们可能会有哪些公共的逻辑可以被抽离,在企业开发中,可不仅仅是这样,对于不同的公司业务也都有很大差异,所以你也可以向我一样思考一下,在你的企业里,有哪些像上述所说的功能可以被抽离的呢?
实现上述思考
因为篇幅有限,所以对于通用service我们会分几篇文章来详细讲解下,本章我们只说一下我们的思考1:对于单张表的增、删、改、查功能。
那好,我们在紧接着想想,既然是要抽离单张表增删改查SERVICE层,那我们肯定是要有一个相对通用的DAO层来完成与数据库的沟通了,没错,我们就是借助上篇讲到的通用Mapper来实现的。
下面让我们来看下具体的代码实现。
PO类统一接口:
package com.zhuma.demo.comm.model.po;
import com.zhuma.demo.comm.model.Model;
import java.util.Date;
public interface PO<PK> extends Model {
PK getId();
void setId(PK id);
Date getCreateTime();
void setCreateTime(Date createTime);
Date getUpdateTime();
void setUpdateTime(Date updateTime);
}
备注
- PO类(也就是数据库表对应的实体类)的统一接口,所有的PO类都应该实现该接口。
- 我们的实体类目录会分的相对详细些:po(persistant object 持久对象)、qo(query object查询对象)、vo(view object 值对象)、bo(business object 业务对象)。
- 从该类中可以看出如果你是PO类需要至少三个参数,id:主键、createTime:创建时间 、updateTime:更新时间,之所以将它们三个都抽离因为这在绝大多数的po下都是公用的,如果你想说我的表就是一个日志记录表都没有更新的情况,所以也没有updateTime,这里,多加个字段无伤大雅,定义这几个参数好处后面会说下。
BasePO类:
package com.zhuma.demo.comm.model.po;
import java.util.Date;
import javax.persistence.Column;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @desc 基础PO类
* @author zhuamer
* @since 7/3/2017 2:14 PM
*/
@Data
public abstract class BasePO<PK> implements PO<PK> {
@ApiModelProperty(value = "创建时间")
@Column(name = "create_time")
private Date createTime;
@ApiModelProperty(value = "更新时间")
@Column(name = "update_time")
private Date updateTime;
}
备注
- 该类是上面PO接口的一个部分实现,如果你懒得定义createTime、updateTime字段可以让你的持久化类直接继承该类即可。
通用接口定义:
package com.zhuma.demo.comm.service;
/**
* @desc 通用服务类
*
* @author zhuamer
* @since 10/18/2017 18:31 PM
*/
public interface CrudService<E, PK> extends
InsertService<E, PK>,
UpdateService<E,PK>,
DeleteService<PK>,
SelectService<E, PK> {
}
解释说明
- 该接口是本章所讲的核心接口类,看名字可以看出Crud就代表该接口具有增删改查的功能,它的能力也都是继承相应的具体接口得来。
- 业务操作service接口类如果想使用通用service的功能,都应该继承该接口以获得相应方法能力。
- 使用时需要传递两个泛型值,E: 具体的PO类, PK:PO类的主键类型。
通用增加接口:
package com.zhuma.demo.comm.service;
/**
* @desc 基础插入服务
*
* @author zhuamer
* @since 10/18/2017 18:31 PM
*/
public interface InsertService<E, PK> {
/**
* 添加一条数据
*
* @param record 要添加的数据
* @return 添加后生成的主键
*/
PK insert(E record);
}
通用删除接口:
package com.zhuma.demo.comm.service;
/**
* @desc 基础删除服务
*
* @author zhuamer
* @since 10/18/2017 18:31 PM
*/
public interface DeleteService<PK> {
/**
* 根据主键删除记录
*
* @param pk 主键
* @return 影响记录数
*/
int deleteByPk(PK pk);
/**
* 根据主键删除记录
*
* @param pks 主键集合
* @return 影响记录数
*/
int deleteByPks(Iterable<PK> pks);
}
通用修改接口:
package com.zhuma.demo.comm.service;
/**
* @desc 基础更新服务
*
* @author zhuamer
* @since 10/18/2017 18:31 PM
*/
public interface UpdateService<E, PK> {
/**
* 修改记录信息
*
* @param pk 主键
* @param record 要修改的对象
* @return 影响记录数
*/
int updateByPk(PK pk, E record);
/**
* 修改记录信息
*
* @param pk 主键
* @param record 要修改的对象
* @return 影响记录数
*/
int updateByPkSelective(PK pk, E record);
/**
* 保存或修改
*
* @param record 要修改的数据
* @return 影响记录数
*/
PK saveOrUpdate(E record);
}
通用查询接口:
package com.zhuma.demo.comm.service;
import com.zhuma.demo.comm.model.qo.PageQO;
import com.zhuma.demo.comm.model.vo.PageVO;
import java.util.List;
/**
* @desc 基础查看服务
*
* @author zhuamer
* @since 10/18/2017 18:31 PM
*/
public interface SelectService<E