# SPeed-ORM-ZERO 手写无侵入式 + 零代码优雅 API 持久化框架,后端降本增效功法 **Repository Path**: chengchuang/speed-orm ## Basic Information - **Project Name**: SPeed-ORM-ZERO 手写无侵入式 + 零代码优雅 API 持久化框架,后端降本增效功法 - **Description**: 1.支持 @Association 和 @Collection 关联查询 2.支持基本增删改查,查询装饰器,批量新增,修改,删除,分页等 3.支持树形查询,如查询机构,只需要 Model.tree(Class tClass); 传入类型即可,一键生成 tree 组 合模式; 4.无需使用 @Autowried 引入,以静态工具类方式对外提供丰富 API; - **Primary Language**: Unknown - **License**: EPL-1.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2024-05-17 - **Last Updated**: 2024-05-17 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # SPeed ORM # 自研框架简介 ```ruby 一、手写 ORM 框架,然后在其他项目中集成使用 1.支持 @Association 和 @Collection 关联查询 2.支持基本增删改查,查询装饰器,批量新增,修改,删除,分页等 3.支持树形查询,如查询机构,只需要 Model.tree(Class tClass); 传入类型即可,一键生成 tree 组 合模式; 4.无需使用 @Autowried 引入,以静态工具类方式对外提供丰富 API; 5.支持 Lambda 双冒号获取字段语法提示; 二、存在问题: 1.未实现多级缓存; 2.优化代码风格; 3.未使用 Android 开发实现 @Select (类似 Lombok)注解支持的 idea 插件, 语法提示, 如 SysUser.selectByUsername() 3.待优化... ``` # 快速上手 ## 新建应用项目 ![输入图片说明](sql/img3.png) ## 引入 Maven 依赖 在 pom.xml 中引入如下 maven 坐标 ```ruby io.gitee.tlgen_1 speed-orm 1.0.3 ``` ## 配置数据源 properties,方便复制 ```ruby spring.application.name=auth-server spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 spring.datasource.username=root spring.datasource.password=1234 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver speed.show-log=true ``` yml,方便复制 ```ruby spring: application: name: auth-server datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/test?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC username: root password: 1234 speed: show-log: true ``` ## 集成使用方式 ### 方式一(万能 Model 类) #### 截图效果 ![输入图片说明](sql/img18fad3679952abb49cadf156f20f32e2.png) #### 代码效果 ```ruby @Service public class SysUserServiceImpl implements SysUserService { @Override public List select() { return Model.select(SysUser.class); } } ``` #### 简介说明 ```ruby // Model API 1. Model 类提供了增删改查的基础 API 方法, 简洁零代码静态方法调用。 ``` ### 方式二(便捷实体类) #### 截图效果 ![输入图片说明](sql/img2.png) #### 代码效果 ```ruby @Service public class SysUserServiceImpl implements SysUserService { @Override public List select() { return SysUser.selectByUsername("影月"); } } ``` #### 简介说明 [@Select注解集成方式](https://gitee.com/tlgen_1/springboot-select.git) ```ruby // 需要在实体类上添加 @Select 注解 // SysUser.selectByUsername("影月"); 1. 是由定义的实体类, 比如 SysUser.java, 其中定义了 username 属性; 2. 然后会在编译的时候, 会自动生成对应字段的的静态查询方法; 3. 如 SysUser.selectByUsername(); 4. 为什么会有这些方法呢...? 5. 答案: 基于充血模型思想, 对象应该拥有状态和行为, 可以衍生出这些方法; 6. 编译为什么会生成...? 7. 答案: Java 屠龙之术, JcTree; 8. 依赖于手写的 @Select 注解【https://gitee.com/tlgen_1/springboot-select.git】 插件; 9. 类似 lombok 底层原理 ``` # 零代码风格专区 #### 零代码快速上手 ```ruby 1.直接零代码风格 2.无需写任何 mapper 或 dao 或 service 或 impl 或 controller 3.只需要一个 model 即可完成全部增删改查 4.支持自定义声明业务性质接口, 即非基础增删改查, 入口在接口层 ``` #### 接口文档标准示例 【关键】全部的栗子都在这里, 包含全部的通用增删改查案例 ```ruby https://apifox.com/apidoc/shared-96f1c01c-7c48-4791-9eec-a03301703c15 ``` #### 注意的点 ```ruby 1.实体类一定要在一个其中名称为 model 的包下, 避免所有实体类存在接口, 限定哪些类可以提供增删改查接口 2.配置文件中, 如果有配置了服务名, 那么接口的前缀会带上该服务名, 支持微服务网关接口风格 3.后端无需写接口, 但是前端需要规范调用, 比如查询单笔, 那么后缀一定是 /selectOne, 新增那么后缀一定是 /insert 分页查询, 那么后缀一定是 /selectPage, 列表查询那么后缀一定是 /select 根据 ID 查询单笔, 那么后缀一定是 /selectById, 修改那么后缀一定是 /update, 删除那么后缀一定是 /delete, 根据 ID 删除, 那么后缀一定是 /deleteById 逻辑删除, 那么后缀一定是 /deleteLogicalById ``` #### 扩展支持 ```ruby 1.其中实体类会包含一个基础类 BaseEntity, 如果想使用自己的基础类, 需要查看 SPeed-ORM 文档, 比如主键字段属性需要使用 @Id 注解进行标注, 不作为数据库映射字段属性使用 @AsNotField 注解, 逻辑删除字段属性 @AsLogicalField 2.自定义业务接口类, 就像平时的 controller 一样的写法, 只是位置在 service 层, 没有 controller 层, 没有 controller 层是因为避免逻辑代码出现在 controller 层中 3.操作和访问数据库时, 直接可以使用 SPeed-ORM 中的万能 Model 类, 极简的代码实现数据库访问和操作功能 ``` #### 举一个栗子 ##### 新建一个项目 ```ruby spring-zero-test ``` ![输入图片说明](doc/1.png) ##### 提供数据源配置 ```ruby server: port: 8088 spring: application: name: auth-server datasource: url: jdbc:mysql://127.0.0.1:3306/zero?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 username: root password: 1234 driver-class-name: com.mysql.cj.jdbc.Driver speed: show-log: true ``` ##### 创建实体类 在一个包名为 model 的包路径下 ```ruby package com.example.model; import com.tlgen.orm.common.BaseEntity; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import java.util.Date; /** * 用户实体类 */ @Data @Builder @NoArgsConstructor @AllArgsConstructor public class SysUser extends BaseEntity { private String username; private String nickname; private Integer gender; private String avatar; private String password; private String mobile; private String email; private Integer status; private String address; private Date birth; private String keyword; } ``` ##### 访问接口测试 ```ruby https://apifox.com/apidoc/shared-96f1c01c-7c48-4791-9eec-a03301703c15 ``` #### 有人说我想自定义接口 ##### 定义 Service 接口 ```ruby package com.example.service; import com.tlgen.zero.common.R; import org.springframework.web.bind.annotation.GetMapping; public interface SysUserService { /** * 根据手机号模糊查询推荐的用户列表 * * @param mobile 模糊手机号码 * @return */ @GetMapping R selectRecommendUserList(String mobile); } ``` ##### 写接口实现类 ```ruby package com.example.service.impl; import com.example.model.SysUser; import com.example.service.SysUserService; import com.tlgen.orm.common.Model; import com.tlgen.orm.factory.QueryOperator; import com.tlgen.zero.common.R; import org.springframework.stereotype.Service; import java.util.List; @Service public class SysUserServiceImpl implements SysUserService { @Override public R selectRecommendUserList(String mobile) { List select = Model.select(new QueryOperator().like(SysUser::getMobile, mobile), SysUser.class); return R.ok(select, "查询成功!"); } } ``` ##### 自定义接口访问测试 访问路径 ```ruby http://localhost:8088/auth-server/sysUser/selectRecommendUserList?mobile=136 ``` ##### 自定义接口注意的点 ```ruby 1.@GetMapping 注解后边不写 url 时会默认使用方法名作为接口后缀路径 2.@RequestMapping 可以加上, 也可以不加, 可以根据类名规范即可 3.怎么知道是 /sysUser/, 没有 @RequestMapping 时, 以 SysUserService 名称获取, 支持以 Api 和 Service 结尾的命名规则, 如接口类名称为 SysUserApi 和 SysUserService 4.接口定义写法跟平时的 controller 类中的写法一模一样, 就是支持 Spring 原有功能 5.如果你一定要写 controller, 没有关系, 一样能够完美运行, 零代码这里也减掉了 controller 而已 ``` # 映射注解 一般都不用做这些配置, 如果你需要很复杂的话, 它都可以帮到你 ```ruby @ID ## 主键映射 @TableName ## 绑定数据库表名称 @FieldName ## 属性绑定数据库字段 @AsNotField ## 不作为数据库映射字段 @AsLogicalField ## 标记为一个逻辑删除字段 @Association ## 一对一模型关联 @Collection ## 一对多模型关联 @MappingClass ## 中间表映射类型 @ParentId ## 标记映射一个父 ID ``` # 丰富的查询装饰器 ![输入图片说明](sql/img.png) # 熟练万能 API ## API 风格一(推荐) ### 查询用户 ```ruby @GetMapping("/select") public List select() { return Model.select(SysUser.class); } ``` 返回结果,如果包含 @Association 或 @Collection 注解则会返回如下一对一或一对多的数据结构,案例可以查看下边的 RBAC 案例。 ```ruby [ { "phonenumber":"13617786374", "id":"1", "dept":{ "id":"1", "deptName":"开发部门", "parentId":"4", "children":null }, "roleList":[ { "id":"2", "roleName":"VIP 用户" }, { "id":"4", "roleName":"企业家" } ], "username":"小米" }, { "phonenumber":"13617786380", "id":"10", "dept":{ "id":"10", "deptName":"子子部门测试2", "parentId":"9", "children":null }, "username":"女帝" }, { "phonenumber":"13617786381", "id":"11", "username":"李茂贞" }, { "phonenumber":"13617786382", "id":"12", "username":"张天师" }, { "phonenumber":"13617786383", "id":"13", "username":"李淳风" }, { "phonenumber":"13617786384", "id":"14", "username":"慧觉大师" }, { "phonenumber":"13617786385", "id":"15", "username":"骆小贝" }, { "phonenumber":"13617786386", "id":"16", "username":"啊姐" }, { "phonenumber":"13617786387", "id":"17", "username":"小米11" }, { "phonenumber":"13617786388", "id":"18", "username":"小米22" }, { "phonenumber":"13617786389", "id":"19", "username":"小米33" }, { "phonenumber":"13617786370", "id":"2", "dept":{ "id":"2", "deptName":"测试部门", "parentId":"4", "children":null }, "roleList":[ { "id":"3", "roleName":"普通用户" } ], "username":"魅族" }, { "phonenumber":"13617786390", "id":"20", "username":"小米44" }, { "phonenumber":"13617786372", "id":"3", "dept":{ "id":"3", "deptName":"运维部门", "parentId":"4", "children":null }, "username":"hello" }, { "phonenumber":"13617786373", "id":"4", "dept":{ "id":"4", "deptName":"Java 部门", "parentId":"0", "children":null }, "username":"小e" }, { "phonenumber":"13617786375", "id":"5", "dept":{ "id":"5", "deptName":"产品部门", "parentId":"4", "children":null }, "username":"苹果" }, { "phonenumber":"13617786376", "id":"6", "dept":{ "id":"6", "deptName":"外包部门", "parentId":"0", "children":null }, "username":"不良帅" }, { "phonenumber":"13617786377", "id":"7", "dept":{ "id":"7", "deptName":"自研部门", "parentId":"0", "children":null }, "username":"李星云" }, { "phonenumber":"13617786378", "id":"8", "dept":{ "id":"8", "deptName":"摸鱼部门", "parentId":"0", "children":null }, "username":"姬如雪" }, { "phonenumber":"13617786379", "id":"9", "dept":{ "id":"9", "deptName":"子部门测试", "parentId":"2", "children":null }, "username":"陆林轩" } ] ``` ### 分页查询用户 ```ruby @GetMapping("/selectPage") public List selectPage() { return Model.selectPage(1, 3, new QueryOperator() .like("username", "小"), SysUser.class); } ``` 返回结果 ```ruby [ { "id":"1", "username":"小米", "phonenumber":"13617786374", "dept":null, "roleList":null }, { "id":"15", "username":"骆小贝", "phonenumber":"13617786385", "dept":null, "roleList":null }, { "id":"17", "username":"小米11", "phonenumber":"13617786387", "dept":null, "roleList":null } ] ``` ### 树形数据 ```ruby @GetMapping("/tree") public List tree() { return Model.tree(SysDept.class); } ``` 返回结果 ```ruby [ { "deptName": "Java 部门", "children": [ { "deptName": "开发部门", "children": [], "id": "1", "parentId": "4" }, { "deptName": "测试部门", "children": [ { "deptName": "子部门测试", "children": [ { "deptName": "子子部门测试2", "children": [], "id": "10", "parentId": "9" } ], "id": "9", "parentId": "2" } ], "id": "2", "parentId": "4" }, { "deptName": "运维部门", "children": [], "id": "3", "parentId": "4" }, { "deptName": "产品部门", "children": [], "id": "5", "parentId": "4" } ], "id": "4", "parentId": "0" }, { "deptName": "外包部门", "id": "6", "parentId": "0" }, { "deptName": "自研部门", "id": "7", "parentId": "0" }, { "deptName": "摸鱼部门", "id": "8", "parentId": "0" } ] ``` ### 查询图书 ```ruby @GetMapping("/select") public List select() { return Model.select(Book.class); } ``` 返回结果 ```ruby [ { "author":"小a", "price":12, "name":"南光极东", "id":"1" }, { "author":"晓晓", "name":"权力游戏", "id":"12" }, { "author":"小b", "price":30, "name":"教父", "id":"2" }, { "author":"c论", "price":22, "name":"冥冥之中", "id":"3" }, { "author":"22", "price":32, "name":"怪剑奇谭", "id":"4" }, { "author":"影月", "name":"怪剑", "id":"861478075935936512" }, { "author":"223", "price":87, "name":"怪剑奇谭", "id":"861478362155241472" } ] ``` ### 条件查询图书 ```ruby @GetMapping("/selectList") public List selectList() { return Model.select(new QueryOperator() .like(Book::getAuthor, "小"), Book.class); } ``` 返回结果 ```ruby [ { "id":"1", "name":"南光极东", "author":"小a", "price":12 }, { "id":"2", "name":"教父", "author":"小b", "price":30 } ] ``` ### 支持 Lambda 双冒号获取字段语法提示 ```ruby @GetMapping("/selectList2") public List selectList2() { return Model.select(new QueryOperator() .like(Book::getName, "小"), Book.class); } ``` ### 查询单笔图书 ```ruby @GetMapping("/selectOne") public Book selectOne() { return Model.selectOne(new QueryOperator() .like(Book::getAuthor, "小"), Book.class); } ``` 返回结果 ```ruby { "id":"1", "name":"南光极东", "author":"小a", "price":12 } ``` ### 根据 ID 查询图书 ```ruby @GetMapping("/selectById") public Book selectById() { return Model.selectById("2", Book.class); } ``` 返回结果 ```ruby { "id":"2", "name":"教父", "author":"小b", "price":30 } ``` ### 新增图书 ```ruby @GetMapping("/save") public Object save() { Book book = new Book(); book.setName("权力游戏"); book.setAuthor("晓晓"); return Model.save(book); } ``` ### 批量新增图书 ```ruby @GetMapping("/saveBatch") public Object saveBatch() { List bookList = new ArrayList<>(); Book book1 = new Book(); book1.setName("怪剑"); book1.setAuthor("影月"); book1.setPrice(new BigDecimal(26)); bookList.add(book1); Book book2 = new Book(); book2.setName("简单化"); book2.setAuthor("明明"); bookList.add(book2); Model.saveBatch(bookList); return true; } ``` ### 更新图书 ```ruby @GetMapping("/update") public Object update() { Book book = new Book(); book.setId("12"); book.setName("权力游戏"); book.setAuthor("晓晓"); Model.update(book); return true; } ``` ### 条件更新多个图书 ```ruby @GetMapping("/updateList") public Object updateList() { Book book = new Book(); book.setName("怪剑奇谭"); Model.update(new QueryOperator().eq(Book::getName, "怪剑1"), book); return true; } ``` ### 条件更新图书 ```ruby @GetMapping("/update2") public Object update2() { Book book = Model.selectById("1", Book.class); book.setName("南光极东"); Model.update(book); return true; } ``` ### 根据 ID 删除图书 ```ruby @GetMapping("/deleteById") public Object deleteById() { Model.deleteById("5", Book.class); return true; } ``` ### 条件删除图书 ```ruby @GetMapping("/deleteList") public Object deleteList() { Model.delete(new QueryOperator() .eq(Book::getName, "简单化") .eq(Book::getAuthor, "明明"), Book.class); return true; } ``` ### 删除全部图书 ```ruby @GetMapping("/delete") public Object delete() { Model.delete(Book.class); return true; } ``` ### 一对一、一对多 ```ruby @GetMapping("/select") public List select() { return Model.select(SysUser.class); } ``` 返回结果 ```ruby [ { "phonenumber": "13617786374", "id": "1", "dept": { "id": "1", "deptName": "开发部门", "parentId": "4" }, "roleList": [ { "id": "2", "roleName": "VIP 用户" }, { "id": "4", "roleName": "企业家" } ], "username": "小米" }, { "phonenumber": "13617786380", "id": "10", "username": "女帝" } ] ``` ### 模糊查询 ```ruby @GetMapping("/like") public Object like() { return Model.select(new QueryOperator().like(Book::getName, "力"), Book.class); } ``` 返回结果 ```ruby [ { "id":"12", "name":"权力游戏", "author":"晓晓", "price":20 } ] ``` ### 左模糊查询 ```ruby @GetMapping("/likeLeft") public Object likeLeft() { return Model.select(new QueryOperator().likeLeft(Book::getName, "东"), Book.class); } ``` 返回结果 ```ruby [ { "id":"1", "name":"南光极东", "author":"小a", "price":12 } ] ``` ### 右模糊查询 ```ruby @GetMapping("/likeRight") public Object likeRight() { return Model.select(new QueryOperator().likeRight(Book::getName, "权"), Book.class); } ``` 返回结果 ```ruby [ { "id":"1", "name":"南光极东", "author":"小a", "price":12 } ] ``` ### 不等于查询 ```ruby @GetMapping("/ne") public Object ne() { return Model.select(new QueryOperator().ne(Book::getName, "南光极东"), Book.class); } ``` 返回结果 ```ruby [ { "id":"12", "name":"权力游戏", "author":"晓晓", "price":20 }, { "id":"2", "name":"教父", "author":"小b", "price":30 }, { "id":"3", "name":"冥冥之中", "author":"c论", "price":22 }, { "id":"4", "name":"怪剑奇谭", "author":"22", "price":32 }, { "id":"5", "name":"迷茫", "author":"仙女", "price":null }, { "id":"861478075935936512", "name":"怪剑", "author":"影月", "price":null }, { "id":"861478362155241472", "name":"怪剑奇谭", "author":"223", "price":87 } ] ``` ### OR 查询 ```ruby @GetMapping("/or") public Object or() { return Model.select(new QueryOperator().eq(Book::getName, "南光极东").or(Book::getName, "教父"), Book.class); } ``` 返回结果 ```ruby [ { "id":"1", "name":"南光极东", "author":"小a", "price":12 }, { "id":"2", "name":"教父", "author":"小b", "price":30 } ] ``` ### IN 查询 ```ruby @GetMapping("/in") public Object in() { return Model.select(new QueryOperator().in(Book::getAuthor, Arrays.asList("晓晓", "c论")), Book.class); } ``` 返回结果 ```ruby [ { "id":"12", "name":"权力游戏", "author":"晓晓", "price":20 }, { "id":"3", "name":"冥冥之中", "author":"c论", "price":22 } ] ``` ### NOT IN 查询 ```ruby @GetMapping("/notIn") public Object notIn() { return Model.select(new QueryOperator().notIn(Book::getAuthor, Arrays.asList("晓晓", "c论")), Book.class); } ``` 返回结果 ```ruby [ { "id":"1", "name":"南光极东", "author":"小a", "price":12 }, { "id":"2", "name":"教父", "author":"小b", "price":30 }, { "id":"4", "name":"怪剑奇谭", "author":"22", "price":32 }, { "id":"5", "name":"迷茫", "author":"仙女", "price":null }, { "id":"861478075935936512", "name":"怪剑", "author":"影月", "price":null }, { "id":"861478362155241472", "name":"怪剑奇谭", "author":"223", "price":87 } ] ``` ### 小于查询 ```ruby @GetMapping("/lt") public Object lt() { return Model.select(new QueryOperator().lt(Book::getPrice, 30), Book.class); } ``` 返回结果 ```ruby [ { "id":"1", "name":"南光极东", "author":"小a", "price":12 }, { "id":"12", "name":"权力游戏", "author":"晓晓", "price":20 }, { "id":"3", "name":"冥冥之中", "author":"c论", "price":22 } ] ``` ### 小于等于查询 ```ruby @GetMapping("/le") public Object le() { return Model.select(new QueryOperator().le(Book::getPrice, 30), Book.class); } ``` 返回结果 ```ruby [ { "id":"1", "name":"南光极东", "author":"小a", "price":12 }, { "id":"12", "name":"权力游戏", "author":"晓晓", "price":20 }, { "id":"2", "name":"教父", "author":"小b", "price":30 }, { "id":"3", "name":"冥冥之中", "author":"c论", "price":22 } ] ``` ### 大于查询 ```ruby @GetMapping("/gt") public Object gt() { return Model.select(new QueryOperator().gt(Book::getPrice, 20), Book.class); } ``` 返回结果 ```ruby [ { "id":"2", "name":"教父", "author":"小b", "price":30 }, { "id":"3", "name":"冥冥之中", "author":"c论", "price":22 }, { "id":"4", "name":"怪剑奇谭", "author":"22", "price":32 }, { "id":"861478362155241472", "name":"怪剑奇谭", "author":"223", "price":87 } ] ``` ### 大于等于查询 ```ruby @GetMapping("/ge") public Object ge() { return Model.select(new QueryOperator().ge(Book::getPrice, 20), Book.class); } ``` 返回结果 ```ruby [ { "id":"12", "name":"权力游戏", "author":"晓晓", "price":20 }, { "id":"2", "name":"教父", "author":"小b", "price":30 }, { "id":"3", "name":"冥冥之中", "author":"c论", "price":22 }, { "id":"4", "name":"怪剑奇谭", "author":"22", "price":32 }, { "id":"861478362155241472", "name":"怪剑奇谭", "author":"223", "price":87 } ] ``` ### between 介于两者之间查询 ```ruby @GetMapping("/between") public Object between() { return Model.select(new QueryOperator().between(Book::getPrice, 20, 30), Book.class); } ``` 返回结果 ```ruby [ { "id":"12", "name":"权力游戏", "author":"晓晓", "price":20 }, { "id":"2", "name":"教父", "author":"小b", "price":30 }, { "id":"3", "name":"冥冥之中", "author":"c论", "price":22 } ] ``` ### NOT BETWEEN 不在两者之间查询 ```ruby @GetMapping("/notBetween") public Object notBetween() { return Model.select(new QueryOperator().notBetween(Book::getPrice, 20, 30), Book.class); } ``` 返回结果 ```ruby [ { "id":"1", "name":"南光极东", "author":"小a", "price":12 }, { "id":"4", "name":"怪剑奇谭", "author":"22", "price":32 }, { "id":"861478362155241472", "name":"怪剑奇谭", "author":"223", "price":87 } ] ``` ### 字段为空查询 ```ruby @GetMapping("/isNull") public Object isNull() { return Model.select(new QueryOperator().isNull(Book::getPrice), Book.class); } ``` 返回结果 ```ruby [ { "id":"5", "name":"迷茫", "author":"仙女", "price":null }, { "id":"861478075935936512", "name":"怪剑", "author":"影月", "price":null } ] ``` ### 字段不为空查询 ```ruby @GetMapping("/isNotNull") public Object isNotNull() { return Model.select(new QueryOperator().isNotNull(Book::getPrice), Book.class); } ``` 返回结果 ```ruby [ { "id":"1", "name":"南光极东", "author":"小a", "price":12 }, { "id":"12", "name":"权力游戏", "author":"晓晓", "price":20 }, { "id":"2", "name":"教父", "author":"小b", "price":30 }, { "id":"3", "name":"冥冥之中", "author":"c论", "price":22 }, { "id":"4", "name":"怪剑奇谭", "author":"22", "price":32 }, { "id":"861478362155241472", "name":"怪剑奇谭", "author":"223", "price":87 } ] ``` ### GROUP BY 分组查询 ```ruby @GetMapping("/groupBy") public Object groupBy() { return Model.select(new QueryOperator().groupBy(Book::getId, Book::getName, Book::getPrice), Book.class); } ``` 返回结果 ```ruby [ { "id":"1", "name":"南光极东", "author":"小a", "price":12 }, { "id":"12", "name":"权力游戏", "author":"晓晓", "price":20 }, { "id":"2", "name":"教父", "author":"小b", "price":30 }, { "id":"3", "name":"冥冥之中", "author":"c论", "price":22 }, { "id":"4", "name":"怪剑奇谭", "author":"22", "price":32 }, { "id":"5", "name":"迷茫", "author":"仙女", "price":null }, { "id":"861478075935936512", "name":"怪剑", "author":"影月", "price":null }, { "id":"861478362155241472", "name":"怪剑奇谭", "author":"223", "price":87 } ] ``` ### GROUP BY 分组查询2 ```ruby @GetMapping("/groupBy2") public Object groupBy2() { return Model.select(new QueryOperator().groupBy("id", "name", "price"), Book.class); } ``` ### ORDER BY ASC 升序查询 ```ruby @GetMapping("/orderByAsc") public Object orderByAsc() { return Model.select(new QueryOperator().orderByAsc(Book::getId, Book::getPrice), Book.class); } ``` 返回结果 ```ruby [ { "id":"1", "name":"南光极东", "author":"小a", "price":12 }, { "id":"12", "name":"权力游戏", "author":"晓晓", "price":20 }, { "id":"2", "name":"教父", "author":"小b", "price":30 }, { "id":"3", "name":"冥冥之中", "author":"c论", "price":22 }, { "id":"4", "name":"怪剑奇谭", "author":"22", "price":32 }, { "id":"5", "name":"迷茫", "author":"仙女", "price":null }, { "id":"861478075935936512", "name":"怪剑", "author":"影月", "price":null }, { "id":"861478362155241472", "name":"怪剑奇谭", "author":"223", "price":87 } ] ``` ### ORDER BY 升序查询2 ```ruby @GetMapping("/orderByAsc2") public Object orderByAsc2() { return Model.select(new QueryOperator().orderByAsc("id", "price"), Book.class); } ``` ### ORDER BY DESC 降序查询 ```ruby @GetMapping("/orderByDesc") public Object orderByDesc() { return Model.select(new QueryOperator().orderByDesc(Book::getPrice), Book.class); } ``` 返回结果 ```ruby [ { "id":"861478362155241472", "name":"怪剑奇谭", "author":"223", "price":87 }, { "id":"4", "name":"怪剑奇谭", "author":"22", "price":32 }, { "id":"2", "name":"教父", "author":"小b", "price":30 }, { "id":"3", "name":"冥冥之中", "author":"c论", "price":22 }, { "id":"12", "name":"权力游戏", "author":"晓晓", "price":20 }, { "id":"1", "name":"南光极东", "author":"小a", "price":12 }, { "id":"5", "name":"迷茫", "author":"仙女", "price":null }, { "id":"861478075935936512", "name":"怪剑", "author":"影月", "price":null } ] ``` ### ORDER BY DESC 降序查询2 ```ruby @GetMapping("/orderByDesc2") public Object orderByDesc2() { return Model.select(new QueryOperator().orderByDesc("price"), Book.class); } ``` # RBAC 案例 #### SysUser.java ```ruby package com.tlgen.orm.domain; import com.tlgen.orm.annotation.*; import java.util.List; // 可以自定义指定 TableName,也可以不写 @TableName(name = "sys_user") public class SysUser { @PRI // @FieldName(name = "id") private String id; @FieldName(name = "username") private String username; private String phonenumber; @Association(relate = "dept_id") private SysDept dept; @Collection(middle = SysUserRole.class) private List roleList; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPhonenumber() { return phonenumber; } public void setPhonenumber(String phonenumber) { this.phonenumber = phonenumber; } public SysDept getDept() { return dept; } public void setDept(SysDept dept) { this.dept = dept; } public List getRoleList() { return roleList; } public void setRoleList(List roleList) { this.roleList = roleList; } @Override public String toString() { return "SysUser{" + "id='" + id + '\'' + ", username='" + username + '\'' + ", phonenumber='" + phonenumber + '\'' + ", dept=" + dept + ", roleList=" + roleList + '}'; } } ``` #### SysUserRole.java ```ruby package com.tlgen.orm.domain; import com.tlgen.orm.annotation.FieldName; import com.tlgen.orm.annotation.MappingClass; import com.tlgen.orm.annotation.TableName; public class SysUserRole { @MappingClass(SysUser.class) @FieldName(name = "user_id") private String userId; @MappingClass(SysRole.class) @FieldName(name = "role_id") private String roleId; public String getUserId() { return userId; } public void setUserId(String userId) { this.userId = userId; } public String getRoleId() { return roleId; } public void setRoleId(String roleId) { this.roleId = roleId; } public SysUserRole(String userId, String roleId) { this.userId = userId; this.roleId = roleId; } public SysUserRole() { } } ``` #### SysRole.java ```ruby package com.tlgen.orm.domain; import com.tlgen.orm.annotation.FieldName; import com.tlgen.orm.annotation.Id; import com.tlgen.orm.annotation.TableName; public class SysRole { @Id private String id; @FieldName(name = "role_name") private String roleName; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getRoleName() { return roleName; } public void setRoleName(String roleName) { this.roleName = roleName; } public SysRole(String id, String roleName) { this.id = id; this.roleName = roleName; } public SysRole() { } @Override public String toString() { return "SysRole{" + "id='" + id + '\'' + ", roleName='" + roleName + '\'' + '}'; } } ``` #### SysDept.java ```ruby package com.tlgen.orm.domain; import com.tlgen.orm.annotation.FieldName; import com.tlgen.orm.annotation.Id; import com.tlgen.orm.annotation.ParentId; import com.tlgen.orm.annotation.TableName; import java.util.List; public class SysDept { @Id private String id; @FieldName(name = "dept_name") private String deptName; @ParentId @FieldName(name = "parent_id") private String parentId; private List children; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getDeptName() { return deptName; } public void setDeptName(String deptName) { this.deptName = deptName; } public String getParentId() { return parentId; } public void setParentId(String parentId) { this.parentId = parentId; } public List getChildren() { return children; } public void setChildren(List children) { this.children = children; } @Override public String toString() { return "SysDept{" + "id='" + id + '\'' + ", deptName='" + deptName + '\'' + ", parentId='" + parentId + '\'' + ", children=" + children + '}'; } } ``` ``` # SQL 范例 ```ruby SELECT * FROM book WHERE author LIKE '%小%' SELECT * FROM book WHERE name LIKE '%小%' SELECT * FROM book WHERE author LIKE '%小%' LIMIT 1 SELECT * FROM book WHERE id = '2' SELECT * FROM book WHERE name LIKE '%力%' SELECT * FROM book WHERE name NOT LIKE '%怪%' SELECT * FROM book WHERE name LIKE '%东' SELECT * FROM book WHERE name LIKE '权%' SELECT * FROM book WHERE name <> '南光极东' SELECT * FROM book WHERE name = '南光极东' OR name = '教父' SELECT * FROM book WHERE author IN ( '晓晓' , 'c论' ) SELECT * FROM book WHERE author NOT IN ( '晓晓' , 'c论' ) SELECT * FROM book WHERE price < '30' SELECT * FROM book WHERE price <= '30' SELECT * FROM book WHERE price > '20' SELECT * FROM book WHERE price >= '20' SELECT * FROM book WHERE price BETWEEN '20' AND '30' SELECT * FROM book WHERE price NOT BETWEEN '20' AND '30' SELECT * FROM book WHERE price IS NULL SELECT * FROM book WHERE price IS NOT NULL SELECT * FROM book GROUP BY id, name, price SELECT * FROM book GROUP BY id, name, price SELECT * FROM book ORDER BY id, price ASC SELECT * FROM book ORDER BY id, price ASC SELECT * FROM book ORDER BY price DESC SELECT * FROM book ORDER BY price DESC ```