From 42be92f01660dc44d6357590bead51be840155f6 Mon Sep 17 00:00:00 2001 From: sun5769675 Date: Fri, 4 Nov 2022 09:20:12 +0000 Subject: [PATCH 1/3] =?UTF-8?q?update=20mybatis-enhance-actable/README.md.?= =?UTF-8?q?=20md=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: sun5769675 --- mybatis-enhance-actable/README.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/mybatis-enhance-actable/README.md b/mybatis-enhance-actable/README.md index 36c9200..7279f3d 100644 --- a/mybatis-enhance-actable/README.md +++ b/mybatis-enhance-actable/README.md @@ -14,7 +14,7 @@ A.C.Table是对Mybatis做的增强功能,支持SpringBoot以及传统的Spring A.C.Table是采用了Spring、Mybatis技术的Maven结构,详细介绍如下: - **基本使用规范** +#### 基本使用规范 1.需要依赖mybatis-enhance-actable-1.5.0.RELEASE.jar @@ -70,7 +70,7 @@ A.C.Table是采用了Spring、Mybatis技术的Maven结构,详细介绍如下 1. com.gitee.sunchenbin.mybatis.actable.manager.* ``` - **Springboot+Mybatis的项目使用步骤方法** +#### Springboot+Mybatis的项目使用步骤方法 1. 首先pom文件依赖actable框架 @@ -107,7 +107,7 @@ A.C.Table是采用了Spring、Mybatis技术的Maven结构,详细介绍如下 2. 通过注解@MapperScan配置,扫描mybatis的mapper,路径为"com.gitee.sunchenbin.mybatis.actable.dao.*" ``` - **传统Spring+Mybatis的Web项目使用步骤方法** +#### 传统Spring+Mybatis的Web项目使用步骤方法 1. 首先pom文件依赖actable框架 @@ -190,7 +190,7 @@ A.C.Table是采用了Spring、Mybatis技术的Maven结构,详细介绍如下 ``` -**代码用途讲解** +#### 代码用途讲解 1. MySqlCharsetConstant.java这个对象里面配置的是mysql的数据类型,这里配置的类型越多,意味着创建表时能使用的类型越多 @@ -227,7 +227,7 @@ A.C.Table是采用了Spring、Mybatis技术的Maven结构,详细介绍如下 13.系统启动后会去自动调用SysMysqlCreateTableManagerImpl.java的createMysqlTable()方法,没错,这就是核心方法了,负责创建、删除、修改表。 - **model的写法例子(这里的@Table和@Column都是用的actable中的,也支持使用javax.persistence包下的@Table和@Column以及@Id)** +#### model的写法例子(这里的@Table和@Column都是用的actable中的,也支持使用javax.persistence包下的@Table和@Column以及@Id) ``` @Builder @Data @@ -294,7 +294,7 @@ public class UserEntity extends BaseModel{ private String realName; } ``` - **@Column不设置类型时的默认转换规则如下(建议类型使用对象类型不要用基本数据类型)** +#### @Column不设置类型时的默认转换规则如下(建议类型使用对象类型不要用基本数据类型) javaToMysqlTypeMap.put("class java.lang.String", MySqlTypeConstant.VARCHAR); javaToMysqlTypeMap.put("class java.lang.Long", MySqlTypeConstant.BIGINT); @@ -309,7 +309,7 @@ public class UserEntity extends BaseModel{ javaToMysqlTypeMap.put("class java.sql.Timestamp", MySqlTypeConstant.DATETIME); javaToMysqlTypeMap.put("class java.sql.Time", MySqlTypeConstant.TIME); - **共通的CUDR功能使用** +#### 共通的CUDR功能使用 1.使用方法很简单,大家在manager或者Controller中直接注入BaseCRUDManager这个接口就可以了 @@ -319,7 +319,7 @@ public class UserEntity extends BaseModel{ 4.最新版本1.3.0.RELEASE引入了对tk.mybatis的支持,方便更灵活的CUDR,仅限于使用javax.persistence的注解Column/Table/Id时生效 - **AC.Table支持tk.mybatis框架的CUDR方法** +#### AC.Table支持tk.mybatis框架的CUDR方法 请参考tk.mybatis官方文档使用即可。 @@ -425,7 +425,7 @@ public class UserEntity extends BaseModel{ "

