我有一个Java Hibernate项目,我在架构迁移时遇到异常。为了更清楚地理解,已经创建了测试项目:https://Li_Ion@bitbucket.org/Li_Ion/hibernatetest。
它由带有生成ID列的 AbstractEntity 组成。所有其他实体都从中继承。
import javax.persistence.*;
@MappedSuperclass
public abstract class AbstractEntity {
@TableGenerator(
name="entityGen",
table="Sequence",
pkColumnName="SeqName",
pkColumnValue="SeqValue",
valueColumnName="SeqCount",
allocationSize=1)
@Id
@GeneratedValue(strategy=GenerationType.TABLE, generator="entityGen")
private Long id;
}
BaseEntity 包含基本业务逻辑(此测试项目为空)。
import java.io.Serializable;
import javax.persistence.Entity;
@Entity
public class BaseEntity extends AbstractEntity implements Serializable {
private static final long serialVersionUID = 7986579000111260735L;
}
SubEntity 包含一些额外逻辑,它存储在同一个表中, BaseEntity ,并且出于某些目的,需要来自 LinkedEntity <的链接(外键) /强>
import java.util.SortedSet;
import java.util.TreeSet;
import javax.persistence.*;
import org.hibernate.annotations.SortNatural;
@Entity
public class SubEntity extends BaseEntity {
private static final long serialVersionUID = -5385038491074771899L;
@SortNatural
@OneToMany(fetch= FetchType.LAZY, mappedBy = "baseEntity", cascade= CascadeType.REMOVE)
private SortedSet<LinkedEntity> linkedEntities = new TreeSet<>();
}
另一方面, LinkedEntity 还需要链接(外键)到 BaseEntity 。
import java.io.Serializable;
import javax.persistence.*;
@Entity
public class LinkedEntity extends AbstractEntity implements Serializable {
private static final long serialVersionUID = -862211573175996002L;
@ManyToOne(fetch = FetchType.LAZY)
protected BaseEntity baseEntity;
}
我的 persistence.xml 是:
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
<persistence-unit name="hibernate-test">
<properties>
<!-- Database connection settings -->
<property name="javax.persistence.jdbc.driver" value="org.postgresql.Driver"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
<property name="jadira.usertype.autoRegisterUserTypes" value="true"/>
<property name="jadira.usertype.databaseZone" value="jvm"/>
<property name="jadira.usertype.javaZone" value="jvm"/>
<property name="javax.persistence.jdbc.url"
value="jdbc:postgresql://localhost:5432/hibernatetest?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8" />
<property name="javax.persistence.jdbc.user" value="test" />
<property name="javax.persistence.jdbc.password" value="test" />
<property name="hibernate.show_sql" value="false" />
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.hbm2ddl.auto" value="update" />
<property name="javax.persistence.validation.mode" value="none" />
</properties>
</persistence-unit>
</persistence>
最后, Main 类包含对运行模式迁移的调用:
import javax.persistence.Persistence;
public class Main {
static public void main(String args[]) {
Persistence.createEntityManagerFactory("hibernate-test");
}
}
然后我运行这个测试项目(在空数据库上),我得到一个例外:
Exception in thread "main" javax.persistence.PersistenceException: [PersistenceUnit: hibernate-test] Unable to build Hibernate SessionFactory
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.persistenceException(EntityManagerFactoryBuilderImpl.java:877)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:805)
at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory(HibernatePersistenceProvider.java:58)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:55)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:39)
at org.Main.main(Main.java:8)
Caused by: org.hibernate.tool.schema.spi.SchemaManagementException: Unable to execute schema management to JDBC target [alter table LinkedEntity add constraint FKcsuu8w377ufaw32jb0s42dgny foreign key (baseEntity_id) references BaseEntity]
at org.hibernate.tool.schema.internal.TargetDatabaseImpl.accept(TargetDatabaseImpl.java:59)
at org.hibernate.tool.schema.internal.SchemaMigratorImpl.applySqlString(SchemaMigratorImpl.java:420)
at org.hibernate.tool.schema.internal.SchemaMigratorImpl.applySqlStrings(SchemaMigratorImpl.java:409)
at org.hibernate.tool.schema.internal.SchemaMigratorImpl.applyForeignKeys(SchemaMigratorImpl.java:374)
at org.hibernate.tool.schema.internal.SchemaMigratorImpl.doMigrationToTargets(SchemaMigratorImpl.java:190)
at org.hibernate.tool.schema.internal.SchemaMigratorImpl.doMigration(SchemaMigratorImpl.java:60)
at org.hibernate.tool.hbm2ddl.SchemaUpdate.execute(SchemaUpdate.java:129)
at org.hibernate.tool.hbm2ddl.SchemaUpdate.execute(SchemaUpdate.java:97)
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:481)
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:444)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:802)
... 4 more
Caused by: org.postgresql.util.PSQLException: ERROR: constraint "fkcsuu8w377ufaw32jb0s42dgny" for relation "linkedentity" already exists
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2270)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1998)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:255)
at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:570)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:406)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeUpdate(AbstractJdbc2Statement.java:334)
at org.hibernate.tool.schema.internal.TargetDatabaseImpl.accept(TargetDatabaseImpl.java:56)
... 14 more
我使用PostgreSQL 9.4.5,Java 8和Hibernate 5.0.2。所有其他信息都可以在测试项目中找到:https://Li_Ion@bitbucket.org/Li_Ion/hibernatetest。
我做错了什么?提前致谢
抱歉我的英文