yang-sql-boot-configure

和SpringBoot配置

License

License

Categories

Categories

config Application Layer Libs Configuration
GroupId

GroupId

top.sanguohf.egg
ArtifactId

ArtifactId

yang-sql-boot-configure
Last Version

Last Version

1.0.31-release
Release Date

Release Date

Type

Type

jar
Description

Description

yang-sql-boot-configure
和SpringBoot配置
Source Code Management

Source Code Management

https://github.com/yangrui110/yang-sql

Download yang-sql-boot-configure

How to add to project

<!-- https://jarcasting.com/artifacts/top.sanguohf.egg/yang-sql-boot-configure/ -->
<dependency>
    <groupId>top.sanguohf.egg</groupId>
    <artifactId>yang-sql-boot-configure</artifactId>
    <version>1.0.31-release</version>
</dependency>
// https://jarcasting.com/artifacts/top.sanguohf.egg/yang-sql-boot-configure/
implementation 'top.sanguohf.egg:yang-sql-boot-configure:1.0.31-release'
// https://jarcasting.com/artifacts/top.sanguohf.egg/yang-sql-boot-configure/
implementation ("top.sanguohf.egg:yang-sql-boot-configure:1.0.31-release")
'top.sanguohf.egg:yang-sql-boot-configure:jar:1.0.31-release'
<dependency org="top.sanguohf.egg" name="yang-sql-boot-configure" rev="1.0.31-release">
  <artifact name="yang-sql-boot-configure" type="jar" />
</dependency>
@Grapes(
@Grab(group='top.sanguohf.egg', module='yang-sql-boot-configure', version='1.0.31-release')
)
libraryDependencies += "top.sanguohf.egg" % "yang-sql-boot-configure" % "1.0.31-release"
[top.sanguohf.egg/yang-sql-boot-configure "1.0.31-release"]

Dependencies

compile (4)

Group / Artifact Type Version
org.projectlombok : lombok Optional jar 1.18.10
top.sanguohf.egg : yang-sql-parse jar 1.0.30-release
org.springframework.boot : spring-boot-starter-web jar 2.2.4.RELEASE
org.springframework.boot : spring-boot-starter-jdbc jar 2.2.4.RELEASE

Project Modules

There are no modules declared in this project.

前言

这个插件是个人开发的,目前已经在我就职的公司中开始使用,mybatis已经被逐步移除。这个插件的思想是借助于我上一家就职的公司,有很多值得参考和借鉴之处。

我写这个插件的理由:

1、一直以来都被增删改查所累,哪怕是有了mybatis以及mybatis plus,也还是需要做一些无用的配置,包括查询条件的书写、排序字段,后期如果需要更改一个小字段,也需要牵动整个后台,十分的重复机械。

2、针对mybatis和mybatis plus,其中难免需要书写一些简单的sql关联语句。极大的浪费时间,消磨人的精力

3、我喜欢一个插件具有简约的配置以及良好的使用方式,易于理解,容易上手。

欢迎加入QQ群:623337780,获取帮助和提出宝贵建议

1、安装

引入maven包:

<dependency>
    <groupId>top.sanguohf.egg</groupId>
    <artifactId>yang-sql-starter</artifactId>
    <version>1.0.20-release</version>
</dependency>

2、初次使用

1、在SpringBoot项目中引入Maven包后,你就可以进行测试了。在SpringBoot的主运行类上加上@ScanEntity注解,如下配置:

@EnableTransactionManagement
@ScanEntity({"top.sanguohf.egg.test.entity"})
@SpringBootApplication
public class YangSqlTest {
    public static void main(String[] args) {
        SpringApplication.run(YangSqlTest.class);
    }
}

2、创建实体类和数据库表,字段一一对应,采用驼峰命名规则。如下所示

@Data
@TableName("user")
public class User {
    @Id
    @Field("user_name")
    private String userName;
    private String password;
    protected String id;
    private BigDecimal price;
}

1582302341327

3、配置数据源,连接远程数据库,如下配置

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      url: jdbc:mysql://xxx:3306/springsys?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC&zeroDateTimeBehavior=convertToNull&&allowPublicKeyRetrieval=true
      username: 账号
      password: 密码

4、编写Test测试文件,代码如下

@RunWith(SpringRunner.class)
@SpringBootTest
public class TestOne {