selectByExampleAndRowBounds:" + JSON.toJSONString(userEntities4); } - **BaseCRUDManager使用代码示例** +#### BaseCRUDManager使用代码示例 ``` @Controller public class TestController{ @@ -468,7 +468,7 @@ public class TestController{ } ``` - **AC.Table支持的共通类BaseCRUDManager的CUDR方法接口文档如下** +#### AC.Table支持的共通类BaseCRUDManager的CUDR方法接口文档如下 /** * 根据实体对象的非Null字段作为Where条件查询结果集,如果对象的属性值都为null则返回全部数据等同于selectAll @@ -621,7 +621,7 @@ public class TestController{ PageResultCommand search(T t); - **######### mybatis增加功能自动创建表——A.C.Table版本说明################** +#### mybatis增加功能自动创建表——A.C.Table版本说明 1. 该版本修复了修改主键同时修改其类型引起的error(版本1.0.1) 2. 该版本修复了根据model创建时没有创建父类中的字段的问题(ps:目前只支持扫描一层继承)(版本1.0.1) 3. 该版本增加了对唯一约束的支持(版本1.0.1) -- Gitee From c3249f027d093eae0a71ed2f4e64537e030abc74 Mon Sep 17 00:00:00 2001 From: sun5769675 Date: Fri, 4 Nov 2022 09:20:45 +0000 Subject: [PATCH 2/3] =?UTF-8?q?update=20README.md.=20md=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: sun5769675 --- README.md | 744 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 742 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ae0fefd..1dc387e 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# mybatis-enhance-actable +# mybatis-enhance-actable-1.5.0.RELEASE 官方文档:[ACTable官方文档地址](https://www.yuque.com/sunchenbin/actable/nfz097) @@ -8,6 +8,746 @@ ACTable技术交流QQ群:[746531106](https://jq.qq.com/?_wv=1027&k=xE4i0dWl) -A.C.Table是对Mybatis做的增强功能,实现了mybatis自动建表的能力,mybatis-enhance-actable支持SpringBoot以及传统的SpringMvc项目结构,简单配置即可,该框架是为了能够使习惯了hibernate框架的开发者能够快速的入手Mybatis, “A.C.Table” 本意是自动建表的意思,A.C.Table是一个基于Spring和Mybatis的Maven项目,增强了Mybatis的功能,过配置model注解的方式来创建表,修改表结构,并且实现了共通的CUDR功能提升开发效率,同时能够兼容tk.mybatis和mybatis-plus,如需使用依赖相关的pom依赖即可,目前仅支持Mysql,后续会扩展针对其他数据库的支持。 +A.C.Table是对Mybatis做的增强功能,支持SpringBoot以及传统的SpringMvc项目结构,简单配置即可,该框架是为了能够使习惯了hibernate框架的开发者能够快速的入手Mybatis, “A.C.Table” 本意是自动建表的意思,A.C.Table是一个基于Spring和Mybatis的Maven项目,增强了Mybatis的功能,过配置model注解的方式来创建表,修改表结构,并且实现了共通的CUDR功能提升开发效率,同时能够兼容tk.mybatis和mybatis-plus,如需使用依赖相关的pom依赖即可,目前仅支持Mysql,后续会扩展针对其他数据库的支持。 [Javadoc文档:https://apidoc.gitee.com/sunchenbin/mybatis-enhance](https://apidoc.gitee.com/sunchenbin/mybatis-enhance) + +A.C.Table是采用了Spring、Mybatis技术的Maven结构,详细介绍如下: + +#### 基本使用规范 + +1.需要依赖mybatis-enhance-actable-1.5.0.RELEASE.jar + +``` + + com.gitee.sunchenbin.mybatis.actable + mybatis-enhance-actable + 1.5.0.RELEASE + + + + + tk.mybatis + mapper-spring-boot-starter + 2.1.5 + +``` + +2.需要配置对于actable支持的配置 + +``` + actable.table.auto=update + actable.model.pack=com.xxx.store.model(ps:要扫描的用于建表做依据的model目录) + actable.database.type=mysql + + 本系统提供四种模式: + + 2.1 当actable.table.auto=create时,系统启动后,会将所有的表删除掉,然后根据model中配置的结构重新建表,该操作会破坏原有数据。 + + 2.2 当actable.table.auto=update时,系统会自动判断哪些表是新建的,哪些字段要修改类型等,哪些字段要删除,哪些字段要新增,该操作不会破坏原有数据。 + + 2.3 当actable.table.auto=none时,系统不做任何处理。 + + 2.4 当actable.table.auto=add,新增表/新增字段/新增索引/新增唯一约束的功能,不做做修改和删除 (只在版本1.0.9.RELEASE及以上支持)。 + + 2.5 actable.model.pack这个配置是用来配置要扫描的用于创建表的对象的包名 + + 2.6 actable.database.type这个是用来区别数据库的,预计会支持这四种数据库mysql/oracle/sqlserver/postgresql,但目前仅支持mysql + +``` + +3. 支持actable的mybatis配置(必备的配置) + +``` + + 1. classpath*:com/gitee/sunchenbin/mybatis/actable/mapping/*/*.xml + 2. com.gitee.sunchenbin.mybatis.actable.dao.* +``` + +4. 扫描actable的包到spring容器中管理(必备的配置) + +``` + 1. com.gitee.sunchenbin.mybatis.actable.manager.* +``` + +#### Springboot+Mybatis的项目使用步骤方法 + +1. 首先pom文件依赖actable框架 + +``` + + com.gitee.sunchenbin.mybatis.actable + mybatis-enhance-actable + 1.5.0.RELEASE + + + + + tk.mybatis + mapper-spring-boot-starter + 2.1.5 + +``` + +2. 项目的application.properties文件配置例如下面 + +``` + # actable的配置信息 + actable.table.auto=update + actable.model.pack=com.xxx.store.model(ps:要扫描的model目录) + actable.database.type=mysql + # mybatis的配置信息,key也可能是:mybatis.mapper-locations + mybatis.mapperLocations=classpath*:com/gitee/sunchenbin/mybatis/actable/mapping/*/*.xml;自己的mapper.xml没有可不填 +``` + +3. springboot启动类需要做如下配置 + +``` + 1. 通过注解@ComponentScan配置,扫描actable要注册到spring的包路径"com.gitee.sunchenbin.mybatis.actable.manager.*" + 2. 通过注解@MapperScan配置,扫描mybatis的mapper,路径为"com.gitee.sunchenbin.mybatis.actable.dao.*" +``` + +#### 传统Spring+Mybatis的Web项目使用步骤方法 + +1. 首先pom文件依赖actable框架 + +``` + + com.gitee.sunchenbin.mybatis.actable + mybatis-enhance-actable + 1.5.0.RELEASE + + + + + tk.mybatis + mapper-spring-boot-starter + 2.1.5 + +``` + +2. 在你的web项目上创建个目录比如config下面创建个文件autoCreateTable.properties文件的内容如下: + +``` + actable.table.auto=update + actable.model.pack=com.xxx.store.model(ps:要扫描的model目录) + actable.database.type=mysql +``` + +3. spring的配置文件中需要做如下配置: +``` + + + + + + + + classpath*:config/autoCreateTable.properties + + + + + + + + + 1. classpath*:com/gitee/sunchenbin/mybatis/actable/mapping/*/*.xml + 2. com.gitee.sunchenbin.mybatis.actable.dao.* + + 举例这两个配置配置的详细位置 + + + + + + + + classpath*:自己的mappring.xml没有可不填 + classpath*:com/gitee/sunchenbin/mybatis/actable/mapping/*/*.xml + + + + + + + + + + + + + + + + + + + + mappers=tk.mybatis.mapper.common.Mapper,tk.mybatis.mapper.common.special.InsertListMapper + + + +``` + +#### 代码用途讲解 + + 1. MySqlCharsetConstant.java这个对象里面配置的是mysql的数据类型,这里配置的类型越多,意味着创建表时能使用的类型越多 + + 2. @Column.java也是一个自定义的注解,用于标记model中的字段上,作为创建表的依据如不标记,不会被扫描到,有几个属性用来设置字段名、字段类型、长度等属性的设置,详细请看代码上的注释 + + 3. @Table.java也是一个自定义的注解,用于标记在model对象上,有一个属性name,用于设置该model生成表后的表名,如不设置该注解,则该model不会被扫描到 + + 4. @Index.java是一个自定义注解,用于标记在model中的字段上,表示为该字段创建索引,有两个属性一个是设置索引名称,一个是设置索引字段,支持多字段联合索引,如果都不设置默认为当前字段创建索引 + + 5. @Unique.java是一个自定义注解,用于标记在model中的字段上,表示为该字段创建唯一约束,有两个属性一个是设置约束名称,一个是设置约束字段,支持多字段联合约束,如果都不设置默认为当前字段创建唯一约束 + + 6. @TableComment用来配置表的注释,可用来替代@Table的comment + + 7. @IsKey/@IsAutoIncrement/@IsNotNull用来代替 @Column中的isKey/isAutoIncrement/isNull三个属性,当然旧的配置方式仍然是支持的 + + 8. @ColumnComment字段注释,用来替代@Column中的comment + + 9. @DefaultValue字段默认值,用来替代@Column中的defaultValue + + 10.@ColumnType字段类型,用来替代@Column中的type,取值范围MySqlTypeConstant.java中的枚举 + + 11.@TableCharset表字符集,用来替代@Table中的charset,取值范围MySqlCharsetConstant.java中的枚举 + + 12.@TableEngine表引擎类型,用来替代@Table中的engine,取值范围MySqlEngineConstant.java中的枚举 + + 13.支持javax.persistence包中的部分注解,用于对tk.mybatis做支持 + + javax.persistence.Column 同 com.gitee.sunchenbin.mybatis.actable.annotation.Column + javax.persistence.Column.name 同 com.gitee.sunchenbin.mybatis.actable.annotation.Column.name + javax.persistence.Column.length 同 com.gitee.sunchenbin.mybatis.actable.annotation.Column.length + javax.persistence.Column.scale 同 com.gitee.sunchenbin.mybatis.actable.annotation.Column.decimalLength + javax.persistence.Table 同 com.gitee.sunchenbin.mybatis.actable.annotation.Table + javax.persistence.Id 同 com.gitee.sunchenbin.mybatis.actable.annotation.IsKey + + 13.系统启动后会去自动调用SysMysqlCreateTableManagerImpl.java的createMysqlTable()方法,没错,这就是核心方法了,负责创建、删除、修改表。 + +#### model的写法例子(这里的@Table和@Column都是用的actable中的,也支持使用javax.persistence包下的@Table和@Column以及@Id) +``` +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@Table(name = "test") +@TableComment("测试表") +@TableEngin(MySqlEngineConstant.InnoDB) +@TableCharset(MySqlCharsetConstant.UTF8MB4) +public class UserEntity extends BaseModel{ + + private static final long serialVersionUID = 5199200306752426433L; + + // 第一种主键设置方式 + @Column(name = "id",type = MySqlTypeConstant.INT,length = 11,isKey = true,isAutoIncrement = true) + private Integer id; + + // 第二种简化的主键设置方式 + @IsKey + @IsAutoIncrement + @Column + @ColumnType(MySqlTypeConstant.INT) + private Integer id; + + // 第一种设置索引的方法,这种方法会在数据库默认创建索引名称为actable_idx_{login_name},索引字段为login_name + @Index + // 第二种设置索引的方法,这种方法会在数据库创建索引名称为actable_idx_{t_idx_login_name},索引字段为login_name + @Index("t_idx_login_name") + // 第三种设置索引的方法,这种方法会在数据库创建索引名称为actable_idx_{t_idx_login_name},索引字段为login_name + @Index(value="t_idx_login_name",columns={"login_name"}) + // 第四种设置索引的方法,可以设置联合索引,这种方法会在数据库创建索引名称为actable_idx_{login_name_mobile},索引字段为login_name和mobile + @Index(columns={"login_name","mobile"}) + // 第五种设置索引的方法,可以设置联合索引,这种方法会在数据库创建索引名称为actable_idx_{login_name_mobile},索引字段为login_name和mobile + @Index(value="t_idx_login_name_mobile",columns={"login_name","mobile"}) + // 唯一约束的注解的使用方法,跟@Index相同 + @Unique + @Column(name = "login_name",type = MySqlTypeConstant.VARCHAR,length = 111) + private String loginName; + + // column的简化写法,不配置默认使用当前属性名作为字段名,当前类型默认转换至mysql支持的类型 + @Column + private String mobile; + + // column的简化写法,根据需要设置注解属性 + @Column(name = "createTime") + private Date create_time; + + @Column(name = "update_time",type = MySqlTypeConstant.DATETIME) + private Date update_time; + + @Column(name = "number",type = MySqlTypeConstant.DECIMAL,length = 10,decimalLength = 2) + private BigDecimal number; + + // 第一种设置字段非空的方法 + @Column(name = "lifecycle",type = MySqlTypeConstant.CHAR,length = 1,isNull=false) + // 第二种设置字段非空的方法 + @IsNotNull + @Column + private String lifecycle; + + @Column + @DefaultValue("111") + @ColumnComment("昵称") + private String realName; +} +``` +#### @Column不设置类型时的默认转换规则如下(建议类型使用对象类型不要用基本数据类型) + + javaToMysqlTypeMap.put("class java.lang.String", MySqlTypeConstant.VARCHAR); + javaToMysqlTypeMap.put("class java.lang.Long", MySqlTypeConstant.BIGINT); + javaToMysqlTypeMap.put("class java.lang.Integer", MySqlTypeConstant.INT); + javaToMysqlTypeMap.put("class java.lang.Boolean", MySqlTypeConstant.BIT); + javaToMysqlTypeMap.put("class java.math.BigInteger", MySqlTypeConstant.BIGINT); + javaToMysqlTypeMap.put("class java.lang.Float", MySqlTypeConstant.FLOAT); + javaToMysqlTypeMap.put("class java.lang.Double", MySqlTypeConstant.DOUBLE); + javaToMysqlTypeMap.put("class java.math.BigDecimal", MySqlTypeConstant.DECIMAL); + javaToMysqlTypeMap.put("class java.sql.Date", MySqlTypeConstant.DATE); + javaToMysqlTypeMap.put("class java.util.Date", MySqlTypeConstant.DATE); + javaToMysqlTypeMap.put("class java.sql.Timestamp", MySqlTypeConstant.DATETIME); + javaToMysqlTypeMap.put("class java.sql.Time", MySqlTypeConstant.TIME); + +#### 共通的CUDR功能使用 + + 1.使用方法很简单,大家在manager或者Controller中直接注入BaseCRUDManager这个接口就可以了 + + 2.旧的BaseMysqlCRUDManager类废弃了请不要使用 + + 3.注意:接口调用方法时传入的对象必须是modle中用于创建表的对象才可以 + + 4.最新版本1.3.0.RELEASE引入了对tk.mybatis的支持,方便更灵活的CUDR,仅限于使用javax.persistence的注解Column/Table/Id时生效 + +#### AC.Table支持tk.mybatis框架的CUDR方法 + + 请参考tk.mybatis官方文档使用即可。 + + import com.gitee.sunchenbin.mybatis.actable.annotation.Index; + import com.gitee.sunchenbin.mybatis.actable.annotation.IsAutoIncrement; + import com.gitee.sunchenbin.mybatis.actable.annotation.IsKey; + import lombok.AllArgsConstructor; + import lombok.Builder; + import lombok.Data; + import lombok.NoArgsConstructor; + + import javax.persistence.Column; + import javax.persistence.Id; + import javax.persistence.Table; + import java.io.Serializable; + import java.util.Date; + + @Builder + @Data + @NoArgsConstructor + @AllArgsConstructor + @Table(name = "user_entity") + public class UserEntity extends UserEntity1 implements Serializable { + + @Id + @IsKey + @IsAutoIncrement + @Column + private Long id; + + @Column(name = "login_name") + @Index + private String loginName; + + @Column(name = "nick_name") + private String nickName; + + @Column(name = "real_name") + private String realName; + + @Column(name = "password") + private String password; + + @Column(name = "mobile") + private String mobile; + + @Column(name = "istrue") + private Boolean isTrue; + + @Column(name = "it") + private Integer it; + + @Column + private Date createTime; + + @Column + private Date modifyTime; + } + + import com.alex.orderapi.dao.entity.UserEntity; + import tk.mybatis.mapper.common.Mapper; + + public interface UserMapper extends Mapper { + + } + + @RequestMapping("/select/user1") + public String select1(HttpServletRequest request) { + userMapper.insert(UserEntity.builder().loginName("s").createTime(new Date()).realName("v").password("r").mobile("1").build()); + userMapper.insert(UserEntity.builder().loginName("s").createTime(new Date()).realName("v").password("r").mobile("2").build()); + userMapper.insert(UserEntity.builder().loginName("s").createTime(new Date()).realName("v").password("r").mobile("3").build()); + userMapper.insert(UserEntity.builder().loginName("s").createTime(new Date()).realName("v").password("r").mobile("4").build()); + userMapper.insert(UserEntity.builder().loginName("s").createTime(new Date()).realName("v").password("r").mobile("5").build()); + userMapper.insert(UserEntity.builder().loginName("s").createTime(new Date()).realName("v").password("r").mobile("6").build()); + userMapper.insert(UserEntity.builder().loginName("s").createTime(new Date()).realName("v").password("r").mobile("7").build()); + userMapper.insert(UserEntity.builder().loginName("s").createTime(new Date()).realName("v").password("r").mobile("8").build()); + userMapper.insert(UserEntity.builder().loginName("s").createTime(new Date()).realName("v").password("r").mobile("9").build()); + userMapper.insert(UserEntity.builder().loginName("s").createTime(new Date()).realName("v").password("r").mobile("10").build()); + userMapper.insert(UserEntity.builder().loginName("s").createTime(new Date()).realName("v").password("r").mobile("11").build()); + userMapper.insert(UserEntity.builder().loginName("s").createTime(new Date()).realName("v").password("r").mobile("12").build()); + userMapper.insert(UserEntity.builder().loginName("s").createTime(new Date()).realName("v").password("r").mobile("13").build()); + userMapper.insert(UserEntity.builder().loginName("s").createTime(new Date()).realName("v").password("r").mobile("14").build()); + userMapper.insert(UserEntity.builder().loginName("s").createTime(new Date()).realName("v").password("r").mobile("2").build()); + List userEntities1 = userMapper.selectAll(); + List select = userMapper.select(UserEntity.builder().mobile("2").build()); + Example example = new Example(UserEntity.class); + example.createCriteria().andEqualTo("mobile","3").andEqualTo("loginName","s"); + List userEntities = userMapper.selectByExample(example); + UserEntity v = userMapper.selectOne(UserEntity.builder().id(30L).build()); + UserEntity userEntity = userMapper.selectByPrimaryKey(10); + List userEntities2 = userMapper.selectByRowBounds(UserEntity.builder().build(), new RowBounds(0, 3)); + List userEntities3 = userMapper.selectByExampleAndRowBounds(Example.builder(UserEntity.class).build(), new RowBounds(3, 3)); + Example example1 = new Example(UserEntity.class); + example1.setOrderByClause("id desc"); + List userEntities4 = userMapper.selectByExampleAndRowBounds(example1, new RowBounds(0, 3)); + return "selectAll: " + JSON.toJSONString(userEntities1) + + "

