xbatis-ddl-auto 1.0.1 的核心变化很直接:它把 xbatis 实体上的表、字段、主键等元数据拿来生成并执行数据库 DDL,让使用 xbatis 的项目获得接近 JPA ddl-auto=create/update 的体验,但不需要引入 JPA 或 Hibernate 这一整套运行时。
这类工具解决的是一个很具体的问题:业务代码里的实体类已经写了 @Table、@TableId、@TableField、@ColumnDefinition,数据库表结构却还要手写 SQL、维护迁移脚本、同步字段变更。xbatis-ddl-auto 试图把这段重复劳动自动化,尤其适合开发环境、测试环境、原型系统和内部工具。
它复用的是 xbatis 的实体元数据
从摘要看,xbatis-ddl-auto 并不是另起一套注解体系,而是复用 xbatis 已有的实体注解解析结果。
这点很重要。开发者不需要同时维护两套模型:
@Table描述实体对应的表;@TableId描述主键字段;@TableField描述普通字段;@ColumnDefinition描述更细的列定义。
换句话说,实体类既服务于 ORM 映射,也可以作为 DDL 生成的输入。对于已经采用 xbatis 的项目,迁移成本会比引入 Hibernate 的 schema generation 低得多。
一个典型实体可以这样组织,下面示例用于说明实践方式,具体包名和注解属性请以项目实际依赖版本为准:
package com.example.demo.entity;
import cn.xbatis.db.annotations.Table;
import cn.xbatis.db.annotations.TableField;
import cn.xbatis.db.annotations.TableId;
import cn.xbatis.db.annotations.ColumnDefinition;
import java.time.LocalDateTime;
@Table("sys_user")
public class UserEntity {
@TableId
@ColumnDefinition("bigint primary key")
private Long id;
@TableField("username")
@ColumnDefinition("varchar(64) not null")
private String username;
@TableField("email")
@ColumnDefinition("varchar(128)")
private String email;
@TableField("created_at")
@ColumnDefinition("datetime not null")
private LocalDateTime createdAt;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public LocalDateTime getCreatedAt() {
return createdAt;
}
public void setCreatedAt(LocalDateTime createdAt) {
this.createdAt = createdAt;
}
}
需要改造的地方通常集中在实体类:表名、列名、主键、列类型、是否允许为空、默认值等信息要表达清楚。否则自动 DDL 工具只能根据 Java 类型做推断,而推断往往不如显式定义可靠。
create/update 的体验,不等于生产环境随便跑
摘要提到它提供接近 ddl-auto=create/update 的体验。这个定位很清晰:
create更适合临时库、测试库、CI 环境;update更适合开发阶段的增量字段同步;- 生产环境仍然应该保留审核、备份、回滚和变更记录。
自动 DDL 最容易被低估的风险,是“它确实能跑”。一旦它具备执行权限,错误的实体注解、误删字段、类型收窄、默认值变化,都可能变成真实的数据库结构变更。
更稳妥的做法是把自动执行限制在非生产 profile 中。可以这样实践:
# application-dev.yml
spring:
datasource:
url: jdbc:mysql://localhost:3306/demo_dev?useSSL=false&serverTimezone=UTC
username: root
password: root
xbatis:
ddl-auto:
enabled: true
mode: update
entity-packages:
- com.example.demo.entity
# application-prod.yml
xbatis:
ddl-auto:
enabled: false
上面的配置是“可以这样实践”的示意,具体配置项名称需要按 xbatis-ddl-auto 1.0.1 的实际文档调整。原则是固定的:开发环境可以自动建表,生产环境默认关闭。
一个最小可改造的 Spring Boot 接入示例
如果你的项目已经是 Spring Boot + xbatis,可以按下面方式搭一个最小验证工程。依赖坐标请替换为你实际使用的 xbatis 与 xbatis-ddl-auto 版本。
<!-- pom.xml 片段:请按实际发布坐标调整 groupId/artifactId/version -->
<dependencies>
<dependency>
<groupId>cn.xbatis</groupId>
<artifactId>xbatis-spring-boot-starter</artifactId>
<version>请替换为项目使用版本</version>
</dependency>
<dependency>
<groupId>cn.xbatis</groupId>
<artifactId>xbatis-ddl-auto</artifactId>
<version>1.0.1</version>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
本地用 Docker 起一个 MySQL,便于反复验证建表结果:
docker run --name xbatis-ddl-demo \
-e MYSQL_ROOT_PASSWORD=root \
-e MYSQL_DATABASE=demo_dev \
-p 3306:3306 \
-d mysql:8.0
# 查看容器是否启动
docker ps --filter name=xbatis-ddl-demo
应用启动后,可以检查表是否生成:
docker exec -it xbatis-ddl-demo mysql -uroot -proot demo_dev -e "show tables;"
docker exec -it xbatis-ddl-demo mysql -uroot -proot demo_dev -e "show create table sys_user\G"
如果你在实体里新增字段,例如增加 status:
@TableField("status")
@ColumnDefinition("tinyint not null default 1")
private Integer status;
再次启动应用后,update 模式理论上应该尝试补齐数据库列。验证命令:
docker exec -it xbatis-ddl-demo mysql -uroot -proot demo_dev -e "desc sys_user;"
这套验证流程的价值在于:你可以在接入前明确看到实体注解如何影响真实 DDL,而不是只相信启动日志。
适合放在哪里用
xbatis-ddl-auto 的边界应该划清楚。它适合让开发者快速从实体得到表结构,也适合让测试环境自动准备 schema。它不适合替代所有数据库变更管理。
建议采用时做一个小清单:
- 只在
dev、test、ci等环境开启自动执行; - 实体字段尽量使用
@ColumnDefinition明确数据库类型; - 每次升级 xbatis-ddl-auto 前,在临时库跑一遍 DDL 验证;
- 对生产库继续使用 Flyway、Liquibase 或人工审核 SQL;
- 对删除字段、修改字段类型、索引变化保持人工确认。
如果团队已经在用 xbatis,这个工具的吸引力在于“顺手”:它利用现有实体元数据,把建表这件事从手工 SQL 推向自动化。但自动化 DDL 的权限很重,越接近生产环境,越要把开关、日志、审核和回滚路径准备好。