    @Autowired
    private CommonService commonService;
    @Test
    public void test3() throws NoSuchFieldException, IOException, ClassNotFoundException 		{
        EntityParams params = new EntityParams();
        params.setTableClassName("User");
        List list = commonService.findList(params);
    }
}

3、服务说明

3.1前端传参

可以查看top.sanguohf.egg.param.EntityParams类所对应的属性。源码如下

@Data
public class EntityParams {
    private String tableClassName;

    private JSONObject condition;
    private List<EntityOrderBy> orderBy;

    public List<EntityOrderBy> getOrderBy() {
        if(orderBy==null)
            orderBy=new LinkedList<>();
        return orderBy;
    }
}

属性详解

tableClassName这个属性标识当前操作的实体类名,比如User类,对应的值就是User,和类名一致

condition这个属性用来确定查询的条件,或者是更新的数据,又或者是插入的数据,又或者是删除的数据,它的格式较为复杂,我会单独开一小节进行讲解。

orderBy定义排序字段,前端传递的格式是形如下

[
  {"column": "userName","direct": "desc"},
  {"column": "password","direct": "asc"}
]

3.2通用增删改查类

可以查看top.sanguohf.top.bootcon.service.impl.CommonServiceImpl实现类。方法的使用方式和mybatis的操作基本相同,都是以实体为基础。下面对方法说明

findByEntityPageList根据传入的条件,分页查询数据

findEntityList根据传入条件,查询所有数据

countEntity统计符合查询条件的数目

insertEntity向数据库中插入单个数据

updateEntity更新单个数据

deleteEntity删除单条数据

batchEntityInsert批量插入数据

batchEntityUpdate批量更新数据

batchEntityDelete批量删除数据

findByPrimaryKey根据主键查找记录(适用于表的主键是单个的情况)

findByPrimaryKeys根据主键的集合,查找记录值

batchSaveEntity批量插入或者是更新值

3.3condition的格式定义

3.3.1插入、更新、删除数据格式

这三种方式传递的数据格式都是一样的,如下示例:

{
  "userName": "张三",
  "password": "王五",
  "id": "10001"
}

简单的JSON对象,列名是key,值是value

3.3.2 查询数据格式

1、基础的查询格式有两种

第一种

{
  "left":"userName",
   "relation":"=",
   "right": "admin"
}

第二种

{
   "condition": [
        {"left": "userName","relation": "like","right": "%admin%"},
        {"left": "password","relation": "=","right": "6547199"}
   ],
   "combine": "and"
}

2、演变出稍微复杂的格式

{
   "left": {
       "condition": [
           {"left": "userName","relation": "=","right": "admin"},
           {"left": "password","relation": "=","right": "123456"}
       ],"combine": "and"
   },
   "relation": "and",
   "right": {
       "condition": [
           {"left": "userName","relation": "like","right": "%admin%"},
           {"left": "password","relation": "=","right": "6547199"}
       ],"combine": "and"
  }
}

3、演变出更为复杂的格式,实现两种基础模式的多层嵌套

{
   "left": {
       "condition": [
           {"left": "userName","relation": "=","right": "admin"},
           {"left": "password","relation": "=","right": "123456"}
       ],"combine": "and"
   },
   "relation": "and",
   "right": {
       "condition": [{
           "left": {
               "condition": [
                   {"left": "userName","relation": "=","right": "admin"},
                   {"left": "password","relation": "=","right": "123456"}
               ],"combine": "and"},
            "relation": "and",
            "right": {"left": "password","relation": "=","right": "6547199"}
           },
           {"left": "password","relation": "=","right": "6547199"}
       ],"combine": "and"
  }
}

3.3.3 条件构造器

查看类top.sanguohf.egg.util.EntityConditionBuilder,使用样式可以参考以下的使用案例

public ResponseResult findPageList(@RequestBody BatisPage<XfSalestype> xfSalestype) throws Exception {
        XfSalestype xf = xfSalestype.getCondition() == null ? new XfSalestype() : xfSalestype.getCondition();
        EntityConditionBuilder builder = EntityConditionBuilder.getInstance().eq("dr", DelState.NORMAL);
        if (!StringUtils.isEmpty(xf.getScode())) {
            builder.like("scode", xf.getScode());
        }
        if (!StringUtils.isEmpty(xf.getStypename())) {
            builder.like("stypename", xf.getStypename());
        }
        if (!StringUtils.isEmpty(xf.getCompname())) {
            builder.like("compname", xf.getCompname());
        }
    	JSONObject jsonObject = builder.combineAnd();//最终的查询条件
        CommonPageResp<List<XfSalestype>> entityPageList = commonService.findEntityPageList(XfSalestype.class, XfSalestype.class, jsonObject, new Page(xfSalestype.getPageNo(), xfSalestype.getPageSize()));
        return new ResponseResult(CommonCode.SUCCESS, entityPageList);
    }

