mirror of
https://gitee.com/mybatis-flex/mybatis-flex.git
synced 2025-12-07 00:58:24 +08:00
feat:@RelationOneToMany支持splitBy字符分割
test:增加测试@RelationOneToMany的splitBy字符分割查询 doc:增加 @RelationOneToMany splitBy介绍
This commit is contained in:
parent
45e5332553
commit
4dc975da37
@ -230,7 +230,128 @@ public class Account implements Serializable {
|
||||
|
||||
> 多对多注解 `@RelationManyToMany` 也是如此。
|
||||
|
||||
**splitBy 分割查询** <Badge type="tip" text="v1.6.8" />
|
||||
|
||||
若 `selfField` 是一个 `由字符拼接而成的列表(如 1,2,3)`,那么,我们可以通过配置 `splitBy` 来指定使用 `selfField` 的值根据字符切割后查询,
|
||||
如下代码所示:
|
||||
|
||||
```java 8
|
||||
@Table(value = "tb_patient")
|
||||
public class PatientVO1 implements Serializable {
|
||||
private static final long serialVersionUID = -2298625009592638988L;
|
||||
|
||||
/**
|
||||
* ID
|
||||
*/
|
||||
@Id
|
||||
private Integer patientId;
|
||||
|
||||
/**
|
||||
* 姓名
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 所患病症(对应字符串类型) 英文逗号 分割
|
||||
*/
|
||||
private String diseaseIds;
|
||||
|
||||
/**
|
||||
* 患者标签(对应数字类型) / 分割
|
||||
*/
|
||||
private String tagIds;
|
||||
|
||||
@RelationOneToMany(
|
||||
selfField = "diseaseIds",
|
||||
splitBy = ",", //使用 , 进行分割
|
||||
targetTable = "tb_disease", //只获取某个字段值需要填入目标表名
|
||||
targetField = "diseaseId", //测试目标字段是字符串类型是否正常转换
|
||||
valueField = "name" //测试只获取某个字段值是否正常
|
||||
)
|
||||
private List<String> diseaseNameList;
|
||||
|
||||
@RelationOneToMany(
|
||||
selfField = "tagIds",
|
||||
splitBy = "/", //使用 / 进行分割
|
||||
targetField = "tagId" //测试目标字段是数字类型是否正常转换
|
||||
)
|
||||
private List<Tag> tagList;
|
||||
|
||||
@RelationOneToMany(
|
||||
selfField = "diseaseIds",
|
||||
splitBy = ",", //使用 , 进行分割
|
||||
targetField = "diseaseId", //测试目标字段是字符串类型是否正常转换
|
||||
mapKeyField = "diseaseId" //测试Map映射
|
||||
)
|
||||
private Map<String, Disease> diseaseMap;
|
||||
|
||||
//getter setter toString
|
||||
}
|
||||
```
|
||||
|
||||
进行查询
|
||||
```java
|
||||
PatientVO1 patientVO1 = patientMapper.selectOneWithRelationsByQueryAs(QueryWrapper.create().orderBy(PatientVO1::getPatientId, false).limit(1), PatientVO1.class);
|
||||
System.out.println(JSON.toJSONString(patientVO1));
|
||||
```
|
||||
|
||||
其执行的 SQL 如下:
|
||||
|
||||
```sql
|
||||
SELECT `patient_id`, `name`, `disease_ids`, `tag_ids` FROM `tb_patient` ORDER BY `patient_id` DESC LIMIT 1;
|
||||
|
||||
SELECT disease_id, name FROM `tb_disease` WHERE `disease_id` IN ('1', '2', '3', '4');
|
||||
SELECT `tag_id`, `name` FROM `tb_tag` WHERE `tag_id` IN (1, 2, 3);
|
||||
SELECT `disease_id`, `name` FROM `tb_disease` WHERE `disease_id` IN ('1', '2', '3', '4');
|
||||
```
|
||||
|
||||
查询结果:
|
||||
```json
|
||||
{
|
||||
"patientId": 4,
|
||||
"name": "赵六",
|
||||
"diseaseIds": "1,2,3,4",
|
||||
"tagIds": "1/2/3",
|
||||
"diseaseNameList": [
|
||||
"心脑血管疾病",
|
||||
"消化系统疾病",
|
||||
"神经系统疾病",
|
||||
"免疫系统疾病"
|
||||
],
|
||||
"tagList": [
|
||||
{
|
||||
"name": "VIP",
|
||||
"tagId": 1
|
||||
},
|
||||
{
|
||||
"name": "JAVA开发",
|
||||
"tagId": 2
|
||||
},
|
||||
{
|
||||
"name": "Web开发",
|
||||
"tagId": 3
|
||||
}
|
||||
],
|
||||
"diseaseMap": {
|
||||
"1": {
|
||||
"diseaseId": "1",
|
||||
"name": "心脑血管疾病"
|
||||
},
|
||||
"2": {
|
||||
"diseaseId": "2",
|
||||
"name": "消化系统疾病"
|
||||
},
|
||||
"3": {
|
||||
"diseaseId": "3",
|
||||
"name": "神经系统疾病"
|
||||
},
|
||||
"4": {
|
||||
"diseaseId": "4",
|
||||
"name": "免疫系统疾病"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 多对一 `@RelationManyToOne`
|
||||
|
||||
|
||||
@ -34,6 +34,12 @@ public @interface RelationOneToMany {
|
||||
*/
|
||||
String selfField() default "";
|
||||
|
||||
/**
|
||||
* 当前字段值根据字符串分割
|
||||
* @return 分割字符串
|
||||
*/
|
||||
String splitBy() default "";
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 目标实体类对应的表的 schema 模式。
|
||||
|
||||
@ -35,6 +35,7 @@ class OneToMany<SelfEntity> extends ToManyRelation<SelfEntity> {
|
||||
, annotation.extraCondition()
|
||||
, annotation.selectColumns());
|
||||
|
||||
this.splitBy = annotation.splitBy();
|
||||
this.orderBy = annotation.orderBy();
|
||||
this.limit = annotation.limit();
|
||||
|
||||
|
||||
@ -29,6 +29,8 @@ class ToManyRelation<SelfEntity> extends AbstractRelation<SelfEntity> {
|
||||
protected FieldWrapper mapKeyFieldWrapper;
|
||||
protected String orderBy;
|
||||
protected long limit = 0;
|
||||
protected String splitBy;
|
||||
|
||||
|
||||
|
||||
public ToManyRelation(String selfField, String targetSchema, String targetTable, String targetField, String valueField,
|
||||
@ -42,6 +44,34 @@ class ToManyRelation<SelfEntity> extends AbstractRelation<SelfEntity> {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建查询目标对象的 QueryWrapper
|
||||
*
|
||||
* @param targetValues 条件的值
|
||||
* @return QueryWrapper
|
||||
*/
|
||||
@Override
|
||||
public QueryWrapper buildQueryWrapper(Set<Object> targetValues) {
|
||||
if (StringUtil.isNotBlank(splitBy) && CollectionUtil.isNotEmpty(targetValues)) {
|
||||
Set<Object> newTargetValues = new HashSet<>();
|
||||
for (Object targetValue : targetValues) {
|
||||
if (targetValue == null) {
|
||||
continue;
|
||||
}
|
||||
if (!(targetValue instanceof String)) {
|
||||
throw FlexExceptions.wrap("被切割字段只支持String类型");
|
||||
}
|
||||
String[] splitValues = ((String) targetValue).split(splitBy);
|
||||
for (String splitValue : splitValues) {
|
||||
//优化分割后的数据类型(防止在数据库查询时候出现隐式转换)
|
||||
newTargetValues.add(ConvertUtil.convert(splitValue, targetFieldWrapper.getFieldType()));
|
||||
}
|
||||
}
|
||||
targetValues = newTargetValues;
|
||||
}
|
||||
return super.buildQueryWrapper(targetValues);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void customizeQueryWrapper(QueryWrapper queryWrapper) {
|
||||
@ -72,7 +102,12 @@ class ToManyRelation<SelfEntity> extends AbstractRelation<SelfEntity> {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
targetMappingValues.add((String) selfValue);
|
||||
if (StringUtil.isNotBlank(splitBy)) {
|
||||
String[] splitValues = ((String) selfValue).split(splitBy);
|
||||
targetMappingValues.addAll(Arrays.asList(splitValues));
|
||||
} else {
|
||||
targetMappingValues.add((String) selfValue);
|
||||
}
|
||||
}
|
||||
|
||||
if (targetMappingValues.isEmpty()) {
|
||||
|
||||
@ -0,0 +1,45 @@
|
||||
package com.mybatisflex.test.model;
|
||||
|
||||
import com.mybatisflex.annotation.Id;
|
||||
import com.mybatisflex.annotation.KeyType;
|
||||
import com.mybatisflex.annotation.Table;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 疾病
|
||||
*
|
||||
* @author Ice 2023/09/26
|
||||
* @version 1.0
|
||||
*/
|
||||
@Table(value = "tb_disease")
|
||||
public class Disease implements Serializable {
|
||||
private static final long serialVersionUID = -3195530228167432902L;
|
||||
|
||||
/**
|
||||
* ID
|
||||
*/
|
||||
@Id(keyType = KeyType.Generator, value = "uuid")
|
||||
private String diseaseId;
|
||||
|
||||
/**
|
||||
* 疾病名称
|
||||
*/
|
||||
private String name;
|
||||
|
||||
public String getDiseaseId() {
|
||||
return diseaseId;
|
||||
}
|
||||
|
||||
public void setDiseaseId(String diseaseId) {
|
||||
this.diseaseId = diseaseId;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,72 @@
|
||||
package com.mybatisflex.test.model;
|
||||
|
||||
import com.mybatisflex.annotation.Id;
|
||||
import com.mybatisflex.annotation.Table;
|
||||
import com.mybatisflex.core.activerecord.Model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 患者信息
|
||||
*
|
||||
* @author Ice 2023/09/26
|
||||
* @version 1.0
|
||||
*/
|
||||
@Table(value = "tb_patient")
|
||||
public class Patient extends Model<Patient> implements Serializable {
|
||||
private static final long serialVersionUID = 5117723684832788508L;
|
||||
|
||||
|
||||
/**
|
||||
* ID
|
||||
*/
|
||||
@Id
|
||||
private Integer patientId;
|
||||
|
||||
/**
|
||||
* 姓名
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 所患病症(对应字符串类型) 英文逗号 分割
|
||||
*/
|
||||
private String diseaseIds;
|
||||
|
||||
/**
|
||||
* 患者标签(对应数字类型) / 分割
|
||||
*/
|
||||
private String tagIds;
|
||||
|
||||
public Integer getPatientId() {
|
||||
return patientId;
|
||||
}
|
||||
|
||||
public void setPatientId(Integer patientId) {
|
||||
this.patientId = patientId;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getDiseaseIds() {
|
||||
return diseaseIds;
|
||||
}
|
||||
|
||||
public void setDiseaseIds(String diseaseIds) {
|
||||
this.diseaseIds = diseaseIds;
|
||||
}
|
||||
|
||||
public String getTagIds() {
|
||||
return tagIds;
|
||||
}
|
||||
|
||||
public void setTagIds(String tagIds) {
|
||||
this.tagIds = tagIds;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,121 @@
|
||||
package com.mybatisflex.test.model;
|
||||
|
||||
import com.mybatisflex.annotation.Id;
|
||||
import com.mybatisflex.annotation.RelationOneToMany;
|
||||
import com.mybatisflex.annotation.Table;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 患者VO
|
||||
*
|
||||
* @author Ice 2023/09/26
|
||||
* @version 1.0
|
||||
*/
|
||||
@Table(value = "tb_patient")
|
||||
public class PatientVO1 implements Serializable {
|
||||
private static final long serialVersionUID = -2298625009592638988L;
|
||||
|
||||
/**
|
||||
* ID
|
||||
*/
|
||||
@Id
|
||||
private Integer patientId;
|
||||
|
||||
/**
|
||||
* 姓名
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 所患病症(对应字符串类型) 英文逗号 分割
|
||||
*/
|
||||
private String diseaseIds;
|
||||
|
||||
/**
|
||||
* 患者标签(对应数字类型) / 分割
|
||||
*/
|
||||
private String tagIds;
|
||||
|
||||
@RelationOneToMany(
|
||||
selfField = "diseaseIds",
|
||||
splitBy = ",", //使用 , 进行分割
|
||||
targetTable = "tb_disease", //只获取某个字段值需要填入目标表名
|
||||
targetField = "diseaseId", //测试目标字段是字符串类型是否正常转换
|
||||
valueField = "name" //测试只获取某个字段值是否正常
|
||||
)
|
||||
private List<String> diseaseNameList;
|
||||
|
||||
@RelationOneToMany(
|
||||
selfField = "tagIds",
|
||||
splitBy = "/", //使用 / 进行分割
|
||||
targetField = "tagId" //测试目标字段是数字类型是否正常转换
|
||||
)
|
||||
private List<Tag> tagList;
|
||||
|
||||
@RelationOneToMany(
|
||||
selfField = "diseaseIds",
|
||||
splitBy = ",", //使用 , 进行分割
|
||||
targetField = "diseaseId", //测试目标字段是字符串类型是否正常转换
|
||||
mapKeyField = "diseaseId" //测试Map映射
|
||||
)
|
||||
private Map<String, Disease> diseaseMap;
|
||||
|
||||
public Integer getPatientId() {
|
||||
return patientId;
|
||||
}
|
||||
|
||||
public void setPatientId(Integer patientId) {
|
||||
this.patientId = patientId;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getDiseaseIds() {
|
||||
return diseaseIds;
|
||||
}
|
||||
|
||||
public void setDiseaseIds(String diseaseIds) {
|
||||
this.diseaseIds = diseaseIds;
|
||||
}
|
||||
|
||||
public String getTagIds() {
|
||||
return tagIds;
|
||||
}
|
||||
|
||||
public void setTagIds(String tagIds) {
|
||||
this.tagIds = tagIds;
|
||||
}
|
||||
|
||||
public List<String> getDiseaseNameList() {
|
||||
return diseaseNameList;
|
||||
}
|
||||
|
||||
public void setDiseaseNameList(List<String> diseaseNameList) {
|
||||
this.diseaseNameList = diseaseNameList;
|
||||
}
|
||||
|
||||
public List<Tag> getTagList() {
|
||||
return tagList;
|
||||
}
|
||||
|
||||
public void setTagList(List<Tag> tagList) {
|
||||
this.tagList = tagList;
|
||||
}
|
||||
|
||||
public Map<String, Disease> getDiseaseMap() {
|
||||
return diseaseMap;
|
||||
}
|
||||
|
||||
public void setDiseaseMap(Map<String, Disease> diseaseMap) {
|
||||
this.diseaseMap = diseaseMap;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
package com.mybatisflex.test.model;
|
||||
|
||||
import com.mybatisflex.annotation.Id;
|
||||
import com.mybatisflex.annotation.Table;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 标签
|
||||
*
|
||||
* @author Ice 2023/09/26
|
||||
* @version 1.0
|
||||
*/
|
||||
@Table(value = "tb_tag")
|
||||
public class Tag implements Serializable {
|
||||
private static final long serialVersionUID = 5600670055904157386L;
|
||||
|
||||
/**
|
||||
* ID
|
||||
*/
|
||||
@Id
|
||||
private Integer tagId;
|
||||
|
||||
/**
|
||||
* 标签名称
|
||||
*/
|
||||
private String name;
|
||||
|
||||
public Integer getTagId() {
|
||||
return tagId;
|
||||
}
|
||||
|
||||
public void setTagId(Integer tagId) {
|
||||
this.tagId = tagId;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,59 @@
|
||||
SET NAMES utf8mb4;
|
||||
SET FOREIGN_KEY_CHECKS = 0;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for tb_disease
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `tb_disease`;
|
||||
CREATE TABLE `tb_disease` (
|
||||
`disease_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT 'ID',
|
||||
`name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '疾病名称',
|
||||
PRIMARY KEY (`disease_id`) USING BTREE
|
||||
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '疾病信息' ROW_FORMAT = Dynamic;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of tb_disease
|
||||
-- ----------------------------
|
||||
INSERT INTO `tb_disease` VALUES ('1', '心脑血管疾病');
|
||||
INSERT INTO `tb_disease` VALUES ('2', '消化系统疾病');
|
||||
INSERT INTO `tb_disease` VALUES ('3', '神经系统疾病');
|
||||
INSERT INTO `tb_disease` VALUES ('4', '免疫系统疾病');
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for tb_patient
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `tb_patient`;
|
||||
CREATE TABLE `tb_patient` (
|
||||
`patient_id` int NOT NULL AUTO_INCREMENT COMMENT 'ID',
|
||||
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '姓名',
|
||||
`disease_ids` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '所患病症(对应字符串类型) 英文逗号 分割',
|
||||
`tag_ids` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '患者标签(对应数字类型) / 分割',
|
||||
PRIMARY KEY (`patient_id`) USING BTREE
|
||||
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '患者信息' ROW_FORMAT = Dynamic;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of tb_patient
|
||||
-- ----------------------------
|
||||
INSERT INTO `tb_patient` VALUES (1, '张三', '1', NULL);
|
||||
INSERT INTO `tb_patient` VALUES (2, '李四', '1,2', '1');
|
||||
INSERT INTO `tb_patient` VALUES (3, '王五', '1,2,3', '1/2');
|
||||
INSERT INTO `tb_patient` VALUES (4, '赵六', '1,2,3,4', '1/2/3');
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for tb_tag
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `tb_tag`;
|
||||
CREATE TABLE `tb_tag` (
|
||||
`tag_id` int NOT NULL AUTO_INCREMENT COMMENT 'ID',
|
||||
`name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '标签名',
|
||||
PRIMARY KEY (`tag_id`) USING BTREE
|
||||
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '标签' ROW_FORMAT = Dynamic;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of tb_tag
|
||||
-- ----------------------------
|
||||
INSERT INTO `tb_tag` VALUES (1, 'VIP');
|
||||
INSERT INTO `tb_tag` VALUES (2, 'JAVA开发');
|
||||
INSERT INTO `tb_tag` VALUES (3, 'Web开发');
|
||||
|
||||
SET FOREIGN_KEY_CHECKS = 1;
|
||||
@ -0,0 +1,30 @@
|
||||
package com.mybatisflex.test.mapper;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import com.mybatisflex.test.model.PatientVO1;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 患者相关测试
|
||||
*
|
||||
* @author Ice 2023/09/26
|
||||
* @version 1.0
|
||||
*/
|
||||
@SpringBootTest
|
||||
@SuppressWarnings("all")
|
||||
public class PatientMapperTest {
|
||||
|
||||
@Autowired
|
||||
private PatientMapper patientMapper;
|
||||
|
||||
@Test
|
||||
public void testRelationOneToManySplitBy() {
|
||||
PatientVO1 patientVO1 = patientMapper.selectOneWithRelationsByQueryAs(QueryWrapper.create().orderBy(PatientVO1::getPatientId, false).limit(1), PatientVO1.class);
|
||||
System.out.println(JSON.toJSONString(patientVO1));
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user