Skip to content

生成DDL

生成DDL语句是huiche-ddl模块提供的一项辅助功能, 它是独立于huiche主体功能的, 可选使用, 主要有生成建表语句和对比表结构差异2个功能

使用前您需要手动引入huiche-ddl模块,因为其是可选功能,使用huiche-spring-boot-starter也不会默认引入

xml
<dependency>
    <groupId>org.huiche</groupId>
    <artifactId>huiche-ddl</artifactId>
    <!--如果使用在测试模块可以设置为test-->
    <scope>test</scope>
</dependency>

定义表结构细节

使用@org.huiche.core.annotation.Table@org.huiche.core.annotation.Column注解可以定义表和列的相关细节,可详细了解

表名和列名可以通过@Table@Column, 但默认会走NamingStrategy进行处理

了解自定义命名策略

生成建表语句

使用org.huiche.ddl.DDL类进行操作,调用ddl方法,会返回List<String>即生成的DDL语句列表,可以把代码放到一个单独模块编写,也可以写在test

java
// 创建连接提供者
// 可以直接使用jdbc-url,user,pwd来创建一个简单的ConnectionProvider
ConnectionProvider connectionProvider = ConnectionProvider.of("jdbc-url","user","pwd");
// 如果使用spring-boot-test环境,您可以注入JdbcExecutor对象来获取自动装配的connectionProvider
@Autowired
private JdbcExecutor executor;
connectionProvider = executor.configuration().connectionProvider();
// 创建DDL实例
DDL ddl = new DDL(executor.configuration().connectionProvider());
// ddl.enumBy() 可选调整默认的枚举取值方式,您也可以从executor.configuration().enumBy()获取
// ddl.dialect() 可选传入自定义的DDLDialect方言,默认使用ConnectionProvider解析
// ddl.setTypeMapping() 可选传入自定义的类型映射
// ddl.execute(true) 可选 直接执行生成的DDL语句,默认不会执行,只会输出到控制台和作为结果返回
// ddl.consumer() 可选 传入一个DDL语句的消费者,自行消费处理生成的DDL语句

// 直接指定实体类生成,对类没有任何要求
List<String> ddls = ddl.ddl(Artist.class,Song.class);
// 指定包名扫描生成, 需要对应实体类添加了@Table注解,否则无法扫描到
// 需要具有对应模块的依赖,否则也无法扫描到
ddl.ddl("com.demo.entity","com.demo.uaa.entity");

对比表结构差异

使用org.huiche.ddl.DDL类进行操作,调用compare方法,会返回List<String>即生成的DDL语句列表,可以把代码放到一个单独模块编写,也可以写在test

对比逻辑

  • 单向对比,从Java侧对比数据库侧, 不会删除数据库侧多余的内容,比如多余的库,表,字段,索引等等,均不会生成相关删除语句
  • java侧不进行普通索引的管理,仅处理主键和单列唯一和非空约束,所以数据库侧所有的普通索引都会被忽略,不会进行删除或添加
  • 列注释和列默认值, 如果java侧没有指定, 不会对数据库侧进行调整,仅java侧指定时,才会进行对比,如果有差异,会生成修改语句
  • 列长度,精度等, 如果java侧没有指定(默认-1), 不会对数据库侧进行调整,仅java侧指定时,才会进行对比,如果有差异,会生成修改语句
  • java侧主键与数据库侧主键不同时,会先删除数据库侧原有主键,然后重新添加新的主键
  • java侧列唯一(仅单列)与数据库侧不同时,会进行删除或添加操作
  • java侧nullable与数据库侧不同时,会进行删除或添加操作
  • 列自增除了MySQL和MariaDB外,其他数据库不支持进行调整,如果修改自增,需要你手动处理(基本需要重建表)
  • SQLite不支持绝大部分的表结构调整

对比表结构较为复杂,可能因现有结构,数据等冲突, 无法保证生成的语句一定可以执行成功

创建DDL实例和配置与建表完全一致,仅需要将最终调用改为compare方法

java
// 直接指定实体类对比,对类没有任何要求
List<String> ddls = ddl.compare(Artist.class,Song.class);
// 指定包名扫描对比, 需要对应实体类添加了@Table注解,否则无法扫描到
// 需要具有对应模块的依赖,否则也无法扫描到
ddl.compare("com.demo.entity","com.demo.uaa.entity");

自定义类型映射

ddl.setTypeMapping() 可以传入一个Map<Class<?>, TypeDef> typeMapping, 来实现自定义的类型映射

  • Class<?> 即需要自定义映射的java类型
  • TypeDef 是需要映射的数据库侧的类型,含长度,精度,其包含type,length,scale三个属性
java
Map<Class<?>, TypeDef> typeMapping = new HashMap<>();
typeMapping.put(Integer.class,new TypeDef("INT"));
typeMapping.put(String.class,new TypeDef("VARCHAR",50));
typeMapping.put(Double.class,new TypeDef("DECIMAL",10,2));
ddl.setTypeMapping(typeMapping);

以上代码,即代表如果实体类中的属性

  • 使用Integer类型时,DDL自动给他生成INT的数据库侧类型
  • 使用String类型时,DDL自动给他生成VARCHAR(50)的数据库侧类型
  • 使用Double类型时,DDL自动给他生成DECIMAL(10,2)的数据库侧类型

注意,自定义映射指定的lengthscale只是默认的,如果在对应属性上通过@Column指定了lengthscale,仍会以注解指定的优先

了解更多DDL生成的细节:DDL说明

了解更多huiche的说明,配置参数,执行逻辑等,点击参考