3.4、实体类的定义

3.4.1基础实体的定义

先看一个定义实例吧

@TableName("user")
public class User {
    @Id
    @Field("user_name")
    private String userName;
    private String password;
    protected String id;
    @IgnoreSelectReback
    private BigDecimal price;
}

我们详细说明一下:

首先创建一个实体,这个实体的类名默认是采用驼峰命名规则和数据库表名对应,如User类,默认对应user表

类中的实体也是采用驼峰命名规则,和数据库列一一对应

3.4.1.1 @TableName

作用:定义实体对应的数据库表名称

属性名 类型 作用 默认值
value String[] 对应数据库表的名称 类名的驼峰转换

3.4.1.2 @Id

作用:定义表的主键,更新会使用,默认的主键是名为Id的属性

属性名 类型 作用

3.4.1.3 @Field

作用:定义属性对应的数据库列名称

属性名 类型 作用 默认值
value String 对应的表的列名 类属性的驼峰转换
alias String 查询列时返回的别名 类属性名

3.4.1.4 @IgnoreSelectReback

作用:标识这个字段在做查询的时候不会返回

无属性

3.4.1.5 @Condition

作用:定义默认的查询条件

属性 类型 作用 默认值
value String 定义查询的值
type String 定义值的类型
relation String 列和值的关系 =
String 列的名字

3.4.1.6 @OrderBy

作用: 定义排序字段

属性 类型 作用 默认值
column String 定义列名
direct String 排序方向 desc

3.4.2视图实体的定义

我们也先看两个实例

@ViewTable
public class TeacherView {

    @MainTable(tableAlias = "oneOs")
    private Teacher teacher;

    @ReferTable(tableAlias = "op",relation = "inner join",condition = "oneOs.teacherId = op.id")
    private User user;
}

另一个更复杂的带子查询的例子

@ViewTable
public class UserClassesView {

    @Condition(column = "teacherId",value = "1")
    @MainTable(tableAlias = "userOne")
    private TeacherView teacherView;

    @ReferTable(tableAlias = "aliasClass",relation = "left join",condition = "userOne.id = aliasClass.classesId and userOne.userName = aliasClass.name")
    private Classes classes;

    @OrderBys({
            @OrderBy(column = "teacherId",direct = "desc")
    })
    @Conditions({
            @Condition(column = "teacherId",value = "1"),
            @Condition(column = "teacherName",value = "8")
    })
    @ReferTable(tableAlias = "teacher",relation = "left join",condition = "userOne.id = teacher.teacherId",includeColumns = {"teacherName"})
    private Teacher teacher;

}

现在我对其中的注解进行详解

3.4.2.1 @ViewTable

作用:标识当前的实体是视图实体

3.4.2.2 @MainTable

作用:标识关联的主表

属性名 类型 作用
tableAlias String 主表的别名
includeColumns String[] 需要查出的列(优先于excludeColumns)
excludeColumns String[] 排除掉不需要查出的列(默认是全部都查出)

3.4.2.3 @ReferTable

作用:标识关联查询的表

属性名 类型 作用 默认值
tableAlias String 表别名
relation String 关系 left join
condition String 标识关联的条件(on后面的)
includeColumns String[] 需要查出的列(优先于excludeColumns)
excludeColumns String[] 排除掉不需要查出的列(默认是全部都查出)

3.4.2.4 @Conditions

作用:是@Condition注解的复数形式

属性名 类型 作用
value Condition[] 定义多个条件

3.4.2.5 @OrderBys

作用:是@OrderBy注解的复数形式

属性名 类型 作用
value OrderBy[] 定义多个排序字段

3.5 配置包扫描

@ScanEntity注解,可以配置多个实体包的扫描路径,如下示例

@EnableTransactionManagement
@ScanEntity({"top.sanguohf.egg.test.entity","top.sanguohf.egg.configure.entity"})
@SpringBootApplication
public class YangSqlTest {
    public static void main(String[] args) {
        SpringApplication.run(YangSqlTest.class);
    }
}

3.6 开启事务

