21.1. Schema 自动生成(Automatic schema generation)
可以从你的映射文件使用一个 Hibernate 工具生成 DDL。生成的 schema 包含有对实体和集合类表的完整性引用约束(主键和外键)。涉及到的标示符生成器所需的表和 sequence 也会同时生成。
在使用这个工具的时候,你必须 通过
hibernate.dialet
属性指定一个 SQL方言(Dialet)
,因为 DDL 是与供应商高度相关的。
首先,要定制你的映射文件,来改善生成的 schema。下章将涵盖 schema 定制。
21.1.1. 对 schema 定制化(Customizing the schema)
很多 Hibernate 映射元素定义了可选的
length
、precision
或者 scale
属性。你可以通过这个属性设置字段的长度、精度、小数点位数。
<property name="zip" length="5"/>
<property name="balance" precision="12" scale="2"/>
有些 tag 还接受
not-null
属性(用来在表字段上生成 NOT NULL
约束)和 unique
属性(用来在表字段上生成 UNIQUE
约束)。
<many-to-one name="bar" column="barId" not-null="true"/>
<element column="serialNumber" type="long" not-null="true" unique="true"/>
unique-key
属性可以对成组的字段指定一个唯一键约束(unique key constraint)。目前,unique-key
属性指定的值在生成 DDL 时并不会被当作这个约束的名字,它们只是在用来在映射文件内部用作区分的。
<many-to-one name="org" column="orgId" unique-key="OrgEmployeeId"/>
<property name="employeeId" unique-key="OrgEmployee"/>
index
属性会用对应的字段(一个或多个)生成一个 index,它指出了这个 index 的名字。如果多个字段对应的 index 名字相同,就会生成包含这些字段的 index。
<property name="lastName" index="CustName"/>
<property name="firstName" index="CustName"/>
foreign-key
属性可以用来覆盖任何生成的外键约束的名字。
<many-to-one name="bar" column="barId" foreign-key="FKFooBar"/>
很多映射元素还接受
<column>
子元素。这在定义跨越多字段的类型时特别有用。
<property name="name" type="my.customtypes.Name"/>
<column name="last" not-null="true" index="bar_idx" length="30"/>
<column name="first" not-null="true" index="bar_idx" length="20"/>
<column name="initial"/>
</property
>
default
属性为字段指定一个默认值(在保存被映射的类的新实例之前,你应该将同样的值赋于对应的属性)。
<property name="credits" type="integer" insert="false">
<column name="credits" default="10"/>
</property
>
<version name="version" type="integer" insert="false">
<column name="version" default="0"/>
</property
>
sql-type
属性允许用户覆盖默认的 Hibernate 类型到 SQL 数据类型的映射。
<property name="balance" type="float">
<column name="balance" sql-type="decimal(13,3)"/>
</property
>
check
属性允许用户指定一个约束检查。
<property name="foo" type="integer">
<column name="foo" check="foo
> 10"/>
</property
>
<class name="Foo" table="foos" check="bar < 100.0">
...
<property name="bar" type="float"/>
</class
>
下表总结了这些可选属性:
表 21.1. 总结
属性(Attribute) 值(Values) 解释(Interpretation) length
数字 字段长度 precision
数字 精度(decimal precision) scale
数字 小数点位数(decimal scale) not-null
true|false
指明字段是否应该是非空的 unique
true|false
指明是否该字段具有惟一约束 index
index_name
指明一个(多字段)的索引(index)的名字 unique-key
unique_key_name
指明多字段惟一约束的名字(参见上面的说明) foreign-key
foreign_key_name
指明一个外键的名字,它是为关联生成的,或者是为 <one-to-one>
, <many-to-one>
, <key>
, or <many-to-many>
映射元素。注意 inverse="true"
会被 SchemaExport
忽略。 sql-type
SQL column type
覆盖默认的字段类型(只能用于 <column>
属性) default
SQL 表达式 为字段指定默认值 check
SQL 表达式 对字段或表加入 SQL 约束检查
<comment>
元素可以让你在生成的 schema 中加入注释。
<class name="Customer" table="CurCust">
<comment
>Current customers only</comment>
...
</class
>
<property name="balance">
<column name="bal">
<comment
>Balance in USD</comment>
</column>
</property
>
结果是在生成的 DDL 中包含 comment on table
或者 comment on column
语句(假若支持的话)。
21.1.2. 运行该工具
SchemaExport
工具把 DDL 脚本写到标准输出,同时/或者执行 DDL 语句。
下表显示了
SchemaExport
命令行选项
java -cp
hibernate_classpaths org.hibernate.tool.hbm2ddl.SchemaExport
options mapping_files
表 21.2. SchemaExport
命令行选项
选项 描述 --quiet
不要把脚本输出到 stdout --drop
只进行 drop tables 的步骤 --create
只创建表 --text
不执行在数据库中运行的步骤 --output=my_schema.ddl
把输出的 ddl 脚本输出到一个文件 --naming=eg.MyNamingStrategy
选择 NamingStrategy
--config=hibernate.cfg.xml
从 XML 文件读入 Hibernate 配置 --properties=hibernate.properties
从文件读入数据库属性 --format
把脚本中的 SQL 语句对齐和美化 --delimiter=;
为脚本设置行结束符
你甚至可以在你的应用程序中嵌入 SchemaExport
工具:
Configuration cfg = ....;
new SchemaExport(cfg).create(false, true);
21.1.3. 属性(Properties)
可以通过如下方式指定数据库属性:
通过
-D
<property> 系统参数在
hibernate.properties
文件中位于一个其它名字的 properties 文件中,然后用
--properties
参数指定
所需的参数包括:
表 21.3. SchemaExport 连接属性
属性名 描述 hibernate.connection.driver_class
jdbc driver class hibernate.connection.url
jdbc url hibernate.connection.username
database user hibernate.connection.password
user password hibernate.dialect
方言(dialect)
21.1.4. 使用 Ant(Using Ant)
你可以在你的 Ant build 脚本中调用
SchemaExport
:
<target name="schemaexport">
<taskdef name="schemaexport"
classname="org.hibernate.tool.hbm2ddl.SchemaExportTask"
classpathref="class.path"/>
<schemaexport
properties="hibernate.properties"
quiet="no"
text="no"
drop="no"
delimiter=";"
output="schema-export.sql">
<fileset dir="src">
<include name="**/*.hbm.xml"/>
</fileset>
</schemaexport>
</target
>
21.1.5. 对 schema 的增量更新(Incremental schema updates)
SchemaUpdate
工具对已存在的 schema 采用"增量"方式进行更新。注意 SchemaUpdate
严重依赖于 JDBC metadata API,所以它并非对所有 JDBC 驱动都有效。
java -cp
hibernate_classpaths org.hibernate.tool.hbm2ddl.SchemaUpdate
options mapping_files
表 21.4. SchemaUpdate
命令行选项
选项 描述 --quiet
不要把脚本输出到 stdout --text
不把脚本输出到数据库 --naming=eg.MyNamingStrategy
选择 NamingStrategy
--properties=hibernate.properties
从文件读入数据库属性 --config=hibernate.cfg.xml
指定一个 .cfg.xml
文件
你可以在你的应用程序中嵌入 SchemaUpdate
工具:
Configuration cfg = ....;
new SchemaUpdate(cfg).execute(false);
21.1.6. 用 Ant 来增量更新 schema(Using Ant for incremental schema updates)
你可以在 Ant 脚本中调用
SchemaUpdate
:
<target name="schemaupdate">
<taskdef name="schemaupdate"
classname="org.hibernate.tool.hbm2ddl.SchemaUpdateTask"
classpathref="class.path"/>
<schemaupdate
properties="hibernate.properties"
quiet="no">
<fileset dir="src">
<include name="**/*.hbm.xml"/>
</fileset>
</schemaupdate>
</target
>
21.1.7. Schema 校验
SchemaValidator
工具会比较数据库现状是否与映射文档“匹配”。注意,SchemaValidator
严重依赖于 JDBC 的 metadata API,因此不是对所有的 JDBC 驱动都适用。这一工具在测试的时候特别有用。
java -cp
hibernate_classpaths org.hibernate.tool.hbm2ddl.SchemaValidator
options mapping_files
下表显示了
SchemaValidator
命令行参数:
表 21.5. SchemaValidator
命令行参数
选项 描述 --naming=eg.MyNamingStrategy
选择 NamingStrategy
--properties=hibernate.properties
从文件读入数据库属性 --config=hibernate.cfg.xml
指定一个 .cfg.xml
文件
你可以在你的应用程序中嵌入 SchemaValidator
:
Configuration cfg = ....;
new SchemaValidator(cfg).validate();
21.1.8. 使用 Ant 进行 schema 校验
你可以在 Ant 脚本中调用
SchemaValidator
:
<target name="schemavalidate">
<taskdef name="schemavalidator"
classname="org.hibernate.tool.hbm2ddl.SchemaValidatorTask"
classpathref="class.path"/>
<schemavalidator
properties="hibernate.properties">
<fileset dir="src">
<include name="**/*.hbm.xml"/>
</fileset>
</schemavalidator>
</target
>