Java 在Hibernate中映射同一实体两次时使用双外键

Java 在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(

通常的做法是将同一实体映射两次甚至三次,每次都需要处理一部分列。我发现,使用Hibernate
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版本?

我已经做了一个解决方法:

  • 向两个实体添加具有相同FK名称的
    @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;
            }
        });
    
    }