2011-02-10 46 views
19

時指定外鍵約束的名字,我有一種奇特的映射的一個字段:使用地圖和@ElementCollection與Hibernate

@ElementCollection 
@CollectionTable(name = "studentGradeLevel", joinColumns = @JoinColumn(name = "studentId")) 
@MapKeyJoinColumn(name = "schoolYearId") 
@Column(name = "gradeLevel", nullable = false) 
@ForeignKey(name = "fkStudentGrade2Student") 
private Map<SchoolYear, GradeLevel> gradeLevels; 

學年爲一個實體,GradeLevel是一個枚舉。

我正在使用Hibernate工具爲模式生成DDL。這產生的模式如下:

create table studentGradeLevel (
    studentId numeric(19,0) not null, 
    gradeLevel int not null, 
    schoolYearId int not null, 
    primary key (studentId, schoolYearId) 
); 

alter table studentGradeLevel 
    add constraint FK1BCA4A883A97C498 
    foreign key (schoolYearId) 
    references schoolYear; 

alter table studentGradeLevel 
    add constraint fkStudentGrade2Student 
    foreign key (studentId) 
    references student; 

的問題是,我似乎無法爲用作地圖鍵實體收集表與表之間的外鍵改變約束名稱。

我已經使用@ForeignKey爲@OneToMany,@ManyToMany和其他@ElementCollections指定約束名稱,沒有任何問題。我試過@ ForiegnKey的「inverseName」屬性,但它似乎被忽略。 @MapKeyJoinColumn似乎沒有任何會影響到這一點的屬性。

有誰知道是否有辦法做到這一點?

+1

你的意思是'FK1BCA4A883A97C498'?你爲什麼想要管理這個名字。 – 2011-02-12 00:11:38

+2

是的。原因是如果違反約束條件,則返回的錯誤將包含一個有意義的名稱。 – 2011-02-12 03:28:11

回答

0

我有同樣的問題,因爲我找不到方法來結束查詢數據庫本身以獲取該信息。

運行在SQL SERVER

select kcu.TABLE_NAME, kcu.CONSTRAINT_NAME, tc.CONSTRAINT_TYPE, kcu.COLUMN_NAME 
from INFORMATION_SCHEMA.TABLE_CONSTRAINTS as tc 
join INFORMATION_SCHEMA.KEY_COLUMN_USAGE as kcu 
on kcu.CONSTRAINT_SCHEMA = tc.CONSTRAINT_SCHEMA 
and kcu.CONSTRAINT_NAME = tc.CONSTRAINT_NAME 
and kcu.TABLE_SCHEMA = tc.TABLE_SCHEMA 
and kcu.TABLE_NAME = tc.TABLE_NAME 

你會得到表名,約束名(如FK1BCA4A883A97C498),類型(如唯一約束)和列名這個查詢。 這應該足以返回有意義的錯誤消息。

我知道是不是偉大的,因爲你失去的分貝便攜性,但顯然沒有辦法做你的那一刻問什麼...

6

我不得不修補Hibernate來創建不同的外鍵的名稱,因爲Hibernate爲我創建的那些並不是很有用。

我拿到了Hibernate源代碼,並將類org.hibernate.mapping.Table的源代碼放入我的源文件夾中,這是類路徑的開始(我的項目中生成的jar以低於hibernate.jar的字母開頭,所以這甚至可以在webapps中工作)。

的我更換了功能(在函數的頂端原始代碼)用下面的代碼uniqueColumnString:

public String uniqueColumnString(Iterator iterator, String referencedEntityName) { 
//  int result = 0; 
//  if (referencedEntityName != null) { 
//   result += referencedEntityName.hashCode(); 
//  } 
//  while (iterator.hasNext()) { 
//   result += iterator.next().hashCode(); 
//  } 
//  return (Integer.toHexString(name.hashCode()) + Integer.toHexString(result)).toUpperCase(); 
      StringBuilder retVal = new StringBuilder(); 
      retVal.append("_").append(referencedEntityName); 
      while(iterator.hasNext()) { 
       Column c = (Column)iterator.next(); 
       retVal.append("_"); 
       retVal.append(c.getName()); 
      } 
      return retVal.toString(); 
    } 

這將返回自動不錯的字符串,如「_Entity_attributeName_id」,這將被用來創建外鍵像「fk_Entity_attributeName_id」!永遠不必再用手指定我的名字:))