事务采用SpringBoot自带的事务控制,如下示例

@EnableTransactionManagement //开启事务
@ScanEntity({"top.sanguohf.egg.test.entity","top.sanguohf.egg.configure.entity"})
@SpringBootApplication
public class YangSqlTest {
    public static void main(String[] args) {
        SpringApplication.run(YangSqlTest.class);
    }
}

开启事务,用于保证批量操作时的原子性

4、完整示例

4.1 基础示例

基础示例只需要三个步骤,无需编写SQL语句,直接实现数据库查询。当然数据库还是需要在yml中配置

4.1.1 实体类

package com.kc.app.xfjl.entity;
/**这是一个具体项目中的实体,不需要知道每个字段多的含义。我为了完整性,将项目中的整个代码都精简出来*/
@Data
@TableName("xf_rMaterial")
public class XfRMaterial {

    @Id //定义此表的主键
    @Field("pk_material")
    private String pk_material;

    @Field("rMeCode")
    private String rMeCode;

    @Field("rMeCodeName")
    private String rMeCodeName;

    @Field("rMeSpecName")
    private String rMeSpecName;

    @Field("mMenicCode")
    private String mMenicCode;

    @Field("cMeMemo")
    private String cMeMemo;

    @Field("cMaker")
    private String cMaker;
    
    //@OrderBy(direct = "desc")
    @Field("dnMaketime")
    private Date dnMaketime;

    @Field("dr")
    private Integer dr;

    @Field("pk_matertype")
    private String pk_matertype;

    @Field("pk_corp")
    private String pk_corp;
}

4.1.2 controller编写

package com.kc.app.xfjl.controller;

@Controller
@RequestMapping("xfRMaterial")
public class XfRMaterialController {
    //直接注入通用的service
    @Autowired
    private CommonService commonService;

    @ApiOperation("分页获取参数")
    @PostMapping("getPageList")
    @ResponseBody
    public ResponseResult findPageList(@RequestBody BatisPage<XfRMaterial> xfRMaterial) throws Exception {
        XfRMaterial xf = xfRMaterial.getCondition()==null?new XfRMaterial():xfRMaterial.getCondition();
        EntityConditionBuilder builder = EntityConditionBuilder.getInstance().eq("dr", 1);
        if(!StringUtils.isEmpty(xf.getPk_material())){
            builder.like("pk_material",xf.getPk_material());
        }
        if(!StringUtils.isEmpty(xf.getRMeCode())){
            builder.like("rMeCode",xf.getRMeCode());
        }
        if(!StringUtils.isEmpty(xf.getRMeCodeName())){
            builder.like("rMeCodeName",xf.getRMeCodeName());
        }
        if(!StringUtils.isEmpty(xf.getRMeSpecName())){
            builder.like("rMeSpecName",xf.getRMeSpecName());
        }
        if(!StringUtils.isEmpty(xf.getMMenicCode())){
            builder.like("mMenicCode",xf.getMMenicCode());
        }
        if(!StringUtils.isEmpty(xf.getTypename())){
            builder.like("typename",xf.getTypename());
        }
        if(!StringUtils.isEmpty(xf.getCMeMemo())){
            builder.like("cMeMemo",xf.getCMeMemo());
        }
        //定义查询的排序字段
        ArrayList sorts = new ArrayList<EntityOrderBy>();
        EntityOrderBy order = new EntityOrderBy();
        order.setDirect("desc");
        order.setColumn("dnMaketime");
        sorts.add(order);

        CommonPageResp<List<XfRMaterial>> entityPageList = commonService.findEntityPageList(XfRMaterialView.class, XfRMaterialVo.class,builder.combineAnd(),sorts, new Page(xfRMaterial.getPageNo(), xfRMaterial.getPageSize()));
        PageResult result = new PageResult(entityPageList.getCount(),entityPageList.data);
        return new ResponseResult(CommonCode.SUCCESS,result);
    }
    @ApiOperation("查询所有记录")
    @PostMapping("getList")
    @ResponseBody
    public ResponseResult findList(@RequestBody XfRMaterial xfRMaterial) throws Exception {
        EntityConditionBuilder builder = EntityConditionBuilder.getInstance().eq("dr", 1);
        List<XfRMaterial> list = commonService.findEntityList(XfRMaterial.class, XfRMaterial.class,builder.combineAnd());
        return new ResponseResult(CommonCode.SUCCESS,list);
    }
    @ApiOperation("插入一条记录")
    @PostMapping("save")
    @ResponseBody
    public ResponseResult save(@RequestBody XfRMaterial xfRMaterial) throws Exception {
        if(StringUtils.isEmpty(xfRMaterial.getPk_material()))
            xfRMaterial.setPk_material(UUIDUtils.createUUID());
        xfRMaterial.setDr(1);
        xfRMaterial.setDnMaketime(new Date());
        xfRMaterial.setDnModifytime(new Date());
        commonService.insertEntity(xfRMaterial);
        return new ResponseResult(CommonCode.SUCCESS,xfRMaterial);
    }
    @ApiOperation("修改一条记录")
    @PostMapping("update")
    @ResponseBody
    public ResponseResult update(@RequestBody XfRMaterial xfRMaterial) throws Exception {
        xfRMaterial.setDnModifytime(new Date());
        commonService.updateEntity(xfRMaterial);
        return new ResponseResult(CommonCode.SUCCESS);
    }
    @ApiOperation("保存或者插入")
    @PostMapping("addOrUpdate")
    @ResponseBody
    public ResponseResult addOrUpdate(@RequestBody XfRMaterial xfRMaterial) throws Exception {
        if(StringUtils.isEmpty(xfRMaterial.getPk_material()))
            save(xfRMaterial);
        else update(xfRMaterial);
        return new ResponseResult(CommonCode.SUCCESS);
    }
    @ApiOperation("批量删除")
    @DeleteMapping("batchDelete")
    @ResponseBody
    public ResponseResult batchDelete(@RequestBody List<XfRMaterial> xfRMaterial) throws Exception {
        commonService.batchEntityDelete(xfRMaterial);
        return new ResponseResult(CommonCode.SUCCESS);
    }
    @ApiOperation("删除单个")
    @DeleteMapping("delete")
    @ResponseBody
    public ResponseResult delete(@RequestBody XfRMaterial xfRMaterial) throws Exception {
        xfRMaterial.setDr(0);
        xfRMaterial.setDnModifytime(new Date());
        commonService.updateEntity(xfRMaterial);
        return new ResponseResult(CommonCode.SUCCESS);
    }
}

