我想将Liquibase添加到已经使用Hibernate Envers但自动创建数据库表的应用程序。因此,我需要编写 Liquibase 变更集,其中包含我的实体的表和 Envers 所需的表。
下面是变更集:
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<property name="long_type" value="bigint" dbms="postgresql"/>
<property name="long_type" value="long" dbms="h2"/>
<changeSet id="CreateBasicSchema" author="Steven Schwenke">
<createSequence sequenceName="hibernate_sequence" startValue="0" incrementBy="1"/>
<createTable tableName="revinfo">
<column name="rev" type="integer">
<constraints primaryKey="true"/>
</column>
<column name="revtstmp" type="bigint"/>
</createTable>
<createTable tableName="stuff">
<column name="id" type="${long_type}">
<constraints nullable="false" unique="true" primaryKey="true"/>
</column>
<column name="text" type="varchar(36)">
<constraints nullable="false"/>
</column>
</createTable>
<createTable tableName="stuff_aud">
<column name="id" type="${long_type}">
<constraints nullable="false" unique="true" primaryKey="true"/>
</column>
<column name="rev" type="integer">
<constraints referencedTableName="revinfo"
foreignKeyName="fk_brands_stuff_revinfo"
referencedColumnNames="rev"
nullable="false"/>
</column>
<column name="revtype" type="integer">
<constraints nullable="false"/>
</column>
<column name="stuff" type="varchar(36)">
<constraints nullable="true"/>
</column>
</createTable>
</changeSet>
这会导致以下异常:
o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 23502, SQLState: 23502
o.h.engine.jdbc.spi.SqlExceptionHelper : NULL nicht zulässig für Feld "REV"
NULL not allowed for column "REV"; SQL statement:
/* insert org.hibernate.envers.DefaultRevisionEntity */ insert into revinfo (rev, revtstmp) values (null, ?) [23502-200]
org.springframework.dao.DataIntegrityViolationException: could not execute statement ...
经过一番研究,我终于发现了我的错误,并将其作为这个问题的答案发布。希望这有助于其他开发人员遇到相同的异常。
缺少的部分是 revinfo 表的 ID 的简单自动增量:
<createTable tableName="revinfo">
<column name="rev" type="integer" autoIncrement="true">
<constraints primaryKey="true"/>
</column>
<column name="revtstmp" type="bigint"/>
</createTable>
如果没有这个,revinfo 表中的新条目将具有空 ID,这正是异常所说的。
上面 liquibase 代码中的另一个错误是 aud 表的 id 在 id 上有一个主键。这将导致更新实体时出现异常。根据 Vlad Mihalcea 的说法,aud 表应该有一个组合键:
<createTable tableName="stuff_aud">
<column name="id" type="${long_type}">
<constraints nullable="false" />
</column>
<column name="rev" type="integer">
<constraints referencedTableName="revinfo"
foreignKeyName="fk_brands_stuff_revinfo"
referencedColumnNames="rev"
nullable="false"/>
</column>
<column name="revtype" type="integer">
<constraints nullable="false"/>
</column>
<column name="stuff" type="varchar(36)">
<constraints nullable="false"/>
</column>
</createTable>
<addPrimaryKey tableName="stuff_aud" columnNames="id, rev" />