# xp-mapper
**Repository Path**: wxpcode123/xp-mapper
## Basic Information
- **Project Name**: xp-mapper
- **Description**: 这是一个mybatis通用的service接口实现。
- **Primary Language**: Java
- **License**: Apache-2.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 2
- **Forks**: 0
- **Created**: 2020-03-05
- **Last Updated**: 2022-09-08
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# MyBatis 通用 Mapper4的扩展
## 介绍
这是一个Mybatis通用的service接口实现,通过继承service类和通用Mapper接口,实现对单表的增删改查。对查询参数可以任意自定义实体类、map等类型,返回参数可以自定义返回参数,通过对象拷贝实现参数自定义转换。
## 软件架构
软件架构说明
spring-boot-starter、Mybatis、mapper等框架集成。
## 使用教程
### 1. 引入依赖包:
```
center.wxp
mybatis.mapper
1.1.5
```
### 2. 对象关系映射
示例针对 MySql 数据库(数据库对主键影响较大,和 insert 关系密切,主键使用的是雪花算法)。
数据库表:
```
CREATE TABLE `user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`name` varchar(30) DEFAULT NULL COMMENT '姓名',
`age` int(11) DEFAULT NULL COMMENT '年龄',
`email` varchar(50) DEFAULT NULL COMMENT '邮箱',
`create_date` datetime DEFAULT NULL COMMENT '创建时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;
```
对应的 Java 实体类型如下:
```
@ApiModelProperty(value = "主键ID")
@NotNull(message="主键ID不能为空")
@Id
private String id;
@ApiModelProperty(value = "姓名")
private String name;
@ApiModelProperty(value = "年龄")
private Integer age;
@ApiModelProperty(value = "邮箱")
private String email;
@ApiModelProperty(value = "创建时间")
@Column(name = "create_date")
private Date createDate;
```
最简单的情况下,只需要一个 @Id 标记字段为主键即可。数据库中的字段名和实体类的字段名是完全相同的,这中情况下实体和表可以直接映射。
### 3、查询接口示列:
#### 3.1 自定义实体类
说明:参数自动判空,但是对空字符不能判断!
参数类:
```
@Data
public class UserListDto {
@ApiModelProperty(value = "主键ID")
private String id;
@ApiModelProperty(value = "姓名")
private String name;
@ApiModelProperty(value = "年龄")
private Integer age;
}
```
#### List findListByObject(Object obj) 接口
代码如下:
```
public Result> objList(UserListDto dto) {
List list = userService.findListByObject(dto);
return Result.ok().setData(list);
}
```
SQL日志:
```
Preparing: SELECT id,name,age,email,create_date FROM user WHERE ( ( name = ? and id = ? and age = ? ) )
Parameters: Jone(String), 1(Long), 18(Integer)
```
UserListDto 类定义参数要跟表生成实体类字段名称一致,就可以进行查询。
#### List findListByMap(Map map) 接口
map:查询参数。
代码:
```
Map map = new HashMap<>();
map.put("id", dto.getId());
map.put("name", dto.getName());
list = userService.findListByMap(map);
```
SQL日志:
```
Preparing: SELECT id,name,age,email,create_date FROM user WHERE ( ( name = ? and id = ? ) )
Parameters: Jone(String), 1(Long)
```
#### List findListByOnly(String fieldName, Object value) 接口
fieldName:字段名属性,value:字段值
代码:
```
List list = new ArrayList<>();
try{
list = userService.findListByOnly("id", id);
```
打印sql:
```
SELECT id,name,age,email,create_date FROM user WHERE ( ( id = ? ) )
```
#### ArrayList findListByObject(Object obj, Class m) 接口
obj:查询参数
Class m:是自定义返回参数类。
返回实体类:
```
@Data
public class UserListVo {
@ApiModelProperty(value = "主键ID")
private Long id;
@ApiModelProperty(value = "姓名")
private String name;
}
```
代码:
```
List list = new ArrayList<>();
try{
list = userService.findListByObject(dto, UserListVo.class);
```
打印sql:
```
SELECT name , id FROM user WHERE ( ( id = ? ) )
```
3.2通过注解查询:
查询条件定义:id使用数组查询,创建时间在某个区间段,时间使用倒序返回,姓名使用模糊查询。
参数实体类:
```
@Data
public class UserListAnnotationDto {
@ApiModelProperty(value = "主键IDS")
@ParamCondition(pattern = "in",entityName = "id")
private String[] ids;
@ApiModelProperty(value = "姓名")
@ParamCondition(pattern = "like",fuzzyPosition = "all")
private String name;
@ApiModelProperty(value = "年龄")
private Integer age;
@ApiModelProperty(value = "开始创建时间")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ParamCondition(pattern = ">=",entityName = "createDate")
private Date beginCreateDate;
@ApiModelProperty(value = "结束创建时间")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ParamCondition(pattern = "<=", entityName = "createDate")
private Date endCreateDate;
}
```
代码:
```
@ApiOperation(value = "Annotation查询参数实体类(list不分页)")
@GetMapping("/objAnnotationList")
public Result> objAnnotationList(UserListAnnotationDto dto) {
List list = new ArrayList<>();
try{
//User.class是表实体类、dto查询参数,ConditionRewrite.equalToCondition注解解析
Condition condition = ConditionRewrite.equalToCondition(new Condition(User.class), dto);
list = userService.findListByCondition(condition);
}catch (Exception e) {
log.error("UserController 获取信息异常:{}", e);
return Result.failure().setCode(StatusCode.FAILURE.getCode()).setMsg("UserController 获取信息异常!");
}
return Result.ok().setData(list);
}
```
打印sql:
```
Preparing: SELECT id,name,age,email,create_date FROM user WHERE ( ( id in ( ? , ? ) and name like ? and create_date >= ? and create_date <= ? ) )
Parameters: 1(Long), 2(Long), %J%(String), 2020-03-20 16:48:50.0(Timestamp), 2020-03-20 16:48:50.0(Timestamp)
```
### 4、保存
#### String saveSelectiveIdObject(Object obj)接口:有选择保存参数。自动加入主键id,id使用雪花算法。
String 返回雪花算法id。
代码如下:
```
@ApiOperation(value = "添加信息")
@PostMapping("/add")
public Result add(User user) {
String id = userService.saveSelectiveId(user);
return Result.ok().setData(id);
}
```
SQL日志:
```
Preparing: INSERT INTO user ( id,name,age,email ) VALUES( ?,?,?,? )
Parameters: 691656638020452352(String), 老王(String), 20(Integer), 1099@qq.com(String)
```
#### int saveOrUpdateKeySelective(Object obj)保存或更新,当主键冲突时更新信息。
int:返回保存或更新行数
代码如下:
```
@ApiOperation(value = "添加或更新信息")
@PostMapping("/addOrUpdate")
public Result addOrUpdate(User user) {
int count = userService.saveOrUpdateKeySelective(user);
return Result.ok().setData(count);
}
```
SQL日志:
```
Preparing: INSERT INTO user ( id,name,age,email ) VALUES( ?,?,?,? ) on duplicate key update name = ?,age = ?,email = ?
Parameters: 691656638020452352(String), 张三(String), 30(Integer), 1099272020@qq.com(String), 张三(String), 30(Integer), 1099272020@qq.com(String)
```
#### int saveOrUpdateKeyList(List models),批量保存或更新。
参数:
```
[
{
"age": 60,
"email": "1099272020@qq.com",
"id": "691656638020452352",
"name": "张三"
},
{
"age": 50,
"email": "12346@qq.com",
"id": "691656638020452353",
"name": "赵六"
}
]
```
代码如下:
```
@ApiOperation(value = "批量保存或更新信息")
@PostMapping("/batchAddOrUpdate")
public Result batchAddOrUpdate(@RequestBody List list) {
for (User user : list) {
user.setCreateDate(new Date());
}
int count = userService.saveOrUpdateKeyList(list);
return Result.ok().setData(count);
}
```
SQL日志:
```
Preparing: INSERT INTO user ( id,name,age,email,create_date ) VALUES ( ?,?,?,?,? ) , ( ?,?,?,?,? ) on duplicate key update id=VALUES (id ),name=VALUES (name ),age=VALUES (age ),email=VALUES (email ),create_date=VALUES (create_date )
Parameters: 691656638020452352(String), 张三(String), 60(Integer), 1099272020@qq.com(String), 2020-03-23 15:36:24.714(Timestamp), 691656638020452353(String), 赵六(String), 50(Integer), 12346@qq.com(String), 2020-03-23 15:36:24.714(Timestamp)
```
### 5、更新
#### int updateBySelectiveObject(Object tbO, Object obj),更新。
tbO:更新表字段。
obj:更新条件参数。
代码:
```
@ApiOperation(value = "修改信息")
@PutMapping("/update")
public Result update(User user) {
try {
userService.updateBySelectiveObject(user,user);
} catch (Exception e) {
log.error("UserController 更新信息异常:{}", e);
return Result.failure().setCode(StatusCode.FAILURE.getCode()).setMsg("UserController 更新信息异常!");
}
return Result.ok();
}
```
```
这里输入代码
```
SQL日志:
```
Preparing: UPDATE user SET name = ?,email = ? WHERE ( ( name = ? and id = ? and email = ? ) )
Parameters: 王二(String), 1099272022@qq.com(String), 王二(String), 1(String), 1099272022@qq.com(String)
```
### 6、删除
#### int deleteBySelectCondition(Condition condition),通过查询参数作为删除条件。
代码:
```
Condition condition = new Condition(User.class);
Condition.Criteria criteria = condition.createCriteria();
criteria.andNotIn("id", Arrays.asList((String[]) ids));
criteria.andEqualTo("age", 12);
userService.deleteBySelectCondition(condition);
```
删除不在ids并且age等于12的数据。
SQL日志:
```
Preparing: DELETE FROM user WHERE id IN (SELECT id FROM (SELECT id FROM user WHERE ( ( id not in ( ? ) and age = ? ) ) ) AS id)
Parameters: 1(String), 12(Integer)
```
### 7、注解类ConditionRewrite使用说明
#### 7.1注解类
```
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ParamCondition {
String entityName() default "";
String pattern();
String patternType() default "and";
String fuzzyPosition() default "";
String order() default "";
String orderType() default "desc";
}
```
entityName:表字段名称,不填写的话默认取实体类名称。
示列:这里取的是createDate。
```
@ParamCondition(pattern = "<=", entityName = "createDate")
private Date endCreateDate;
```
##### pattern:查询符号,可取值(is not null、=、!=、>、>=、<、<=、in、not in、like、not like),默认值:=。
##### patternType:参数连接符号,可取值(and、or),默认值:and。
##### fuzzyPosition:模糊查询符号,需要和like和not like一起使用,可取值(before(前模糊)、after(后模糊)、all(前后模糊))。
##### order:排序,可取值(order)
##### orderType:排序类型,和order一起使用,可取值(desc,asc)
#### 7.2注解使用示列:
```
@Data
public class UserListAnnotationDto {
@ApiModelProperty(value = "主键IDS")
@ParamCondition(pattern = "in",entityName = "id")
private Long[] ids;
@ApiModelProperty(value = "姓名")
@ParamCondition(pattern = "like",fuzzyPosition = "all")
private String name;
@ApiModelProperty(value = "年龄")
@ParamCondition(order = "order",orderType = "desc")
private Integer age;
@ApiModelProperty(value = "开始创建时间")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ParamCondition(pattern = ">=",entityName = "createDate")
private Date beginCreateDate;
@ApiModelProperty(value = "结束创建时间")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ParamCondition(pattern = "<=", entityName = "createDate")
private Date endCreateDate;
}
```
SQL日志:
```
Preparing: SELECT id,name,age,email,create_date FROM user WHERE ( ( id in ( ? ) and name like ? and create_date >= ? and create_date <= ? ) ) order by age DESC
Parameters: 1(Long), %J%(String), 2020-03-20 16:48:50.0(Timestamp), 2020-03-20 16:48:50.0(Timestamp)
```
#### 码云特技
##### 1、个人CSDN博客地址:https://blog.csdn.net/xp_lx1
##### 2、通用mapper文档:https://github.com/abel533/Mapper/wiki
##### 3、使用demo地址:https://gitee.com/wxpcode123/mybatis-mapper-demo