2014-10-09 57 views
0

通常的做法是將同一個實體映射兩次或甚至三次,每次映射處理所需的列的子集。我發現在Hibernate 3.5.1中,每次在映射同一個表的兩個實體中都存在@ManyToOne@OneToMany時,會創建兩次外鍵。這對MySQL和SQL Server沒有影響,但是Oracle拒絕了第二個創建語句。當映射同一個實體兩次時,Hibernate中的雙重外鍵 -

下面是一個例子:

@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的bug。我們目前不能移植到Hibernate 4.可以通過代碼修復它,還是需要新的Hibernate版本?

回答

0

我已經做了變通方法:

  1. 添加@ForeignKey註釋具有相同FK名兩個實體(如@ForeignKey(name = "FK_TO_ENTITY", inverseName = "FK_TO_ROLE")
  2. 擴展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查詢,以便不允許重複。

相關問題