# mybatis-plus-jpa-dicode **Repository Path**: mybatis-plus-jpa/mybatis-plus-jpa-dicode ## Basic Information - **Project Name**: mybatis-plus-jpa-dicode - **Description**: mybatis-plus-jpa-dicode打破了传统意义上的低代码理念,实现了真正意义上的建表自动化和接口自动化,除定制场景外全程不需要写代码。 - **Primary Language**: Java - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-07-16 - **Last Updated**: 2025-10-11 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 介绍 mybatis-plus-jpa-dicode打破了传统意义上的低代码理念,实现了真正意义上的建表自动化和接口自动化,除定制场景外全程不需要写代码。 ## Maven引用[点击此处查看最新版本号](https://central.sonatype.com/artifact/com.xiaoyudeguang/mybatis-plus-jpa-dicode) ```xml com.xiaoyudeguang mybatis-plus-jpa-dicode ${最新版本} ``` 也可访问[mybatis-plus-jpa-dicode-demo](https://gitee.com/mybatis-plus-jpa/mybatis-plus-jpa-dicode-demo)下载示例项目 ## 添加配置 ``` server: port: 8080 spring: main: allow-bean-definition-overriding: true datasource: driver-class-name: com.mysql.cj.jdbc.Driver type: com.alibaba.druid.pool.DruidDataSource username: ${MYSQL_USER:root} password: ${MYSQL_PWD:123456} url: jdbc:mysql://mysql-server:3306/${MYSQL_DB:demo}?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&allowMultiQueries=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true jpa: hibernate: ddl-auto: update properties: hibernate: enable_lazy_load_no_trans: true schema_update: unique_constraint_strategy: RECREATE_QUIETLY data: redis: database: 1 host: 127.0.0.1 port: 6379 password: 123456 timeout: 10s lettuce: pool: max-active: 200 max-wait: -1ms max-idle: 10 min-idle: 0 springdoc: api-docs: enabled: true info: title: ${pom.name} description: ${pom.description} version: ${pom.version} contact: name: 赵光 email: 1316851612@qq.com license: name: Apache 2.0 url: https://www.apache.org/licenses/LICENSE-2.0.html groups: enabled: true group-configs: - group: all paths-to-match: /**/** display-name: "全部接口" paths-to-exclude: /internal/** oauth2: client-id: oauth-client-id client-secret: oauth-client-secret cache: disabled: false writer-with-default-pretty-printer: true writer-with-order-by-keys: true mybatis-plus: type-handlers-package: com.xiaoyudeguang.handler configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl ``` # 使用教程 ## 自动建表 启动项目后,把下面的curl复制到postman或者直接在命令行执行,然后数据库里就有了一张名称为"sys_dept"的表。 ``` curl --location --request GET 'http://127.0.0.1:8080/sysDept/getById/1' ``` "sys_dept"表的结构( **所有的数据都会存储在json字段中,所以等同于表字段是可以随意扩展的** ): ![输入图片说明](sys_dept%E8%A1%A8%E7%BB%93%E6%9E%84.png) 打开地址 [http://localhost:8080/doc.html],可以看到框架提供的公共接口下的11个接口,都是可以直接调用的(使用教程点击[更多](https://gitee.com/mybatis-plus-jpa/mybatis-plus-jpa-dicode/wikis/公共接口使用说明)查看): ![输入图片说明](image.png) ## 定制场景 ### 1. 假设已经按照上面的教程通过自动建表的方式创建了用户表(sys_user)和角色表(sys_role)和用户角色表(sys_user_role)三张表,我们要新写一个接口查询编码为"zhangsan"的用户有哪些角色,curl如下: ``` curl --location 'http://127.0.0.1:8080/user/roleList' \ --data '{ "userNo": "zhangsan" }' ``` ### 2. 代码实现: #### 2.1 创建实体类 实体类模板 ``` import com.baomidou.mybatisplus.annotation.TableName; import com.xiaoyudeguang.annotation.JsonField; import com.xiaoyudeguang.model.BaseModel; import lombok.*; @Data @Builder @AllArgsConstructor @NoArgsConstructor @TableName("{表名}") public class {实体类名} extends BaseModel<{实体类名}>{ } ``` #### 2.2 创建mapper接口 mybatisplus的[ActiveRecord模式](https://baomidou.com/guides/data-interface/#activerecord)要求必须创建实体类对应的mapper接口,如果不想手动创建,可以引入[mybatis-plus-apt-support](https://gitee.com/mybatis-plus-support/mybatis-plus-apt-support)来自动创建mapper接口 ``` import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.example.model.{实体类名}; import org.apache.ibatis.annotations.Mapper; @Mapper public interface {实体类名}Mapper extends BaseMapper<{实体类名}> { } ``` #### 2.3 编写ServiceImpl(因为数据都会存在json字段中,所以此处用到了[mybatis-plus-json-support](https://gitee.com/mybatis-plus-support/mybatis-plus-json-support)) ``` package com.example.service; import com.fasterxml.jackson.databind.JsonNode; import com.xiaoyudeguang.dicode.service.impl.DiCodeServiceImpl; import org.springframework.stereotype.Service; import java.util.List; import java.util.Map; @Service public class SysUserServiceImpl extends DiCodeServiceImpl { public List roleList(String tableName, JsonNode request) throws Exception { JsonLambdaQueryWrapper sysUserJsonWrapper = new JsonLambdaQueryWrapper<>(); sysUserJsonWrapper.json(SysUser::getJson).eq("userNo", request.findValue("userNo").asText()); SysUser sysUser = new SysUser().selectOne(sysUserJsonWrapper); if (sysUser == null) { throw new BusinessException("用户不存在"); } JsonLambdaQueryWrapper sysUserRoleJsonWrapper = new JsonLambdaQueryWrapper<>(); sysUserRoleJsonWrapper.json(SysUserRole::getJson).in("roleNo", request.findValue("userNo").asText()); List sysUserRoleList = new SysUserRole().selectList(sysUserRoleJsonWrapper); Set roleNoList = sysUserRoleList.stream().map(SysUserRole::getRoleNo).collect(Collectors.toSet()); if (sysUser == null) { throw new BusinessException("用户没有关联角色"); } JsonLambdaQueryWrapper sysRoleJsonWrapper = new JsonLambdaQueryWrapper<>(); sysRoleJsonWrapper.json(SysRole::getJson).in("roleNo", roleNoList); new SysRole().selectList(sysRoleJsonWrapper); return null; } } @Data @Builder @AllArgsConstructor @NoArgsConstructor @TableName("sys_user") public class SysUser extends BaseModel { private static final long serialVersionUID = 1L; @JsonField private String roleNo; @JsonField private String userNo; @JsonField private String userNo; @JsonField private String userName; @JsonField(exist = false) private List roleList; } @Data @Builder @AllArgsConstructor @NoArgsConstructor @TableName("sys_role") public class SysRole extends BaseModel { private static final long serialVersionUID = 1L; @JsonField private String roleNo; @JsonField private String roleName; } @Data @Builder @AllArgsConstructor @NoArgsConstructor @TableName("sys_user_role") public class SysUserRole extends BaseModel { private static final long serialVersionUID = 1L; @JsonField private String roleNo; @JsonField private String userNo; } ``` # 适配其他数据库(框架本身已支持下面3种) ## mysql ```java @Bean public TableSQLProvider tableSQLProvider() { return new TableSQLProvider() { @Override public String getSql(String dataSourceType, String tableName) { return """ CREATE TABLE `%s` ( `id` bigint NOT NULL PRIMARY KEY COMMENT '主键id', `app_id` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '应用id', `tenant_id` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '租户id', `created` datetime DEFAULT NULL COMMENT '创建时间', `creator` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '创建人', `modified` datetime DEFAULT NULL COMMENT '修改时间', `modifier` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '修改人', `status` bigint DEFAULT 0 COMMENT '状态', `is_default` bigint DEFAULT 1 COMMENT '是否默认', `json` json NOT NULL COMMENT '扩展字段', `sort` int DEFAULT 100000 COMMENT '排序' ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='%s' ROW_FORMAT=DYNAMIC; """.formatted(tableName, tableName); } }; } ``` ## gaaus(高斯) ``` @Bean public TableSQLProvider tableSQLProvider() { return new TableSQLProvider() { @Override public String getSql(String dataSourceType, String tableName) { return """ CREATE TABLE "%s" ( "id" BIGSERIAL PRIMARY KEY, "app_id" VARCHAR(50) DEFAULT NULL, "tenant_id" VARCHAR(50) DEFAULT NULL, "created" TIMESTAMP DEFAULT NULL, "creator" VARCHAR(50) DEFAULT NULL, "modified" TIMESTAMP DEFAULT NULL, "modifier" VARCHAR(50) DEFAULT NULL, "status" BIGINT DEFAULT 0, "is_default" BIGINT DEFAULT 1, "json" JSONB NOT NULL, "sort" INTEGER DEFAULT 100000 ) WITH (orientation=column, compression=middle); COMMENT ON COLUMN "%s"."id" IS '主键id'; COMMENT ON COLUMN "%s"."app_id" IS '应用id'; COMMENT ON COLUMN "%s"."tenant_id" IS '租户id'; COMMENT ON COLUMN "%s"."created" IS '创建时间'; COMMENT ON COLUMN "%s"."creator" IS '创建人'; COMMENT ON COLUMN "%s"."modified" IS '修改时间'; COMMENT ON COLUMN "%s"."modifier" IS '修改人'; COMMENT ON COLUMN "%s"."status" IS '状态'; COMMENT ON COLUMN "%s"."is_default" IS '是否默认'; COMMENT ON COLUMN "%s"."json" IS '扩展字段'; COMMENT ON COLUMN "%s"."sort" IS '排序'; COMMENT ON TABLE "%s" IS '%s'; """.formatted( tableName, tableName, tableName, tableName, tableName, tableName, tableName, tableName, tableName, tableName, tableName, tableName, tableName, tableName ); } }; } ``` ## dm(达梦) ``` @Bean public TableSQLProvider tableSQLProvider() { return new TableSQLProvider() { @Override public String getSql(String dataSourceType, String tableName) { return """ CREATE TABLE "%s" ( "ID" BIGINT NOT NULL IDENTITY(1,1) PRIMARY KEY, "APP_ID" VARCHAR(50) DEFAULT NULL, "TENANT_ID" VARCHAR(50) DEFAULT NULL, "CREATED" DATETIME DEFAULT NULL, "CREATOR" VARCHAR(50) DEFAULT NULL, "MODIFIED" DATETIME DEFAULT NULL, "MODIFIER" VARCHAR(50) DEFAULT NULL, "STATUS" BIGINT DEFAULT 0, "IS_DEFAULT" BIGINT DEFAULT 1, "JSON" CLOB NOT NULL, "SORT" INT DEFAULT 100000 ); COMMENT ON COLUMN "%s"."ID" IS '主键id'; COMMENT ON COLUMN "%s"."APP_ID" IS '应用id'; COMMENT ON COLUMN "%s"."TENANT_ID" IS '租户id'; COMMENT ON COLUMN "%s"."CREATED" IS '创建时间'; COMMENT ON COLUMN "%s"."CREATOR" IS '创建人'; COMMENT ON COLUMN "%s"."MODIFIED" IS '修改时间'; COMMENT ON COLUMN "%s"."MODIFIER" IS '修改人'; COMMENT ON COLUMN "%s"."STATUS" IS '状态'; COMMENT ON COLUMN "%s"."IS_DEFAULT" IS '是否默认'; COMMENT ON COLUMN "%s"."JSON" IS '扩展字段'; COMMENT ON COLUMN "%s"."SORT" IS '排序'; COMMENT ON TABLE "%s" IS '%s'; """.formatted( tableName, tableName, tableName, tableName, tableName, tableName, tableName, tableName, tableName, tableName, tableName, tableName, tableName, tableName ); } }; } ```