Java 在Hibernate中映射同一实体两次时使用双外键
通常的做法是将同一实体映射两次甚至三次,每次都需要处理一部分列。我发现,使用HibernateJava 在Hibernate中映射同一实体两次时使用双外键,java,hibernate,Java,Hibernate,通常的做法是将同一实体映射两次甚至三次,每次都需要处理一部分列。我发现,使用Hibernate3.5.1,每当映射同一表的两个实体中存在@manytone或@OneToMany时,就会创建两次外键。这对MySQL和SQL Server没有影响,但Oracle拒绝了第二条创建语句 以下是一个例子: @Entity @javax.persistence.SequenceGenerator(name = "SEQ_STORE", sequenceName = "SEQ_ENTITY") @Table(
3.5.1
,每当映射同一表的两个实体中存在@manytone
或@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>();
}
我不确定这是否是一个休眠错误。我们目前无法移动到Hibernate4。这个问题可以通过代码解决,还是需要新的Hibernate版本?我已经做了一个解决方法:
@ForeignKey
注释(例如@ForeignKey(name=“FK_to_ENTITY”,inverseName=“FK_to_ROLE”)
)LocalSessionFactoryBean
,如下所示:@覆盖
public void createDatabaseSchema()引发DataAccessException
{
info(“为Hibernate SessionFactory创建数据库模式”);
SessionFactory SessionFactory=getSessionFactory();
最终方言方言=((SessionFactoryImplementor)sessionFactory).getdial();
final LinkedHashSet sql=新LinkedHashSet();
for(字符串查询:getConfiguration().generateSchemaCreationScript(方言))
添加(查询);
HibernateTemplate HibernateTemplate=新的HibernateTemplate(sessionFactory);
执行(新的HibernateCallback()
{
@凌驾
public Void doInHibernate(会话会话)引发SQLException
{
会议.工作(新工作)
{
@凌驾
public void execute(连接连接)引发SQLException
{
PhoenixAnnotationSessionFactoryBean.this.executeSchemaScript(conn,sql.toArray(新字符串[0]);
}
});
返回null;
}
});
}
原因:
@ForeignKey
注释确保FKs具有相同的名称,因此SQL语句将彼此相等。被重写的LSFB
将在集合中存储创建架构所需的SQL查询,这样就不允许重复
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;
@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;
}
});
}