Due to the products of the company belongs to the initial set up stage, the increasing of library database table, based on the control layer, business layer and persistence layer under this mode of development, the directory structure and changes frequently and realize the basic functions such as add and delete words too trival, so thinking decided to adopt template pattern to encapsulate the functionality
The technology stack uses springboot+ MyBatis direction, because the persistence layer uses MyBatis, so it directly adopts the secondary encapsulation tool Mybatis – Plus, in addition to myBatis – Plus provides a good template method, in addition to some method extension, mainly based on inheritance and generics to achieve
@[TOC]
The domain model
For simple description, only three domain model objects are used here, such as VO(display object, which is also used as a request response object in addition to Query object), DO(data object, one-to-one correspondence to database fields), Query(data Query object), etc., the inheritance relationship is,VO inherits DO Query inherits DO, so DO is the base class
BaseModel
Consider the basic operation scenarios from the perspective of services, most of which are add, delete, modify, and query. The following uses query as an example. In query scenarios, basic queries, such as conditional queries, Query list, Query paging, fuzzy Query, Query by primary key, Query by primary key set, Query interval, sort Query, etc. Since the Query object is used, the above queries are not limited to the condition of this object, so the Query model is extended and defined as the basic model is defined as follows
public class BaseModel implements Serializable {
private final static Pattern AZ=Pattern.compile("[A-Z]");
/**
* ids 主键集合
*/
private List<Integer> ids;
/** * sort asc desc */
private String orderBy;
/**
* 排序的字段
*/
private String orderByName;
/** * sorted field set */
private List<String> orderByNames;
/** * page size */
private Integer size;
/** * Number of pages */
private Integer page;
/** * keyword Query */
private String keyword;
/** * user id */
privateString userId; . Omit get/set methodsCopy the code
Created as a user table domain object
DO object
@Data
public class TUser extends BaseModel implements Serializable {
/ * * *@TableIdMybatis -plus primary key identifier Type = idtype. AUTO meaning primary key increment */
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
/** * User name */
private String username;
/** * Password */
private String password;
Copy the code
VO object
@Data
public class TUserVO extends TUser implements Serializable {}Copy the code
The Query object
@Data
public class TUserQuery extends TUser implements Serializable {}Copy the code
General development templates
The following template is based on Mybatis – Plus
The controller control layer
@RestController
@RequestMapping("/user")
@Slf4j
public class TUserController {
@Autowired
private TUserService tUserService;
/* * Query the user list * */
@RequestMapping("/getList")
public ResultUtil<List<TUserVO>> getList(@RequestBody TUserQuery tUserQuery) {
List<TUserVO> tUserList= tUserService.getList(tUser);
returnResultUtil.ok(tUserList); } ----- Deleted ----- Changed ----- AddedCopy the code
Service business layer
/** * Business layer interface definition */
public interface TUserService extends IService<TUser> {
List<TUserVO> getList(TUserQuery tUserQuery)
}
/** * Business interface implementation */
public class TUserServiceImpl extends ServiceImpl<TUserMapper, TUser> implements TUserService {
@Override
public List<TUserVO> getList(TUserQuery tUserQuery) {
return newArrayList<TUserVO>(); }}Copy the code
The dao persistence layer
@Repository
public interface TUserMapper extends BaseMapper<TUser> {
List<TUser> getList(TUserQuery tUser); . }Copy the code
Control layer template method
ContorllerExtend(Control layer template interface definition)
From the conventional control layer visible, basic each table should be so defined as the basis of the increase, deletion, change and check, then the basis of the increase, deletion, change and check is the common existence, as a part-time job touch the brick staff is unbearable, holding the thought of interface programming, we first define the control layer of the basic method interface
/** * Controller method extension *@param<DO> Persistence layer object *@param<VO> VO model *@param<Query> Query model * *@author cyp
* @Date: 2021/4/26 14:42 * /
public interface ContorllerExtend<DO.VO.Query> {
/** * query the list of single table data *@param query
* @return* /
ResultUtil<List<VO>> getList(Query query);
}
Copy the code
Because responding to data objects, receiving data objects, and querying data objects all involve the domain model, define the interface to the domain model
Where there is an interface there must be an implementation, so let’s define BaseController as an implementation
BaseController(Control layer template interface implementation)
BaseController is defined by inheritance
/** * Basecontorller base template controller, can be directly inherited using **@author cyp
* @Date: 2021/4/26 16:08 * /
public abstract class BaseController<DO extends BaseModel.VO.Query > implements ContorllerExtend<DO.VO.Query> {
/** * control layer template set query implementation **@paramQuery Query model *@return* /
@Override
@RequestMapping(value = "/getList", method = {RequestMethod.POST, RequestMethod.GET})
public ResultUtil<List<VO>> getList(Query query) {
return ResultUtil.ok();
}
Copy the code
The DO model in BaseController inherits BaseModel by generics using the underlying query method field, For example, query.getids () gets the set of primary keys that are passed in, and the interface and implementation are done. This only implements the control layer, and we need to call the business layer. We change the BaseController to call the business layer
/** * Basecontorller base template controller, can be directly inherited using **@author cyp
* @Date: 2021/4/26 16:08 * /
public abstract class
BaseController<DO extends BaseModel.VO.Query.Service extends IServiceExtend<DO.VO.Query>
> implements ContorllerExtend<DO.VO.Query> {
@Autowired
protected Service baseService;
/** * control layer template set query implementation **@paramQuery Query model *@return* /
@Override
@RequestMapping(value = "/getList", method = {RequestMethod.POST, RequestMethod.GET})
public ResultUtil<List<VO>> getList(Query query) {
return ResultUtil.ok();
}
Copy the code
Service extends IServiceExtend
Service extends IServiceExtend
Service extends IServiceExtend
We use this as the definition of the business layer template method interface
IServiceExtend(Business layer interface extension)
public interface IServiceExtend<DO.VO.Query> {
/** * query table list *@param query
* @return* /
List<VO> getList(Query query);
}
Copy the code
ServiceImplExtend(Business Layer interface implementation)
As with the control layer template interface implementation, we implement this
public abstract class
ServiceImplExtend<
DO extends BaseModel.VO extends DO.Query extends DO.M extends BaseMapperExtend<DO.Query>> extends ServiceImpl<M.DO>
implements IServiceExtend<DO.VO.Query> {
/** * Business layer template interface implementation */
@Override
public List<VO> getList(Query query) {
beforeQuery(query);
List<DO> list = getBaseMapper().getList(query);
afterQuery(list)
returnCollectionUtil.isNotEmpty(list)? JsonUtil.toList(list,voClass):Collections.emptyList(); }/** ** Operation before query */
public void beforeQuery(Query query){}/** ** After query */
public void afterQuery( List<DO> list){}/** * Get VO class *@return* /
public Class<DO> getDoClass(a) {
Type superClass = getClass().getGenericSuperclass();
return (Class<DO>) ((ParameterizedType) superClass).getActualTypeArguments()[0];
}
/** * Get VO class *@return* /
public Class<VO> getVoClass(a) {
Type superClass = getClass().getGenericSuperclass();
return (Class<VO>) ((ParameterizedType) superClass).getActualTypeArguments()[1];
}
/** * Get Query class *@return* /
public Class<Query> getQueryClass(a) {
Type superClass = getClass().getGenericSuperclass();
return (Class<Query>) ((ParameterizedType) superClass).getActualTypeArguments()[2]; }}Copy the code
M extends BaseMapperExtend < DO, Query > > M is your definition of dao layer interface file such as TUserMapper it inherited BaseMapperExtend is the extension of his own persistence layer interface interface
You can customize template methods, such as beforeQuery() before a query, afterQuery() after a query, overridden in TUserServiceImpl
BaseMapperExtend(Persistence layer custom interface)
/** * baseMapper extension **@param <DO>
*/
public interface BaseMapperExtend<DO.Query> extends BaseMapper<DO> {
/** * conditional query list *@param query
* @return* /
List<DO> getList(Query query);
}
Copy the code
Extends BaseMapper Extends BaseMapper to the method wrapped by Mybatis – Plus
TUserMapper.xml
Generate XML SQL files based on the code generator
<resultMap id="BaseResultMap" type="com.xnnf.system.MO.DO.TUser">
<result column="id" property="id"/>
<result column="username" property="username"/>
<result column="password" property="password"/>
</resultMap>
<! -- table field -->
<sql id="baseColumns">
id
, username
, password
</sql>
<! -->
<select id="getList" resultMap="BaseResultMap">
SELECT
<include refid="baseColumns"/>
FROM t_user
<where>
<if test="ids! =null and ids.size()! = 0">
and id in
<foreach collection="ids" item="id" separator="," open="(" close=")" index="index">
#{id}
</foreach>
</if>
<if test="id! =null">
and id =#{id}
</if>
<if test="username! =null and username! = "">
and username =#{username}
</if>
<if test="password! =null and password! = "">
and password =#{password}
</if>
<! -- String fuzzy matching -->
<if test="keyword! =null and keyword! = "">
and (
username like concat('%',#{keyword,jdbcType=VARCHAR},'%')
)
</if>
<! -- Sort by field -->
<if test="orderBy! =null and orderBy! ='' and orderByName! =null and orderByName! = "">
and 1=1 order BY ${orderByName} ${orderBy}
</if>
</where>
</select>
Copy the code
With that done, template methods are defined, combined with code generators, to improve efficiency in new table operations