通常的做法是将相同的实体映射两次甚至三次,每次都需要处理所需的列子集。我发现使用Hibernate 3.5.1
,每次映射同一个表的两个实体中存在@ManyToOne
或@OneToMany
时,外键会被创建两次。这对MySQL和SQL Server没有影响,但Oracle拒绝第二个创建语句。
以下是一个例子:
@Entity
@javax.persistence.SequenceGenerator(name = "SEQ_STORE", sequenceName = "SEQ_ENTITY")
@Table(name = "ENTITIES")
class Entity {
//All columns
//And then.....
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "BRIDGE_TABLE", joinColumns = { @JoinColumn(name = "ENTITY_ID") }, inverseJoinColumns = { @JoinColumn(name = "ROLE_ID") })
@OrderBy("id DESC")
private Set<Role> roles = new HashSet<Roles>();
}
@Entity
@javax.persistence.SequenceGenerator(name = "SEQ_STORE", sequenceName = "SEQ_ENTITY")
@Table(name = "ENTITIES")
class EntityListItem {
//Only a subset of the previous columns
//And then.....
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "BRIDGE_TABLE", joinColumns = { @JoinColumn(name = "ENTITY_ID") }, inverseJoinColumns = { @JoinColumn(name = "ROLE_ID") })
@OrderBy("id DESC")
private Set<Role> roles = new HashSet<Roles>();
}
目前,Role
的设计不能导航到Entity
(否则我猜会有4个外键)。
以下是Hibernate发布的声明:
create table BRIDGE_TABLE (ENTITY_ID number(19,0) not null, ROLE_ID varchar2(60 char) not null, primary key (ENTITY_ID, ROLE_ID)); //Creates the table
alter table BRIDGE_TABLE add constraint FK47CFB9F0B068EF3F foreign key (ENTITY_ID) references ENTITIES;
alter table BRIDGE_TABLE add constraint FK47CFB9F0B068EF3F foreign key (ENTITY_ID) references ENTITIES;
我不确定这是否是一个Hibernate错误。我们目前无法迁移到Hibernate 4.可以通过代码修复它还是需要一个新的Hibernate版本?
答案 0 :(得分:0)
我做了一个解决方法:
@ForeignKey
注释(例如@ForeignKey(name = "FK_TO_ENTITY", inverseName = "FK_TO_ROLE")
)LocalSessionFactoryBean
:@override
public void createDatabaseSchema() throws DataAccessException
{
logger.info("Creating database schema for Hibernate SessionFactory");
SessionFactory sessionFactory = getSessionFactory();
final Dialect dialect = ((SessionFactoryImplementor) sessionFactory).getDialect();
final LinkedHashSet<String> sql = new LinkedHashSet<String>();
for (String query : getConfiguration().generateSchemaCreationScript(dialect))
sql.add(query);
HibernateTemplate hibernateTemplate = new HibernateTemplate(sessionFactory);
hibernateTemplate.execute(new HibernateCallback<Void>()
{
@Override
public Void doInHibernate(Session session) throws SQLException
{
session.doWork(new Work()
{
@Override
public void execute(Connection conn) throws SQLException
{
PhoenixAnnotationSessionFactoryBean.this.executeSchemaScript(conn, sql.toArray(new String[0]));
}
});
return null;
}
});
}
原因:@ForeignKey
注释确保FK具有相同的名称,因此SQL语句将彼此相等。覆盖LSFB
将存储在Set
中创建模式所需的SQL查询,以便不允许重复。