4.1.3 启动类

@EnableTransactionManagement
@SpringBootApplication
//配置实体类的扫描路径
@ScanEntity({"com.kc.app.xfjl.entity","com.kc.app.xfjl.vo","com.kc.app.xfjl.view"})
public class XfjlApplication {
    public static void main(String[] args) {
        SpringApplication.run(XfjlApplication.class, args);
    }
}

4.1.4 yml配置

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      url: jdbc:mysql://ip:3306/springsys?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC&zeroDateTimeBehavior=convertToNull&&allowPublicKeyRetrieval=true
      username: root
      password:

4.2 表关联示例

针对表关联的实现,是个很有趣的问题。请看以下的示例。

4.2.1 关联实体定义

package com.kc.app.xfjl.view;
//定义表之间的关系(可以理解为一条join语句,可以复用之前定义的实体)
@ViewTable
public class XfRMaterialView {

    @MainTable(tableAlias = "xfRMaterialVo") //定义视图查询的主表信息(其也可是视图实体)
    private XfRMaterial xfRMaterial;

    @ReferTable(tableAlias = "xfMatertype",relation = "left join",condition = "xfRMaterialVo.pk_matertype = xfMatertype.pkMatertype",includeColumns = {"typename"})
    private XfMatertype xfMatertype; //这里也可以是其它视图
}

4.2.2 使用方法

package com.kc.app.xfjl;

@SpringBootTest
@RunWith(SpringRunner.class)
public class BaseTest {
    @Autowired
    private CommonService commonService;
    
    @Test
    public void test3() throws Exception {
        List<Map> entityList = commonService.findEntityList(XfRMaterialView.class, Map.class);//这里的map是接收的实体类,也可以定义指定的java类型
        System.out.println(entityList);
    }
}

Versions

Version
1.0.31-release
1.0.30-release
1.0.26-release
1.0.25-release
1.0.24-release
1.0.23-release
1.0.22-release
1.0.20-release
1.0.19-release
1.0.18-release
1.0.17-release
1.0.16-release
1.0.15-release
1.0.14-release
1.0.13-release
1.0.12-release
1.0.10-release
1.0.9-release
1.0.8-release
1.0.7-release
1.0.6-release
1.0.5-release
1.0.4-release
1.0.3-release
1.0-release