提交 1a053fe3 编写于 作者: templmaster's avatar templmaster

更新 README.md

上级 36254360
流水线 #117 已取消 ,包含阶段
......@@ -26,22 +26,15 @@ iBizSys 是以 `Model Driven Development(MDD)`作为核心理论依据的开发
## 快速开始
## MyBatis-Plus实现CURD
## GitLab-CI/CD实现
我们将通过搭建一个简单的Demo来阐述 iBizSys 整合 mybatis-plus 的过程,在此之前,我们假设您已经:
我们将通过搭建一个简单的Demo来阐述 iBizSys 实现 GitLab-CI/CD 的过程,在此之前,我们假设您已经:
- **熟悉iBizSys实体建立**
- **熟悉MyBatis-Plus**
- **熟悉GitLab-CI/CD**
- **熟悉FreeMaker**
## 建立实体
iBizSys将通过管理数据模型的方式来实现对业务表的管理 [查看更多实体建立小知识](http://bbs.ibizlab.cn/)
![produce](img/quickstart/createEntity.png)
## 建立模板
......@@ -267,394 +260,4 @@ DBET(dbetname=这是第五条实体数据, createdate=null, createman=null, dbet
通过以上几个简单的步骤,您已经成功搭建一个(SpringBoot+MyBatis-Plus)的项目,实现了对数据表的CURD功能。并且您也成功了搭建了一套属于您个人的技术模板,您可以在以后的任何项目当中,使用您搭建的这套技术模板。
iBizSys可以帮助您快速搭建并使用您所搭建的技术模板来生产您的项目,想要了解更多iBizSys模板生产体系?那就继续往下看吧!
## MyBatis-Plus实现关系映射
通过第一章的学习,您已经成功搭建了一个基于(SpringBoot+MyBatis-Plus)的项目,实现了对数据表的CURD功能。但我们日常项目经常使用到关系型数据库,经常会遇到(1:N、N:N)关系场景,本章就向大家介绍iBizSys实体关系。
### 建立实体1:N关系
建立`ONEET``MANYET`实体,实体关系为: `ONEET 1:N MANYET`
实体关系如下图所示:[了解更多实体关系建立小知识](http://bbs.ibizlab.cn/)
![produce](img/relations/der1-n.png)
### 模板支持1:N关系
#### Mapper文件模板
增加Mapper.xml.ftl,用于映射该实体`主从关系`的查询结果集`resultMap`,相关模板代码如下:
```java
<#ibiztemplate>
TARGET=PSDATAENTITY
</#ibiztemplate>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="${pub.getPKGCodeName()}.${item.getPSSystemModule().codeName?lower_case}.mapper.${item.codeName}Mapper">
<#comment>暴露明细数据查询mapper给主关系调用</#comment>
<#if item.getMinorPSDERs?? && item.getMinorPSDERs()??>
<#list item.getMinorPSDERs() as MinorPSDER>
<#assign MajorEntity = MinorPSDER.getMajorPSDataEntity()>
<#assign MajorkeyField = MajorEntity.getKeyPSDEField()>
<#assign MajorField = MinorPSDER.getPSPickupDEField()>
<#list item.getAllPSDEDataQueries() as singleQuery>
<#list singleQuery.getAllPSDEDataQueryCodes() as dedqcode>
<select id="selectBy${MajorField.getName()?lower_case}" resultMap="${de.codeName}ResultMap">
<![CDATA[ select m1.* from( select t1.* from (
${srfjavasqlcode('${dedqcode.getQueryCode()}')}
)t1 ) m1 where ${MajorField.getName()?lower_case}=<#noparse>#{</#noparse>${MajorkeyField.codeName?lower_case}<#noparse>}</#noparse>
]]>
</select>
</#list>
<#break>
</#list>
</#list>
</#if>
<#comment>mybatis返回结果映射</#comment>
<resultMap id="${de.codeName}ResultMap" type="${pub.getPKGCodeName()}.${item.getPSSystemModule().codeName?lower_case}.domain.${item.codeName}" autoMapping="true">
<id property="${item.getKeyPSDEField().codeName?lower_case}" column="${item.getKeyPSDEField().getName()?lower_case}" /><!--主键字段映射-->
<#if item.getMinorPSDERs?? && item.getMinorPSDERs()??>
<#list item.getMinorPSDERs() as MinorPSDER>
<#assign MajorField = MinorPSDER.getPSPickupDEField()>
<result property="${MajorField.codeName?lower_case}" column="${MajorField.getName()?lower_case}" /><!--关系字段映射-->
</#list>
</#if>
<#comment>1N关系中,在子实体中创建父实体的实例对象</#comment>
<#if item.getMinorPSDERs?? && item.getMinorPSDERs()??>
<#list item.getMinorPSDERs() as MinorPSDER>
<#assign MajorEntity = MinorPSDER.getMajorPSDataEntity()>
<association property="${MinorPSDER.getCodeName()?lower_case}" javaType="${pub.getPKGCodeName()}.${MajorEntity.getPSSystemModule().codeName?lower_case}.domain.${MajorEntity.codeName}" column="${MajorField.getName()?lower_case}" select="${pub.getPKGCodeName()}.${MajorEntity.getPSSystemModule().codeName?lower_case}.mapper.${MajorEntity.codeName}Mapper.selectById" fetchType="lazy"></association>
</#list>
</#if>
<#comment>1N关系中,在父实体中创建子实体的List集合</#comment>
<#if item.getMajorPSDERs?? && item.getMajorPSDERs()??>
<#list item.getMajorPSDERs() as MajorPSDER>
<#assign MinorEntity = MajorPSDER.getMinorPSDataEntity()>
<#assign MajorDerField = MajorPSDER.getPSPickupDEField()>
<collection property="${MajorPSDER.getMinorCodeName()?lower_case}" ofType="${pub.getPKGCodeName()}.${MinorEntity.getPSSystemModule().codeName?lower_case}.domain.${MinorEntity.codeName}" column="${item.getKeyPSDEField().getName()?lower_case}" select="${pub.getPKGCodeName()}.${MinorEntity.getPSSystemModule().codeName?lower_case}.mapper.${MinorEntity.codeName}Mapper.selectBy${MajorDerField.getName()?lower_case}" fetchType="lazy"></collection>
</#list>
</#if>
</resultMap>
</mapper>
```
#### 实体类模板
在实体类中关联 `resultMap`,并发布出该实体主从关系对象,相关模板代码如下:
```java
@TableName(value = "${item.getTableName()}",resultMap = "${item.codeName}ResultMap")
@Data
public class ${item.codeName}{
<#comment>输出当前实体1:N主实体</#comment>
<#if item.getMinorPSDERs?? && item.getMinorPSDERs()??>
<#list item.getMinorPSDERs() as MinorPSDER>
<#assign MajorEntity = MinorPSDER.getMajorPSDataEntity()>
@TableField(exist = false)//关系主表数据
private ${MajorEntity.getCodeName()} ${MinorPSDER.getCodeName()?lower_case};
</#list>
</#if>
<#comment>输出当前实体1:N子实体</#comment>
<#if item.getMajorPSDERs?? && item.getMajorPSDERs()??>
<#list item.getMajorPSDERs() as MajorPSDER>
<#assign MinorEntity = MajorPSDER.getMinorPSDataEntity()>
@TableField(exist = false)//关系子表数据
private List <${MinorEntity.getCodeName()}> ${MajorPSDER.getMinorCodeName()?lower_case};
</#list>
</#if>
}
```
## 开始使用
添加主实体`ONEET`、关系实体`MANYET`实体建表的schema脚本
```sql
create table IF NOT EXISTS T_ONEET
(
oneetid VARCHAR2(100) not null,
oneetname VARCHAR2(200),
createman VARCHAR2(60),
updateman VARCHAR2(60),
createdate DATE,
updatedate DATE
);
create table IF NOT EXISTS T_MANYET
(
manyetid VARCHAR2(100) not null,
manyetname VARCHAR2(200),
oneetid VARCHAR2(200),
createman VARCHAR2(60),
updateman VARCHAR2(60),
createdate DATE,
updatedate DATE
);
```
添加主实体`ONEET`、关系实体`MANYET`实体测试数据的schema脚本
```sql
INSERT INTO T_ONEET (oneetid, oneetname) VALUES
(1, '主实体1'),
(2, '主实体2');
INSERT INTO T_MANYET (manyetid, manyetname,oneetid) VALUES
(1, '关系实体数据1',1),
(2, '关系实体数据2',1),
(3, '关系实体数据3',2);
```
添加测试类进行功能测试,测试类代码如下:
```java
@RunWith(SpringRunner.class)
@SpringBootTest(classes = demoMain.class)
public class RelationsTest {
@Autowired
private ONEETMapper oneetMapper;
@Test
public void testMain() {
System.out.println(("----- selectAll method test ------"));
List<ONEET> oneets = oneetMapper.selectList(null);
for(ONEET oneet: oneets){
System.out.println(String.format("[%s]关联的关系实体数量为[%s]",oneet.getOneetname(),oneet.getManyetobjs().size()));
}
}
}
```
控制台输出:
从测试结果可以看出,在查询主数据时,可以获取到子数据`Manyetobjs`对象,从而实现关联查询。
```
----- selectAll method test ------
[主实体1]关联的关系实体数量为[2]
[主实体2]关联的关系实体数量为[1]
```
## MyBatis-Plus实现动态查询
通过前两章节的学习,相信你已经初步了解iBizSys的模型发布体系,在第三章,将会向大家介绍iBizSys如何通过MyBatis-Plus实现动态查询。
在项目里可能会经常遇到查询同一个数据表,在不同的地方,需要根据不同的条件进行过滤。此时,查询条件是不固定的,需要动态拼接查询条件进行查询。
技术实现:
可以使用iBizSys为每个实体模型建立搜索项
可以使用MyBatis-Plus提供[条件构造器](https://mp.baomidou.com/guide/wrapper.html),根据实体搜索项生成条件构造器,在查询时使用条件构造器,MyBatis-Plus将会解析构造器中的条件来动态拼接where条件,从而实现动态查询。
## 配置实体搜索项
建立实体搜索项,支持通过SEX作为条件进行查询[查看更多实体搜索项配置小技巧](http://bbs.ibizlab.cn/)
![produce](img/dycond/search_cond.png)
## 模板支持实体搜索项
### 实体搜索项模板
模板中为每个实体发布实体搜索项 `searchfilter`,搜索条件包含:`模糊匹配``等于``大于等于``小于等于`···,模板代码如下:
```java
@Data
public class ${item.getCodeName()}SearchFilter{
private QueryWrapper<${item.getCodeName()}> selectCond;
public ${item.getCodeName()}SearchFilter(){
this.selectCond=new QueryWrapper<${item.getCodeName()}>();
}
/**
* 输出实体搜索项
*/
<#list item.getPSDEFields() as defield>
<#list defield.getAllPSDEFSearchModes() as formitem>
private ${srfjavatype(formitem.getPSDEField().stdDataType)} ${formitem.getName()?lower_case};//[${defield.getLogicName()}]
public void set${formitem.getName()?lower_case?cap_first}(${srfjavatype(formitem.getPSDEField().stdDataType)} ${formitem.getName()?lower_case}) {
this.${formitem.getName()?lower_case} = ${formitem.getName()?lower_case};
if(!StringUtils.isEmpty(this.${formitem.getName()?lower_case})){
<#if formitem.getValueOp() == "LIKE">
this.selectCond.like("${formitem.getPSDEField().getName()?lower_case}", ${formitem.getName()?lower_case});
<#elseif formitem.getValueOp() == "LEFTLIKE">
this.selectCond.likeLeft("${formitem.getPSDEField().getName()?lower_case}", ${formitem.getName()?lower_case});
<#elseif formitem.getValueOp() == "RIGHTLIKE">
this.selectCond.likeRight("${formitem.getPSDEField().getName()?lower_case}", ${formitem.getName()?lower_case});
<#elseif formitem.getValueOp() == "EQ">
this.selectCond.eq("${formitem.getPSDEField().getName()?lower_case}", ${formitem.getName()?lower_case});
<#elseif formitem.getValueOp() == "NOTEQ">
this.selectCond.ne("${formitem.getPSDEField().getName()?lower_case}", ${formitem.getName()?lower_case});
<#elseif formitem.getValueOp() == "GT">
this.selectCond.gt("${formitem.getPSDEField().getName()?lower_case}", ${formitem.getName()?lower_case});
<#elseif formitem.getValueOp() == "GTANDEQ">
this.selectCond.ge("${formitem.getPSDEField().getName()?lower_case}", ${formitem.getName()?lower_case});
<#elseif formitem.getValueOp() == "LT">
this.selectCond.lt("${formitem.getPSDEField().getName()?lower_case}", ${formitem.getName()?lower_case});
<#elseif formitem.getValueOp() == "LTANDEQ">
this.selectCond.le("${formitem.getPSDEField().getName()?lower_case}", ${formitem.getName()?lower_case});
</#if>
}
}
</#list>
</#list>
}
```
### 实体服务对象模板
实体服务类对象中,发布`实体数据集`相关模板代码,数据集接收`searchfilter`作为过滤参数,并将`searchfilter`作为参数传递 `mapper` 实现动态查询
```java
@Service
public class ${item.codeName}ServiceImpl extends ServiceImpl<${item.codeName}Mapper, ${item.codeName}> implements ${item.codeName}Service{
@Resource
private ${item.codeName}Mapper ${item.codeName?lower_case}Mapper;
<#if item.getAllPSDEDataSets()??>
<#list item.getAllPSDEDataSets() as dedataset>
public List<${item.codeName}> list${dedataset.getCodeName()}(${item.codeName}SearchFilter filter) {
return ${item.codeName?lower_case}Mapper.search${dedataset.getCodeName()}(filter,filter.getSelectCond());
}
</#list>
</#if>
}
```
### Mapper类模板
Mapper类提供接口供service调用,调用mapper.xml
```java
public interface ${item.getCodeName()}Mapper extends BaseMapper<${item.getCodeName()}>{
<#if item.getAllPSDEDataSets()??>
<#list item.getAllPSDEDataSets() as dedataset>
List<${item.getCodeName()}> search${dedataset.getCodeName()}(@Param("srf") ${item.getCodeName()}SearchFilter searchfilter,@Param("ew") Wrapper<${item.getCodeName()}> wrapper) ;
</#list>
</#if>
}
```
### Mapper文件模板
根据 `Mapper类` 中传递过来的搜索条件,动态拼接查询条件
```java
<#comment>实体数据查询</#comment>
<select id="search${singleQuery.getCodeName()}" resultMap="${de.codeName}ResultMap">
<![CDATA[select t1.* from (
${srfjavasqlcode('${dedqcode.getQueryCode()}')}
)t1]]>
<where><if test="ew!=null and ew.sqlSegment!=null and !ew.emptyOfWhere"><#noparse>${ew.sqlSegment}</#noparse></if></where>
<if test="ew!=null and ew.sqlSegment!=null and ew.emptyOfWhere"><#noparse>${ew.sqlSegment}</#noparse></if>
</select>
```
## 开始使用
添加`DBET`实体建表的schema脚本:
```sql
create table IF NOT EXISTS T_DBET
(
dbetid VARCHAR2(100) not null,
dbetname VARCHAR2(200),
sex VARCHAR2(200),
createman VARCHAR2(60),
updateman VARCHAR2(60),
createdate DATE,
updatedate DATE
);
```
添加`DBET`实体测试数据的schema脚本
```sql
INSERT INTO T_DBET (dbetid, dbetname,sex) VALUES
(1, '这是第一条实体数据','男'),
(2, '这是第二条实体数据','男'),
(3, '这是第三条实体数据','男'),
(4, '这是第四条实体数据','女'),
(5, '这是第五条实体数据','女');
```
添加测试类,测试类相关代码如下:
```java
@RunWith(SpringRunner.class)
@SpringBootTest(classes = demoMain.class)
public class DyCondTest {
@Autowired
private DBETService dbetService;
@Test
public void testMain() {
System.out.println(("----- selectAll method test ------"));
DBETSearchFilter dbetSearchFilter=new DBETSearchFilter();
dbetSearchFilter.setN_sex_eq("男");
List<DBET> dbets = dbetService.listDefault(dbetSearchFilter);
dbets.forEach(System.out::println);
}
}
```
控制台输出:
可以看出已经能够根据实体搜索项【searchfilter】中设定的条件,过滤出 SEX=“男” 的数据
```
----- selectAll method test ------
DBET(dbetname=这是第一条实体数据, createdate=null, createman=null, dbetid=1, updateman=null, updatedate=null, sex=男)
DBET(dbetname=这是第二条实体数据, createdate=null, createman=null, dbetid=2, updateman=null, updatedate=null, sex=男)
DBET(dbetname=这是第三条实体数据, createdate=null, createman=null, dbetid=3, updateman=null, updatedate=null, sex=男)
```
\ No newline at end of file
iBizSys可以帮助您快速搭建并使用您所搭建的技术模板来生产您的项目。
\ No newline at end of file
Markdown 格式
0% or
您添加了 0 到此讨论。请谨慎行事。
先完成此消息的编辑!
想要评论请 注册