select: " + JSON.toJSONString(select) + + "

selectByExample:" + JSON.toJSONString(userEntities) + + "

selectOne:" + JSON.toJSONString(v) + + "

selectByPrimaryKey:" + JSON.toJSONString(userEntity) + + "

selectByRowBounds:" + JSON.toJSONString(userEntities2) + + "

selectByExampleAndRowBounds:" + JSON.toJSONString(userEntities3) + + "

selectByExampleAndRowBounds:" + JSON.toJSONString(userEntities4); + } + +#### BaseCRUDManager使用代码示例 +``` +@Controller +public class TestController{ + + @Autowired + private TestManager testManager; + + @Autowired + private BaseCRUDManager baseCRUDManager; + + /** + * 首页 + */ + @RequestMapping("/testDate") + @ResponseBody + public String testDate(){ + UserEntity insert = baseCRUDManager.insert(UserEntity.builder().loginName("111").build()); + UserEntity insertSelective = baseCRUDManager.insertSelective(UserEntity.builder().loginName("222").build()); + List userEntities1 = baseCRUDManager.selectAll(UserEntity.class); + boolean b = baseCRUDManager.updateByPrimaryKey(UserEntity.builder().id(1L).mobile("1111").build()); + boolean b1 = baseCRUDManager.updateByPrimaryKeySelective(UserEntity.builder().id(2L).mobile("1111").build()); + UserEntity userEntity = baseCRUDManager.selectOne(UserEntity.builder().id(1L).mobile("1111").build()); + UserEntity userEntity1 = baseCRUDManager.selectByPrimaryKey(UserEntity.builder().id(8L).mobile("1111").build()); + List select = baseCRUDManager.select(UserEntity.builder().mobile("1111").build()); + int i = baseCRUDManager.selectCount(UserEntity.builder().build()); + int sss = baseCRUDManager.delete(UserEntity.builder().realName("sss").build()); + int i1 = baseCRUDManager.deleteByPrimaryKey(UserEntity.builder().id(5L).loginName("222").build()); + boolean b2 = baseCRUDManager.existsByPrimaryKey(UserEntity.builder().id(1L).build()); + boolean b3 = baseCRUDManager.existsByPrimaryKey(UserEntity.builder().id(222L).build()); + UserEntity user = new UserEntity(); + user.setCurrentPage(1); + user.setPageSize(5); + LinkedHashMap ordermap = new LinkedHashMap<>(); + ordermap.put("id",BaseModel.ASC); + user.setOrderBy(ordermap); + PageResultCommand search = baseCRUDManager.search(user); + PageResultCommand search3 = baseCRUDManager.search(user, 1, 5, ordermap); + return "success"; + } +} + +``` +#### AC.Table支持的共通类BaseCRUDManager的CUDR方法接口文档如下 + + /** + * 根据实体对象的非Null字段作为Where条件查询结果集,如果对象的属性值都为null则返回全部数据等同于selectAll + * @param t 实体对象 + * @param 实体对象类型 + * @return List实体对象列表 + * @version 支持版本1.1.0.RELEASE + */ + List select(T t); + + /** + * 根据实体对象的@IsKey主键字段的值作为Where条件查询结果,主键字段不能为null + * @param t 实体对象(只设置主键值即可,其他字段值不会读取) + * @param 实体对象类型 + * @return 实体对象 + * @version 支持版本1.1.0.RELEASE + */ + T selectByPrimaryKey(T t); + + /** + * 查询表全部数据 + * @param clasz 实体对象的class + * @param 实体对象类型 + * @return List实体对象列表 + * @version 支持版本1.1.0.RELEASE + */ + List selectAll(Class clasz); + + /** + * 根据实体对象的非Null字段作为Where条件查询结果集的Count,如果对象的属性值都为null则Count全表 + * @param t 实体对象 + * @param 实体对象类型 + * @return 结果数量 + * @version 支持版本1.1.0.RELEASE + */ + int selectCount(T t); + + /** + * 根据实体对象的非Null字段作为Where条件查询结果集,如果对象的属性值都为null则返回结果集的第一条使用的limit 1 + * @param t 实体对象 + * @param 实体对象类型 + * @return 实体对象 + * @version 支持版本1.1.0.RELEASE + */ + T selectOne(T t); + + /** + * 根据实体对象的非Null字段作为Where条件进行删除操作,如果对象的属性值都为null则删除表全部数据 + * @param t 实体对象 + * @param 实体对象类型 + * @return 返回成功条数 + * @version 支持版本1.1.0.RELEASE + */ + int delete(T t); + + /** + * 根据实体对象的@IsKey主键字段的值作为Where条件进行删除操作,主键字段不能为null + * @param t 实体对象(只设置主键值即可,其他字段值不会读取) + * @param 实体对象类型 + * @return 返回成功条数 + * @version 支持版本1.1.0.RELEASE + */ + int deleteByPrimaryKey(T t); + + /** + * 根据实体对象的@IsKey主键字段的值作为Where条件查询该数据是否存在,主键字段不能为null + * @param t 实体对象(只设置主键值即可,其他字段值不会读取) + * @param 实体对象类型 + * @return true存在,fasle不存在 + * @version 支持版本1.1.0.RELEASE + */ + boolean existsByPrimaryKey(T t); + + /** + * 根据实体对象保存一条数据,主键如果没有设置自增属性则必须不能为null + * @param t 实体对象 + * @param 实体对象类型 + * @return 实体对象 + * @version 支持版本1.1.0.RELEASE + */ + T insert(T t); + + /** + * 根据实体对象保存一条数据,如果属性值为null则不插入默认使用数据库的字段默认值,主键如果没有设置自增属性则必须不能为null + * @param t 实体对象 + * @param 实体对象类型 + * @return 实体对象 + * @version 支持版本1.1.0.RELEASE + */ + T insertSelective(T t); + + /** + * 根据实体对象主键作为Where条件更新其他字段数据,主键必须不能为null + * @param t 实体对象 + * @param 实体对象类型 + * @return 更新结果 + * @version 支持版本1.1.0.RELEASE + */ + boolean updateByPrimaryKey(T t); + + /** + * 根据实体对象主键作为Where条件更新其他字段数据,如果其他字段属性值为null则忽略更新,主键必须不能为null + * @param t 实体对象 + * @param 实体对象类型 + * @return 更新结果 + * @version 支持版本1.1.0.RELEASE + */ + boolean updateByPrimaryKeySelective(T t); + + /** + * 直接根据sql查询数据,并根据指定的对象类型转化后返回 + * + * @param sql 动态sql + * @param beanClass 返回list对象类型 + * @param 实体对象类型 + * @return list的实体对象类型 + * @version 支持版本1.1.0.RELEASE + */ + List query(String sql, Class beanClass); + + /** + * 直接根据sql查询返回数据 + * + * @param sql 自定义的sql + * @return list map结构的数据 + * @version 支持版本1.1.0.RELEASE + */ + List> query(String sql); + + /** + * 根据实体对象的非Null字段作为Where条件查询结果集,如果对象的属性值都为null则返回全部数据等同于selectAll+分页 + * + * @param t 实体对象 + * @param currentPage 分页参数查询第几页,默认1 + * @param pageSize 分页参数每页显示的条数,默认10 + * @param orderby 分页使用的排序,有序的Map结构{key(要排序的字段名),value(desc/asc)} + * @param 实体类型 + * @return PageResultCommand分页对象类型 + * @version 支持版本1.1.1.RELEASE + */ + PageResultCommand search(T t, Integer currentPage, Integer pageSize,LinkedHashMap orderby); + + /** + * 根据实体对象的非Null字段作为Where条件查询结果集,如果对象的属性值都为null则返回全部数据等同于selectAll+分页 + * @param t 实体对象 + * @param 实体对象类型 + * @return PageResultCommand分页对象类型 + * @version 支持版本1.1.1.RELEASE + */ + PageResultCommand search(T t); + + +#### mybatis增加功能自动创建表——A.C.Table版本说明 +1. 该版本修复了修改主键同时修改其类型引起的error(版本1.0.1) +2. 该版本修复了根据model创建时没有创建父类中的字段的问题(ps:目前只支持扫描一层继承)(版本1.0.1) +3. 该版本增加了对唯一约束的支持(版本1.0.1) +4. 从原有的框架中剥离出来,支持任意结构的spring+mybatis的框架使用(版本1.0.1) +5. 再次声明A.C.Table目前仅支持mysql数据库(版本1.0.1) +6. 修复了不同数据库中有相同表名时,启动报错的问题。(版本1.0.2) +7. 修复了model属性名与表字段名不一致时公共的查询方法查不出数据的问题。(版本1.0.2) +8. 增加了对公共的CUDR方法的优化,保存成功会返回id,query查询时可以设置参数进行分页查询(pageSize:int类型标识每页数量,currentPage:int类型标识当前第几页,start:int类型从第几条开始,orderField:string类型排序字段,sortStr:string类型排序方式(desc,asc))(版本1.0.3) +9. 增加了对Mysql的longtext和mediumtext两种字段类型的支持,公共的CUDR方法的优化,原query方法更正为search,现query方法支持动态sql查询,原orderField字段只支持单个字段的排序,现修改为orderBy字段,支持数据类型为LinkedHashMap,有序,key为字段名,value为排序方式(版本1.0.4) +10. 增加对mysql数据库(timestamp/time/date/float/bit)五种数据类型的支持(版本1.0.5) +11. 增加对springboot框架的支持(版本1.0.5) +12. 删除旧版本在@Colum中实现唯一约束的方式(版本1.0.6.RELEASE) +13. 增加了新的唯一约束实现方式@Unique,支持多字段聚合约束(版本1.0.6.RELEASE) +14. 增加了索引创建方式@Index,支持多字段聚合索引(版本1.0.6.RELEASE) +15. 修复query查询方法无法返回父类字段数据的bug(版本1.0.6.RELEASE) +16. 修复原本是主键,现在依然主键,修改该字段的其他信息时会报multiple primary key defined(例如id为int(11),改为int(10)后,就可重现次bug)(版本1.0.7.RELEASE) +17. 增加对字段备注的支持,使用方式@Column的comment属性(版本1.0.7.RELEASE) +18. 修复issues/IZ6WQ:bit类型的默认值设置失败,默认值可以使用0、1、true、false(版本1.0.8.1.RELEASE) +19. 修复issues/IYTJ1:使用@Unique进行联合约束,启动项目自动创建表结构后,删除联合约束报错(版本1.0.8.1.RELEASE) +20. 迭代issues/IYW9F:mybatis.model.pack支持多包扫描","或者";"隔开(版本1.0.8.1.RELEASE) +21. 修复issues/I160LP:drop拼写的问题(版本1.0.9.RELEASE) +22. 优化issues/I1IENW:@Index,@Unique创建索引和唯一约束的实现逻辑,默认会给索引名和约束名增加前缀actable_idx_和actable_uni_方便更新删除时只针对这两个前缀的进行删除更新,避免删掉手动创建的字段的索引约束 (版本1.0.9.RELEASE) +23. 修复issues/I16OZQ::@Index,@Unique在只设置了索引名称没有设置索引字段时,报错的bug,并且原有name改为value,原有value改为columns(版本1.0.9.RELEASE) +24. 迭代issues/I1IF5E:增加对tinyint/smallint/mediumint/year/blob/longblob/mediumblob/tinytext/tinyblob/binary字段类型的支持 (版本1.0.9.RELEASE) +25. 迭代issues/I1IF5Q:框架模式新增add模式,本模式下只具备,新增表/新增字段/新增索引/新增唯一约束的功能,不会做修改和删除 (版本1.0.9.RELEASE) +26. 迭代issues/I193FC:@Column的name属性改为非必填,不填默认使用属性名作为表字段名 (版本1.0.9.RELEASE) +27. 迭代issues/I193FC:@Column的type属性改为非必填,不填默认使用属性的数据类型进行转换,转换失败的字段不会添加 (版本1.0.9.RELEASE) + + 支持java类型转mysql类型如下: + + java.lang.String + java.lang.Long + java.lang.Integer + java.lang.Boolean + java.math.BigInteger + java.lang.Float + java.lang.Double + java.math.BigDecimal + java.sql.Date + java.util.Date + java.sql.Timestamp + java.sql.Time + + 本次迭代至1.0.9.RELEASE,极大的简化了注解的使用复杂度,在保留原有复杂的自定义配置能力的同时,增加了更多的默认适配能力 + 也就是对于@Column标签如果对字段命名等没有任何要求的情况下,直接使用标签即可,无需配置类型等参数,会默认根据上面支持的类型去进行匹配转换 +28. 迭代issues/I1ILS6:@IsKey/@IsAutoIncrement/@IsNotNull用来代替 @Column中的isKey/isAutoIncrement/isNull三个属性,当然旧的配置方式仍然是支持的 (版本1.0.9.RELEASE) +29. 紧急修复1.0.9.RELEASE版本CUDR的bug,请不要使用1.0.9.RELEASE版本(版本1.0.9.1.RELEASE) +30. 迭代issues/I1IVXK:BaseMysqlCRUDManager该工具类废弃,请勿使用,新增工具类BaseCRUDManager,新的insert接口取消了对主键的integer类型的限定,主键可以自由使用类型(版本1.1.0.RELEASE) + + 新增工具类BaseCRUDManager的方法列表如下,详细接口文档见文档结尾部分: + + List select(T t); + T selectByPrimaryKey(T t); + List selectAll(Class clasz); + int selectCount(T t); + T selectOne(T t); + int delete(T t); + int deleteByPrimaryKey(T t); + boolean existsByPrimaryKey(T t); + T insert(T t); + T insertSelective(T t); + boolean updateByPrimaryKey(T t); + boolean updateByPrimaryKeySelective(T t); + List query(String sql, Class beanClass); + List> query(String sql); +31. 迭代issues/I1JC91:工具类BaseCRUDManager新增对分页查询的支持,新增两个search接口一个实体中包含分页字段,一个通过方法参数传递分页字段(版本1.1.1.RELEASE) + + 新增工具类BaseCRUDManager的方法列表如下,详细接口文档见文档结尾部分: + + PageResultCommand search(T t, Integer currentPage, Integer pageSize,LinkedHashMap orderby); + PageResultCommand search(T t); +32. 建表的字段时如果@Column没有设置字段名,那么默认会读属性的名字,根据驼峰转换逻辑,进行转换例如loginName会转换为login_name作为字段名,如果没有驼峰也就是全是小写字母,那么直接作为字段名,如果设置了Column(name="LOGIN_NAME")那么默认创建的字段会转换为小写,也就是login_name,所以字段名都会强制转换为小写(版本1.2.0.RELEASE,**该版本对于之前建表字段名使用大写的项目不向下兼容,要升级至此版本需谨慎**) +33. 修复索引约束创建完成后,修改字段名的情况下报错的bug(版本1.2.0.RELEASE,**该版本对于之前建表字段名使用大写的项目不向下兼容,要升级至此版本需谨慎**) +34. 为了防止配置信息引起歧义(版本1.2.0.RELEASE,**该版本对于之前建表字段名使用大写的项目不向下兼容,要升级至此版本需谨慎**) + + mybatis.table.auto 变为 actable.table.auto + mybatis.model.pack 变为 actable.model.pack + mybatis.database.type 变为 actable.database.type +35. 修复建表时没有读取继承类中的字段信息的问题(版本1.2.0.RELEASE,**该版本对于之前建表字段名使用大写的项目不向下兼容,要升级至此版本需谨慎**) +36. 迭代issues/I1LUAZ:修复实体对象字段有多个大写,转换为列名时,只转换了第一个下划线,提供对@Table标签的驼峰转换的支持,不填表名默认使用类名驼峰转换(版本1.2.1.RELEASE) +37. 支持使用javax.persistence的Column/Table/Id等注解生成及更新表(版本1.3.0.RELEASE) + + javax.persistence.Column = com.gitee.sunchenbin.mybatis.actable.annotation.Column + javax.persistence.Column.name = com.gitee.sunchenbin.mybatis.actable.annotation.Column.name + javax.persistence.Column.length = com.gitee.sunchenbin.mybatis.actable.annotation.Column.length + javax.persistence.Column.scale = com.gitee.sunchenbin.mybatis.actable.annotation.Column.decimalLength + javax.persistence.Table = com.gitee.sunchenbin.mybatis.actable.annotation.Table + javax.persistence.Id = com.gitee.sunchenbin.mybatis.actable.annotation.IsKey +38. 引入对tk.mybatis的支持,方便更灵活的CUDR,仅限于使用javax.persistence包的Column/Table/Id等注解时生效,如使用actable的注解则只支持BaseCRUDManager(版本1.3.0.RELEASE) +39. 增加对json数据类型的支持(版本1.3.0.RELEASE) +40. 增加注解@ColumnComment字段注释,用来替代@Column中的comment(版本1.3.0.RELEASE) +41. 增加注解@DefaultValue字段默认值,用来替代@Column中的defaultValue(版本1.3.0.RELEASE) +42. 增加注解@ColumnType字段类型,用来替代@Column中的type,取值范围MySqlTypeConstant中的枚举(版本1.3.0.RELEASE) +43. 增加注解@TableComment用来配置表的注释,可用来替代@Table的comment(版本1.3.0.RELEASE) +44. 迭代issues/I24UU4:增加注解@TableCharset用来配置表的字符集,可用来替代@Table的charset,取值范围MySqlCharsetConstant中的枚举(版本1.3.1.RELEASE) +45. 增加注解@TableEngine用来配置表的注释,可用来替代@Table的engine,取值范围MySqlEngineConstant中的枚举(版本1.3.1.RELEASE) +46. 删除默认依赖tk.mybatis的pom配置,避免跟其他框架冲突,如需使用自行依赖即可,只要依赖tk.mybatis的pom,actable可以完全兼容使用(版本1.3.2.RELEASE) +47. 修复bug,当设置bit类型的默认值时,启动时会一直日志输出修改改字段的日志记录(版本1.4.0.RELEASE,该版本不向下兼容需修改少量代码,谨慎升级) +48. 修复bug,当使用默认的字段类型时,可以通过@Column的length和decimalLength来配置长度(版本1.4.0.RELEASE,该版本不向下兼容需修改少量代码,谨慎升级) +49. @ColumnType增加length和decimalLength两个属性用来配置该类型的长度(版本1.4.0.RELEASE,该版本不向下兼容需修改少量代码,谨慎升级) +50. 优化注解@Column的type字段以及注解@ColumnType的value字段,类型从String改为枚举类型,枚举类为MySqlTypeConstant(版本1.4.0.RELEASE,该版本不向下兼容需修改少量代码,谨慎升级) +51. 优化注解@TableCharset的value和@TableEngine的value字段类型从String改为枚举类型,枚举类为MySqlCharsetConstant和MySqlEngineConstant(版本1.4.0.RELEASE,该版本不向下兼容需修改少量代码,谨慎升级) +52. 修复bug,当id使用Long类型时,采用BaseCRUDManagerImpl中的保存和更新方法时报错的问题(版本1.4.0.RELEASE,该版本不向下兼容需修改少量代码,谨慎升级) +53. 优化引入对mybatis-plus的支持,方便更灵活的CUDR,支持@TableName/@TableField/@TableId三个注解(版本1.4.0.RELEASE,该版本不向下兼容需修改少量代码,谨慎升级) +54. 移除@LengthCount和@LengthDefault两个注解(版本1.4.0.RELEASE,该版本不向下兼容需修改少量代码,谨慎升级) +55. issues/I28XQY:新增java默认转换LocalDateTime/LocalDate/LocalTime数据类型的支持(版本1.4.1.RELEASE) +56. 修正DOUBLE和FLOAT支持设置小数长度(版本1.4.1.RELEASE) +57. Table标签新增属性isSimple表示是否开启简单的配置模式,如果开启,实体的属性可以不打@Column的标签全部按照默认规则驼峰转换创建字段,默认为false不开启(版本1.4.1.RELEASE) +58. Table标签新增属性excludeFields用来标记排除属性名,排除掉的属性不参与建表(版本1.4.1.RELEASE) +59. 检查实体类有重名的表名会抛异常(版本1.4.1.RELEASE) +60. issues/I2BL9O:新增数据包装数据类型Short,删除byte类型的支持(版本1.4.2.RELEASE) +61. 修复bug,当使用@TableEngine和@TableCharset是失效的问题(版本1.4.3.RELEASE) +62. 修复bug,@Column.isNull()和@javax.persistence.Column.nullable()(版本1.4.4.RELEASE) +63. 修复bug,float和double类型默认小数位数为2,如果强制指定0的情况下会失效,修复后效果为默认效数位数0,人工指定则按照人工指定的来(版本1.4.5.RELEASE) +64. issues/I2DU0K,优化默认值指定的缺陷,之前无法指定某些特殊类型的默认值,例如CURRENT_TIMESTAMP这种,现在支持了,会根据字段类型来决定,目前只有String和Boolean采用字符串传参的方式使用的是'#{}',其他类型均使用原生方式拼接sql使用的是'${}'(版本1.4.6.RELEASE) +65. 新增注解@IsNativeDefValue值的范围是true或者false基于上一版本64条更新日志,系统会自动根据数据类型判断是否使用原生的值作为DEFAULT,这里增加这个注解用来可以手动指定,增加了一些灵活性(版本1.4.7.RELEASE) +66. 新增两个配置项,允许自行指定生成的索引和约束的前缀,不指定默认使用actable_idx_和actable_uni_ + + actable.index.prefix=自己定义的索引前缀 + actable.unique.prefix=自己定义的唯一约束前缀 +67. 如果字段名中包含 ` 关键字会默认忽略掉,因为actable建表时自动给所有字段名增加过了,这个主要是为了避免字段名是数据库的关键字(版本1.4.8.RELEASE) +68. 修复66条自定义索引和唯一约束前缀的功能bug(版本1.4.8.RELEASE) +69. SysMysqlCreateTableManagerImpl.getAllFields方法改为public可被重写(版本1.4.9.RELEASE) +70. issues/I38G7Q:修复避免子类重写付类属性时创建重复字段报错的问题(版本1.4.9.RELEASE) +71. issues/I2CVCS:迭代优化actable.model.pack配置属性支持模糊扫描,支持类似com.bz.**.entity且支持配置多个路径英文逗号或者分号隔开(版本1.4.9.RELEASE) +72. 增加注解@EnableTimeSuffix,支持表名添加时间后缀(版本1.5.0.RELEASE) +73. issues/I3PRVK:添加@IgnoreUpdate注解 标注当前字段参与创建不参与更新,解决使用@DefaultValue("NULL ON UPDATE CURRENT_TIMESTAMP")时当前字段每次重启项目都会进行更新操作的问题(版本1.5.0.RELEASE) +74. issues/I3NGD2:添加@IgnoreTable注解 设置某个model实体不参与建表操作(版本1.5.0.RELEASE) +75. issues/I3TNMB:修复使用mybatisplus时使用了多租户的插件时,使用@ColumnComment注解报错的问题(版本1.5.0.RELEASE) -- Gitee From 7257c070f08c5125ef141d4be3f4cae5ea796837 Mon Sep 17 00:00:00 2001 From: dengbuladuo Date: Sun, 22 Jan 2023 16:17:50 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=A4=96=E9=94=AE?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mybatis-enhance-actable/pom.xml | 16 +- .../mybatis/actable/EnableMyBatisActable.java | 15 ++ .../actable/MyBatisActableEnvironment.java | 12 + .../mybatis/actable/annotation/Foreign.java | 46 ++++ .../actable/command/CreateTableParam.java | 68 +++++ .../mybatis/actable/command/ForeignKey.java | 97 +++++++ .../actable/command/ForeignKeyModel.java | 247 ++++++++++++++++++ .../mybatis/actable/constants/Constants.java | 3 + .../actable/constants/DeleteAction.java | 10 + .../actable/constants/UpdateAction.java | 10 + .../dao/system/CreateMysqlTablesMapper.java | 31 ++- .../SysMysqlCreateTableManagerImpl.java | 206 +++++++++++++-- .../system/CreateMysqlTablesMapper.xml | 99 ++++++- .../spring/ActableMapperRegistrar.java | 154 +++++++++++ 14 files changed, 991 insertions(+), 23 deletions(-) create mode 100644 mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/EnableMyBatisActable.java create mode 100644 mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/MyBatisActableEnvironment.java create mode 100644 mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/annotation/Foreign.java create mode 100644 mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/command/ForeignKey.java create mode 100644 mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/command/ForeignKeyModel.java create mode 100644 mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/constants/DeleteAction.java create mode 100644 mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/constants/UpdateAction.java create mode 100644 mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/spring/ActableMapperRegistrar.java diff --git a/mybatis-enhance-actable/pom.xml b/mybatis-enhance-actable/pom.xml index 67fd95a..ddea24d 100644 --- a/mybatis-enhance-actable/pom.xml +++ b/mybatis-enhance-actable/pom.xml @@ -3,7 +3,7 @@ 4.0.0 com.gitee.sunchenbin.mybatis.actable mybatis-enhance-actable - 1.5.0.RELEASE + 1.6.0.RELEASE org.sonatype.oss @@ -41,6 +41,11 @@ 4.3.7.RELEASE + 8 + 8 + UTF-8 + 1.8 + true @@ -98,6 +103,11 @@ mybatis-plus-annotation 3.4.1 + + org.mybatis.spring.boot + mybatis-spring-boot-starter + 2.1.4 + @@ -169,8 +179,8 @@ maven-compiler-plugin 3.0 - 1.6 - 1.6 + 1.8 + 1.8 true true UTF-8 diff --git a/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/EnableMyBatisActable.java b/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/EnableMyBatisActable.java new file mode 100644 index 0000000..a53b832 --- /dev/null +++ b/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/EnableMyBatisActable.java @@ -0,0 +1,15 @@ +package com.gitee.sunchenbin.mybatis.actable; + + +import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; +import org.springframework.context.annotation.Import; + +import java.lang.annotation.*; + +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE}) +@Documented +@Import({MyBatisActableEnvironment.class}) +@ConditionalOnWebApplication +public @interface EnableMyBatisActable { +} diff --git a/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/MyBatisActableEnvironment.java b/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/MyBatisActableEnvironment.java new file mode 100644 index 0000000..4ed0a04 --- /dev/null +++ b/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/MyBatisActableEnvironment.java @@ -0,0 +1,12 @@ +package com.gitee.sunchenbin.mybatis.actable; + +import com.gitee.sunchenbin.mybatis.actable.spring.ActableMapperRegistrar; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Import; + +@Import(ActableMapperRegistrar.class) +//@MapperScan +@ComponentScan(basePackages = {"com.gitee.sunchenbin.mybatis.actable.manager.*"}) +public class MyBatisActableEnvironment { +} diff --git a/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/annotation/Foreign.java b/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/annotation/Foreign.java new file mode 100644 index 0000000..5eb19ee --- /dev/null +++ b/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/annotation/Foreign.java @@ -0,0 +1,46 @@ +package com.gitee.sunchenbin.mybatis.actable.annotation; + +import java.lang.annotation.*; + +@Target(ElementType.FIELD) +// VM将在运行期也保留注释,因此可以通过反射机制读取注解的信息 +@Retention(RetentionPolicy.RUNTIME) +// 将此注解包含在javadoc中 +@Documented +public @interface Foreign { + + /** + * 外键名字 + * 1.6.0版本支持, + * @return 字段名:不填默认使用属性名作为表字段名 + */ + String value() default ""; + + /** + * 外键名字 + * 1.6.0版本支持, + * @return 字段名:不填默认使用属性名作为表字段名 + */ + String name() default ""; + + /** + * 外表名字 + */ + String foreignTable(); + + /** + * 外表字段名字 + */ + String foreignColumn(); + + /** + * 更新时操作 + */ + String updateAction() default "NO ACTION"; + + /** + * 删除时操作 + */ + String deleteAction() default "NO ACTION"; + +} diff --git a/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/command/CreateTableParam.java b/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/command/CreateTableParam.java index 02980f9..0a0ceab 100644 --- a/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/command/CreateTableParam.java +++ b/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/command/CreateTableParam.java @@ -95,6 +95,34 @@ public class CreateTableParam implements Cloneable{ */ private boolean ignoreUpdate; + + // 外键补充 + /** + * 外键名称 + */ + private String foreignKeyName; + + /** + * 修改时外键操作 + */ + private String updateAction; + + /** + * 删除时,外键操作 + */ + private String deleteAction; + + /** + * 指向外表 + */ + private String foreignTable; + + + /** + * 指向外键 + */ + private String foreignColumn; + public boolean getIgnoreUpdate() { return ignoreUpdate; } @@ -241,4 +269,44 @@ public class CreateTableParam implements Cloneable{ } return createTableParam; } + + public String getUpdateAction() { + return updateAction; + } + + public void setUpdateAction(String updateAction) { + this.updateAction = updateAction; + } + + public String getDeleteAction() { + return deleteAction; + } + + public void setDeleteAction(String deleteAction) { + this.deleteAction = deleteAction; + } + + public String getForeignTable() { + return foreignTable; + } + + public void setForeignTable(String foreignTable) { + this.foreignTable = foreignTable; + } + + public String getForeignColumn() { + return foreignColumn; + } + + public void setForeignColumn(String foreignColumn) { + this.foreignColumn = foreignColumn; + } + + public String getForeignKeyName() { + return foreignKeyName; + } + + public void setForeignKeyName(String foreignKeyName) { + this.foreignKeyName = foreignKeyName; + } } diff --git a/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/command/ForeignKey.java b/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/command/ForeignKey.java new file mode 100644 index 0000000..7bf4ffd --- /dev/null +++ b/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/command/ForeignKey.java @@ -0,0 +1,97 @@ +package com.gitee.sunchenbin.mybatis.actable.command; + +import com.gitee.sunchenbin.mybatis.actable.constants.DeleteAction; +import com.gitee.sunchenbin.mybatis.actable.constants.UpdateAction; + +public class ForeignKey { + + /** + * The name (not a numeric value) of the foreign key index, preceded by the schema (database) name (for example, test/products_fk). + */ + private String id; + + /** + * The name of the child table in this foreign key relationship. + */ + private String forName; + + /** + * The name of the parent table in this foreign key relationship. + */ + private String refName; + + /** + * The number of columns in the foreign key index. + */ + private int cols; + + /** + * A collection of bit flags with information about the foreign key column, ORed together. + * 0 = ON DELETE/UPDATE RESTRICT, + * 1 = ON DELETE CASCADE, + * 2 = ON DELETE SET NULL, + * 4 = ON UPDATE CASCADE, + * 8 = ON UPDATE SET NULL, + * 16 = ON DELETE NO ACTION, + * 32 = ON UPDATE NO ACTION. + */ + private int type; + + /** + * 外部字段名 + */ + private String foreignColumnName; + + + public String getForeignTable(){ + return forName.split("\\/")[1]; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getForName() { + return forName; + } + + public void setForName(String forName) { + this.forName = forName; + } + + public String getRefName() { + return refName; + } + + public void setRefName(String refName) { + this.refName = refName; + } + + public int getCols() { + return cols; + } + + public void setCols(int cols) { + this.cols = cols; + } + + public int getType() { + return type; + } + + public void setType(int type) { + this.type = type; + } + + public String getForeignColumnName() { + return foreignColumnName; + } + + public void setForeignColumnName(String foreignColumnName) { + this.foreignColumnName = foreignColumnName; + } +} diff --git a/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/command/ForeignKeyModel.java b/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/command/ForeignKeyModel.java new file mode 100644 index 0000000..4500da8 --- /dev/null +++ b/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/command/ForeignKeyModel.java @@ -0,0 +1,247 @@ +package com.gitee.sunchenbin.mybatis.actable.command; + +import com.gitee.sunchenbin.mybatis.actable.constants.DeleteAction; +import com.gitee.sunchenbin.mybatis.actable.constants.UpdateAction; + +public class ForeignKeyModel { + +// /** +// * The name (not a numeric value) of the foreign key index, preceded by the schema (database) name (for example, test/products_fk). +// */ +// private String id; +// +// /** +// * The name of the child table in this foreign key relationship. +// */ +// private String forName; +// +// /** +// * The name of the parent table in this foreign key relationship. +// */ +// private String refName; +// +// /** +// * The number of columns in the foreign key index. +// */ +// private int cols; +// +// /** +// * A collection of bit flags with information about the foreign key column, ORed together. +// * 0 = ON DELETE/UPDATE RESTRICT, +// * 1 = ON DELETE CASCADE, +// * 2 = ON DELETE SET NULL, +// * 4 = ON UPDATE CASCADE, +// * 8 = ON UPDATE SET NULL, +// * 16 = ON DELETE NO ACTION, +// * 32 = ON UPDATE NO ACTION. +// */ +// private int type; + +// private String foreignColumnName; + + private String updateAction; + + private String deleteAction; + + private String foreignTable; + + private String foreignKeyName; + + private String childColumnName; + + private String foreignColumn; + + public ForeignKeyModel(String childColumnName, String updateAction, String deleteAction, String foreignTable, String foreignKeyName) { + this.childColumnName = childColumnName; + this.updateAction = updateAction; + this.deleteAction = deleteAction; + this.foreignTable = foreignTable; + this.foreignKeyName = foreignKeyName; + } + + public ForeignKeyModel(String childColumnName, String updateAction, String deleteAction, String foreignTable, String foreignKeyName, String foreignColumn) { + this.childColumnName = childColumnName; + this.updateAction = updateAction; + this.deleteAction = deleteAction; + this.foreignTable = foreignTable; + this.foreignKeyName = foreignKeyName; + this.foreignColumn = foreignColumn; + } + +// public ForeignKeyModel(ForeignKey key){ +// this.refName = key.getRefName(); +// this.forName = key.getForName(); +// this.cols = key.getCols(); +// this.id = key.getId(); +// this.type = key.getType(); +// this.foreignColumnName = key.getForeignColumnName(); +// this.foreignTable = refName.split("\\/")[1]; +// this.foreignKeyName = id.split("\\/")[1]; +// this.updateAction = initUpdateAction(); +// this.deleteAction = initDeleteAction(); +// } + + + + public String getForeignTable(){ + return foreignTable; + } + + public String getForeignKeyName(){ + return foreignKeyName; + } + +// public String initUpdateAction(){ +// +// int t = type; +// if(t == 0){ +// return UpdateAction.RESTRICT; +// } +// +// int d = 0x01 & (t >> 2); +// if(d == 1){ +// return UpdateAction.CASCADE; +// } +// +// d = 0x01 & (t >> 3); +// if(d == 1){ +// return UpdateAction.SET_NULL; +// } +// +// d = 0x01 & (t >> 5); +// if(d == 1){ +// return UpdateAction.NO_ACTION; +// } +// +// return UpdateAction.NO_ACTION; +// } +// +// public String initDeleteAction(){ +// +// int t = type; +// if(t == 0){ +// return DeleteAction.RESTRICT; +// } +// +// int d = 0x01 & (t >> 0); +// if(d == 1){ +// return DeleteAction.CASCADE; +// } +// +// d = 0x01 & (t >> 1); +// if(d == 1){ +// return DeleteAction.SET_NULL; +// } +// +// d = 0x01 & (t >> 4); +// if(d == 1){ +// return DeleteAction.NO_ACTION; +// } +// +// return DeleteAction.NO_ACTION; +// } +// +// public String getId() { +// return id; +// } +// +// public void setId(String id) { +// this.id = id; +// } +// +// public String getForName() { +// return forName; +// } +// +// public void setForName(String forName) { +// this.forName = forName; +// } +// +// public String getRefName() { +// return refName; +// } +// +// public void setRefName(String refName) { +// this.refName = refName; +// } +// +// public int getCols() { +// return cols; +// } +// +// public void setCols(int cols) { +// this.cols = cols; +// } +// +// public int getType() { +// return type; +// } +// +// public void setType(int type) { +// this.type = type; +// } + +// public String getForeignColumnName() { +// return foreignColumnName; +// } +// +// public void setForeignColumnName(String foreignColumnName) { +// this.foreignColumnName = foreignColumnName; +// } + + public String getUpdateAction() { + return updateAction; + } + + public void setUpdateAction(String updateAction) { + this.updateAction = updateAction; + } + + public String getDeleteAction() { + return deleteAction; + } + + public void setDeleteAction(String deleteAction) { + this.deleteAction = deleteAction; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof ForeignKeyModel)) return false; + + ForeignKeyModel that = (ForeignKeyModel) o; + + if (!getUpdateAction().equals(that.getUpdateAction())) return false; + if (!getDeleteAction().equals(that.getDeleteAction())) return false; + if (!getForeignTable().equals(that.getForeignTable())) return false; + if (!getForeignKeyName().equals(that.getForeignKeyName())) return false; + return getChildColumnName().equals(that.getChildColumnName()); + } + + @Override + public int hashCode() { + int result = getUpdateAction().hashCode(); + result = 31 * result + getDeleteAction().hashCode(); + result = 31 * result + getForeignTable().hashCode(); + result = 31 * result + getForeignKeyName().hashCode(); + result = 31 * result + getChildColumnName().hashCode(); + return result; + } + + public String getChildColumnName() { + return childColumnName; + } + + public void setChildColumnName(String childColumnName) { + this.childColumnName = childColumnName; + } + + public String getForeignColumn() { + return foreignColumn; + } + + public void setForeignColumn(String foreignColumn) { + this.foreignColumn = foreignColumn; + } +} diff --git a/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/constants/Constants.java b/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/constants/Constants.java index df510da..b4517c6 100644 --- a/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/constants/Constants.java +++ b/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/constants/Constants.java @@ -27,8 +27,11 @@ public class Constants { public static final String MODIFY_TABLE_PROPERTY_MAP = "modifyTablePropertyMap"; public static final String DROPKEY_TABLE_MAP = "dropKeyTableMap"; public static final String DROPINDEXANDUNIQUE_TABLE_MAP = "dropIndexAndUniqueTableMap"; + + public static final String DROP_FOREIGN_KEY_TABLE_MAP = "DROP_FOREIGN_KEY_TABLE_MAP"; public static final String ADDINDEX_TABLE_MAP = "addIndexTableMap"; public static final String ADDUNIQUE_TABLE_MAP = "addUniqueTableMap"; + public static final String FOREIGN_MAP = "addForeignKey"; public static final String TABLE_INDEX_KEY = "actable.index.prefix"; public static final String TABLE_UNIQUE_KEY = "actable.unique.prefix"; diff --git a/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/constants/DeleteAction.java b/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/constants/DeleteAction.java new file mode 100644 index 0000000..c3a5ff3 --- /dev/null +++ b/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/constants/DeleteAction.java @@ -0,0 +1,10 @@ +package com.gitee.sunchenbin.mybatis.actable.constants; + +public class DeleteAction { + + public static final String RESTRICT = "RESTRICT"; + public static final String NO_ACTION = "NO ACTION"; + public static final String CASCADE = "CASCADE"; + public static final String SET_NULL = "SET NULL"; + +} diff --git a/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/constants/UpdateAction.java b/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/constants/UpdateAction.java new file mode 100644 index 0000000..84dc89b --- /dev/null +++ b/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/constants/UpdateAction.java @@ -0,0 +1,10 @@ +package com.gitee.sunchenbin.mybatis.actable.constants; + +public class UpdateAction { + + public static final String RESTRICT = "RESTRICT"; + public static final String NO_ACTION = "NO ACTION"; + public static final String CASCADE = "CASCADE"; + public static final String SET_NULL = "SET NULL"; + +} diff --git a/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/dao/system/CreateMysqlTablesMapper.java b/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/dao/system/CreateMysqlTablesMapper.java index 2ae657e..abafb8d 100644 --- a/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/dao/system/CreateMysqlTablesMapper.java +++ b/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/dao/system/CreateMysqlTablesMapper.java @@ -5,12 +5,9 @@ import java.util.Map; import java.util.Set; import com.baomidou.mybatisplus.annotation.InterceptorIgnore; -import com.gitee.sunchenbin.mybatis.actable.command.SysMysqlTable; -import com.gitee.sunchenbin.mybatis.actable.command.TableConfig; +import com.gitee.sunchenbin.mybatis.actable.command.*; import org.apache.ibatis.annotations.Param; -import com.gitee.sunchenbin.mybatis.actable.command.SysMysqlColumns; - /** * 创建更新表结构的Mapper @@ -89,6 +86,12 @@ public interface CreateMysqlTablesMapper { */ public void dropTabelIndex(@Param("tableMap") Map tableMap); + /** + * 删除表外键 + * @param tableMap + */ + public void dropTableForeign(@Param("tableMap") Map tableMap); + /** * 创建索引 * @param tableMap @@ -101,4 +104,24 @@ public interface CreateMysqlTablesMapper { */ public void addTableUnique(@Param("tableMap") Map tableMap); + /** + * 创建外键关系 + */ + public void addTableForeign(@Param("tableMap") Map tableMap); + + /** + * 查找所有外键约束名称 + * @return + */ + List findForeignKeyByTableName(@Param("tableName") String tableName, @Param("database") String database); + + /** + * 查询数据库名称 + */ + String selectDatabase(); + + /** + * 获取字段名字 + */ + String describeTableColumn(@Param("tableName")String tableName, @Param("col") int col); } diff --git a/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/manager/system/SysMysqlCreateTableManagerImpl.java b/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/manager/system/SysMysqlCreateTableManagerImpl.java index 6ec8506..bd62c12 100644 --- a/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/manager/system/SysMysqlCreateTableManagerImpl.java +++ b/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/manager/system/SysMysqlCreateTableManagerImpl.java @@ -1,19 +1,9 @@ package com.gitee.sunchenbin.mybatis.actable.manager.system; import com.baomidou.mybatisplus.annotation.TableName; -import com.gitee.sunchenbin.mybatis.actable.annotation.IgnoreUpdate; -import com.gitee.sunchenbin.mybatis.actable.annotation.Index; -import com.gitee.sunchenbin.mybatis.actable.annotation.Table; -import com.gitee.sunchenbin.mybatis.actable.annotation.Unique; -import com.gitee.sunchenbin.mybatis.actable.command.CreateTableParam; -import com.gitee.sunchenbin.mybatis.actable.command.MySqlTypeAndLength; -import com.gitee.sunchenbin.mybatis.actable.command.SysMysqlColumns; -import com.gitee.sunchenbin.mybatis.actable.command.SysMysqlTable; -import com.gitee.sunchenbin.mybatis.actable.command.TableConfig; -import com.gitee.sunchenbin.mybatis.actable.constants.Constants; -import com.gitee.sunchenbin.mybatis.actable.constants.MySqlCharsetConstant; -import com.gitee.sunchenbin.mybatis.actable.constants.MySqlEngineConstant; -import com.gitee.sunchenbin.mybatis.actable.constants.MySqlTypeConstant; +import com.gitee.sunchenbin.mybatis.actable.annotation.*; +import com.gitee.sunchenbin.mybatis.actable.command.*; +import com.gitee.sunchenbin.mybatis.actable.constants.*; import com.gitee.sunchenbin.mybatis.actable.dao.system.CreateMysqlTablesMapper; import com.gitee.sunchenbin.mybatis.actable.manager.util.ConfigurationUtil; import com.gitee.sunchenbin.mybatis.actable.utils.ClassScaner; @@ -36,6 +26,7 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import java.util.stream.Collectors; /** * 项目启动时自动扫描配置的目录中的model,根据配置的规则自动创建或更新表 该逻辑只适用于mysql,其他数据库尚且需要另外扩展,因为sql的语法不同 @@ -73,6 +64,8 @@ public class SysMysqlCreateTableManagerImpl implements SysMysqlCreateTableManage pack = springContextUtil.getConfig(Constants.MODEL_PACK_KEY); tableAuto = springContextUtil.getConfig(Constants.TABLE_AUTO_KEY); + log.info("开始扫描包 {}, 扫描方式 {}", pack, tableAuto); + // 不做任何事情 if (!"none".equals(tableAuto) && !"update".equals(tableAuto) && !"create".equals(tableAuto) && !"add".equals(tableAuto)) { log.warn("配置mybatis.table.auto错误无法识别,当前配置只支持[none/update/create/add]三种类型!"); @@ -148,6 +141,9 @@ public class SysMysqlCreateTableManagerImpl implements SysMysqlCreateTableManage baseTableMap.put(Constants.ADDUNIQUE_TABLE_MAP, new HashMap()); // 9.更新表注释 baseTableMap.put(Constants.MODIFY_TABLE_PROPERTY_MAP, new HashMap()); + // 10.更新外键 + baseTableMap.put(Constants.DROP_FOREIGN_KEY_TABLE_MAP, new HashMap()); + baseTableMap.put(Constants.FOREIGN_MAP, new HashMap()); return baseTableMap; } @@ -210,6 +206,7 @@ public class SysMysqlCreateTableManagerImpl implements SysMysqlCreateTableManage baseTableMap.get(Constants.NEW_TABLE_MAP).put(tableName, new TableConfig(allFieldList, map)); baseTableMap.get(Constants.ADDINDEX_TABLE_MAP).put(tableName, new TableConfig(getAddIndexList(null, allFieldList))); baseTableMap.get(Constants.ADDUNIQUE_TABLE_MAP).put(tableName, new TableConfig(getAddUniqueList(null, allFieldList))); + baseTableMap.get(Constants.FOREIGN_MAP).put(tableName, new TableConfig(getForeignKey(allFieldList))); return; }else{ Map map = new HashMap(); @@ -251,12 +248,25 @@ public class SysMysqlCreateTableManagerImpl implements SysMysqlCreateTableManage String uniPrefix = springContextUtil.getConfig(Constants.TABLE_UNIQUE_KEY); String idxPrefix = springContextUtil.getConfig(Constants.TABLE_INDEX_KEY); Map paramMap = new HashMap(); + String database = createMysqlTablesMapper.selectDatabase(); paramMap.put("tableName", tableName); - paramMap.put("uniquePrefix",uniPrefix); - paramMap.put("indexPrefix",idxPrefix); + paramMap.put("uniquePrefix", uniPrefix); + paramMap.put("indexPrefix", idxPrefix); + paramMap.put("database", database); // 查询当前表中全部acteble创建的索引和唯一约束,也就是名字前缀是actable_和actable_的 Set allIndexAndUniqueNames = createMysqlTablesMapper.findTableIndexByTableName(paramMap); + // 查询当前表的全部外键信息 + + List allForeignKeyModels = createMysqlTablesMapper.findForeignKeyByTableName(tableName, database); +// if(allForeignKeys != null & allForeignKeys.size() > 0){ +// for(ForeignKey m : allForeignKeys){ +// String columnName = createMysqlTablesMapper.describeTableColumn(m.getForeignTable(), m.getCols()); +// m.setForeignColumnName(columnName); +// } +// } +// List allForeignKeyModels = allForeignKeys.stream().map(ForeignKeyModel::new).collect(Collectors.toList()); + // 6. 找出需要删除的索引和唯一约束 List dropIndexAndUniqueFieldList = getDropIndexAndUniqueList(allIndexAndUniqueNames, allFieldList); @@ -266,6 +276,12 @@ public class SysMysqlCreateTableManagerImpl implements SysMysqlCreateTableManage // 8. 找出需要新增的唯一约束 List addUniqueFieldList = getAddUniqueList(allIndexAndUniqueNames, allFieldList); + // 9. 找出需要删除的外键 + List dropForeignKeyList = getDropForeignKeyList(allForeignKeyModels, allFieldList); + + // 10. 找出需要增加的外键 + List allNewForeignKeyList = getNewForeignKeyList(allForeignKeyModels, allFieldList); + if (addFieldList.size() != 0) { baseTableMap.get(Constants.ADD_TABLE_MAP).put(tableName, new TableConfig(addFieldList)); } @@ -281,12 +297,117 @@ public class SysMysqlCreateTableManagerImpl implements SysMysqlCreateTableManage if (dropIndexAndUniqueFieldList.size() != 0) { baseTableMap.get(Constants.DROPINDEXANDUNIQUE_TABLE_MAP).put(tableName, new TableConfig(dropIndexAndUniqueFieldList)); } + if (dropForeignKeyList.size() != 0) { + baseTableMap.get(Constants.DROP_FOREIGN_KEY_TABLE_MAP).put(tableName, new TableConfig(dropForeignKeyList)); + } if (addIndexFieldList.size() != 0) { baseTableMap.get(Constants.ADDINDEX_TABLE_MAP).put(tableName, new TableConfig(addIndexFieldList)); } if (addUniqueFieldList.size() != 0) { baseTableMap.get(Constants.ADDUNIQUE_TABLE_MAP).put(tableName, new TableConfig(addUniqueFieldList)); } + if (allNewForeignKeyList.size() != 0) { + baseTableMap.get(Constants.FOREIGN_MAP).put(tableName, new TableConfig(allNewForeignKeyList)); + } + } + + private List getNewForeignKeyList(List currentKeys, List allFieldList) { + List newForeignKeyList = new ArrayList(); + if (null == allFieldList || allFieldList.size() == 0) { + return newForeignKeyList; + } + List newForeignKeys = new ArrayList(); + for (Object obj : allFieldList) { + CreateTableParam createTableParam = (CreateTableParam) obj; + if(createTableParam.getForeignTable() == null || createTableParam.getForeignColumn() == null){ + continue; + } + + String newModelForeignKeyName = createTableParam.getForeignKeyName() == null ? createTableParam.getFieldName() + "_FK" : createTableParam.getForeignKeyName(); + String newForeignTable = createTableParam.getForeignTable(); + String newForeignColumn = createTableParam.getForeignColumn(); + String newColumn = createTableParam.getFieldName(); + String updateAction = createTableParam.getUpdateAction() == null ? UpdateAction.RESTRICT : createTableParam.getUpdateAction(); + String deleteAction = createTableParam.getFieldName() == null ? DeleteAction.RESTRICT : createTableParam.getDeleteAction(); + + ForeignKeyModel model = new ForeignKeyModel( + newColumn, + updateAction, + deleteAction, + newForeignTable, + newModelForeignKeyName, + newForeignColumn + ); + + newForeignKeys.add(model); + } + for (ForeignKeyModel string : newForeignKeys) { + if (!currentKeys.contains(string)) { + newForeignKeyList.add(string); + } + } + return newForeignKeyList; + } + + private List getDropForeignKeyList(List allForeignKeys, List allFieldList) { + List dropIndexAndUniqueFieldList = new ArrayList(); + if (null == allForeignKeys || allForeignKeys.size() == 0) { + return dropIndexAndUniqueFieldList; + } + List currentModelIndexAndUnique = new ArrayList(); + for (Object obj : allFieldList) { + CreateTableParam createTableParam = (CreateTableParam) obj; + if(createTableParam.getForeignTable() == null || createTableParam.getForeignColumn() == null){ + continue; + } + + String currentModelForeignKeyName = createTableParam.getForeignKeyName() == null ? createTableParam.getFieldName() + "_FK" : createTableParam.getForeignKeyName(); + String currentModelForeignTable = createTableParam.getForeignTable(); + String currentModelForeignColumn = createTableParam.getForeignColumn(); + String currentModelColumn = createTableParam.getFieldName(); + String updateAction = createTableParam.getUpdateAction() == null ? UpdateAction.NO_ACTION : createTableParam.getUpdateAction(); + String deleteAction = createTableParam.getFieldName() == null ? DeleteAction.NO_ACTION : createTableParam.getDeleteAction(); + + ForeignKeyModel model = new ForeignKeyModel( + currentModelColumn, + updateAction, + deleteAction, + currentModelForeignTable, + currentModelForeignKeyName, + currentModelForeignColumn + ); + + currentModelIndexAndUnique.add(model); + } + for (ForeignKeyModel string : allForeignKeys) { + if (!currentModelIndexAndUnique.contains(string)) { + dropIndexAndUniqueFieldList.add(string); + } + } + return dropIndexAndUniqueFieldList; + } + + private List getForeignKey(List allFieldList) { + List allForeignKeyList = new ArrayList(); +// if (null == allIndexAndUniqueNames) { +// allIndexAndUniqueNames = new HashSet(); +// } + for (Object obj : allFieldList) { + CreateTableParam createTableParam = (CreateTableParam) obj; + if (null != createTableParam.getForeignColumn() && null != createTableParam.getForeignTable()) { + String newModelForeignKeyName = createTableParam.getForeignKeyName() == null ? createTableParam.getFieldName() + "_FK" : createTableParam.getForeignKeyName(); + ForeignKeyModel model = new ForeignKeyModel( + createTableParam.getFieldName(), + createTableParam.getUpdateAction(), + createTableParam.getDeleteAction(), + createTableParam.getForeignTable(), + newModelForeignKeyName, + createTableParam.getForeignColumn() + ); + allForeignKeyList.add(model); + } + } + return allForeignKeyList; } /** @@ -625,6 +746,15 @@ public class SysMysqlCreateTableManagerImpl implements SysMysqlCreateTableManage param.setFiledUniqueValue( uniqueValue.length == 0 ? Arrays.asList(ColumnUtils.getColumnName(field,clas)) : Arrays.asList(uniqueValue)); } + + Foreign foreign = field.getAnnotation(Foreign.class); + if (null != foreign ) { + param.setForeignTable(foreign.foreignTable()); + param.setForeignColumn(foreign.foreignColumn()); + param.setDeleteAction(foreign.deleteAction()); + param.setUpdateAction(foreign.updateAction()); + } + // 获取当前字段的@IgnoreUpdate注解 IgnoreUpdate ignoreUpdate = field.getAnnotation(IgnoreUpdate.class); if (null != ignoreUpdate){ @@ -715,6 +845,8 @@ public class SysMysqlCreateTableManagerImpl implements SysMysqlCreateTableManage modifyTableCommentByMap(baseTableMap.get(Constants.MODIFY_TABLE_PROPERTY_MAP)); // 6. 修改字段类型等 modifyFieldsByMap(baseTableMap.get(Constants.MODIFY_TABLE_MAP)); + // 7. 删除外键 + dropForeignKeyByMap(baseTableMap.get(Constants.DROP_FOREIGN_KEY_TABLE_MAP)); } // 7. 添加新的字段 @@ -726,6 +858,50 @@ public class SysMysqlCreateTableManagerImpl implements SysMysqlCreateTableManage // 9. 创建约束 addUniqueByMap(baseTableMap.get(Constants.ADDUNIQUE_TABLE_MAP)); + // 10. 创建外键关系 + addForeignKey(baseTableMap.get(Constants.FOREIGN_MAP)); + + } + + + /** + * 删除外键 + * @param foreignKeyMap + */ + private void dropForeignKeyByMap(Map foreignKeyMap) { + if (foreignKeyMap.size() > 0) { + for (Entry entry : foreignKeyMap.entrySet()) { + for (Object obj : entry.getValue().getList()) { + Map map = new HashMap(); + map.put(entry.getKey(), obj); + ForeignKeyModel model = (ForeignKeyModel) obj; + log.info("开始删除表" + entry.getKey() + "中的外键" + model.getForeignKeyName()); + createMysqlTablesMapper.dropTableForeign(map); + log.info("完成删除表" + entry.getKey() + "中的外键" + model.getForeignKeyName()); + } + } + } + } + + + /** + * 根据map结构创建索引 + * @param foreignMap + * 用于创建索引和唯一约束 + */ + private void addForeignKey(Map foreignMap) { + if (foreignMap.size() > 0) { + for (Entry entry : foreignMap.entrySet()) { + for (Object obj : entry.getValue().getList()) { + Map map = new HashMap(); + map.put(entry.getKey(), obj); + ForeignKeyModel fieldProperties = (ForeignKeyModel) obj; + log.info("开始创建表" + entry.getKey() + "中的外键" + fieldProperties.getForeignKeyName()); + createMysqlTablesMapper.addTableForeign(map); + log.info("完成创建表" + entry.getKey() + "中的外键" + fieldProperties.getForeignKeyName()); + } + } + } } /** diff --git a/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/mapping/system/CreateMysqlTablesMapper.xml b/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/mapping/system/CreateMysqlTablesMapper.xml index 1b05bce..e4017f0 100644 --- a/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/mapping/system/CreateMysqlTablesMapper.xml +++ b/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/mapping/system/CreateMysqlTablesMapper.xml @@ -240,8 +240,13 @@ DROP TABLE IF EXISTS `${tableName}`; + + + - select index_name from information_schema.statistics where @@ -262,6 +267,61 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/spring/ActableMapperRegistrar.java b/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/spring/ActableMapperRegistrar.java new file mode 100644 index 0000000..9b649ce --- /dev/null +++ b/mybatis-enhance-actable/src/main/java/com/gitee/sunchenbin/mybatis/actable/spring/ActableMapperRegistrar.java @@ -0,0 +1,154 @@ +package com.gitee.sunchenbin.mybatis.actable.spring; + +import org.mybatis.spring.annotation.MapperScan; +import org.mybatis.spring.annotation.MapperScans; +import org.mybatis.spring.mapper.MapperFactoryBean; +import org.mybatis.spring.mapper.MapperScannerConfigurer; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.support.AbstractBeanDefinition; +import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.beans.factory.support.BeanNameGenerator; +import org.springframework.context.ResourceLoaderAware; +import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; +import org.springframework.core.annotation.AnnotationAttributes; +import org.springframework.core.io.ResourceLoader; +import org.springframework.core.type.AnnotationMetadata; +import org.springframework.util.ClassUtils; +import org.springframework.util.StringUtils; + +import java.lang.annotation.Annotation; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 由于@MapperScan在@Import中无法使用 + * 使得 @MapperScan("com.gitee.sunchenbin.mybatis.actable.dao.*") 无法生效 + * + * 使用该类指向特定的 com.gitee.sunchenbin.mybatis.actable.dao.* 手动注入Mapper接口 + */ +public class ActableMapperRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware { + + /** + * {@inheritDoc} + * + * @deprecated Since 2.0.2, this method not used never. + */ + @Override + @Deprecated + public void setResourceLoader(ResourceLoader resourceLoader) { + // NOP + } + + /** + * {@inheritDoc} + */ + @Override + public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { +// AnnotationAttributes mapperScanAttrs = AnnotationAttributes +// .fromMap(importingClassMetadata.getAnnotationAttributes(MapperScan.class.getName())); +// if (mapperScanAttrs != null) { + registerBeanDefinitions(importingClassMetadata, registry, + generateBaseBeanName(importingClassMetadata, 0)); +// } + } + + void registerBeanDefinitions(AnnotationMetadata annoMeta, + BeanDefinitionRegistry registry, String beanName) { + + BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MapperScannerConfigurer.class); + builder.addPropertyValue("processPropertyPlaceHolders", true); + +// Class annotationClass = annoAttrs.getClass("annotationClass"); +// if (!Annotation.class.equals(annotationClass)) { +// builder.addPropertyValue("annotationClass", Annotation.class); +// } + +// Class markerInterface = annoAttrs.getClass("markerInterface"); +// if (!Class.class.equals(markerInterface)) { +// builder.addPropertyValue("markerInterface", markerInterface); +// } + +// Class generatorClass = annoAttrs.getClass("nameGenerator"); +// if (!BeanNameGenerator.class.equals(generatorClass)) { +// builder.addPropertyValue("nameGenerator", BeanUtils.instantiateClass(BeanNameGenerator.class)); +// } + +// Class mapperFactoryBeanClass = annoAttrs.getClass("factoryBean"); +// if (!MapperFactoryBean.class.equals(mapperFactoryBeanClass)) { +// builder.addPropertyValue("mapperFactoryBeanClass", mapperFactoryBeanClass); +// } + +// String sqlSessionTemplateRef = annoAttrs.getString("sqlSessionTemplateRef"); +// if (StringUtils.hasText(sqlSessionTemplateRef)) { +// builder.addPropertyValue("sqlSessionTemplateBeanName", annoAttrs.getString("sqlSessionTemplateRef")); +// } + +// String sqlSessionFactoryRef = annoAttrs.getString("sqlSessionFactoryRef"); +// if (StringUtils.hasText(sqlSessionFactoryRef)) { +// builder.addPropertyValue("sqlSessionFactoryBeanName", annoAttrs.getString("sqlSessionFactoryRef")); +// } + + List basePackages = new ArrayList<>(); + basePackages.add("com.gitee.sunchenbin.mybatis.actable.dao.*"); + +// basePackages.addAll(Arrays.stream(annoAttrs.getStringArray("basePackages")).filter(StringUtils::hasText) +// .collect(Collectors.toList())); + +// basePackages.addAll(Arrays.stream(annoAttrs.getClassArray("basePackageClasses")).map(ClassUtils::getPackageName) +// .collect(Collectors.toList())); + + if (basePackages.isEmpty()) { + basePackages.add(getDefaultBasePackage(annoMeta)); + } + +// String lazyInitialization = annoAttrs.getString("lazyInitialization"); +// if (StringUtils.hasText(lazyInitialization)) { +// builder.addPropertyValue("lazyInitialization", lazyInitialization); +// } + +// String defaultScope = annoAttrs.getString("defaultScope"); +// if (!AbstractBeanDefinition.SCOPE_DEFAULT.equals(defaultScope)) { +// builder.addPropertyValue("defaultScope", defaultScope); +// } + + builder.addPropertyValue("basePackage", StringUtils.collectionToCommaDelimitedString(basePackages)); + + registry.registerBeanDefinition(beanName, builder.getBeanDefinition()); + + } + + private static String generateBaseBeanName(AnnotationMetadata importingClassMetadata, int index) { + return importingClassMetadata.getClassName() + "#" + ActableMapperRegistrar.class.getSimpleName() + "#" + index; + } + + private static String getDefaultBasePackage(AnnotationMetadata importingClassMetadata) { + return ClassUtils.getPackageName(importingClassMetadata.getClassName()); + } + +// /** +// * A {@link ActableMapperRegistrar} for {@link MapperScans}. +// * +// * @since 2.0.0 +// */ +// static class RepeatingRegistrar extends ActableMapperRegistrar { +// /** +// * {@inheritDoc} +// */ +// @Override +// public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { +// AnnotationAttributes mapperScansAttrs = AnnotationAttributes +// .fromMap(importingClassMetadata.getAnnotationAttributes(MapperScans.class.getName())); +// if (mapperScansAttrs != null) { +// AnnotationAttributes[] annotations = mapperScansAttrs.getAnnotationArray("value"); +// for (int i = 0; i < annotations.length; i++) { +// registerBeanDefinitions(importingClassMetadata, registry, +// generateBaseBeanName(importingClassMetadata, i)); +// } +// } +// } +// } + +} -- Gitee