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