使用Map时指定外键约束名称,使用Hibernate指定@ElementCollection

时间:2011-02-10 04:33:39

标签: java hibernate hibernate-annotations

我对某个领域有一种奇特的映射:

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

SchoolYear是一个实体,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似乎没有任何会影响它的属性。

有没有人知道是否有办法做到这一点?

2 个答案:

答案 0 :(得分:6)

我不得不修补Hibernate以创建不同的外键名称,因为Hibernate为我创建的名称并不是真的有用。

我使用了Hibernate源代码,并将类org.hibernate.mapping.Table的Source放入我的源文件夹中,这是类路径的开头(我项目中生成的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”之类的外键!永远不必再手动指定我的名字:)))

答案 1 :(得分: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

您将获得tablename,约束名称(如FK1BCA4A883A97C498),类型(如UNIQUE约束)和列名称。 这应该是一个有意义的错误信息。

我知道这不是很好,因为你放弃了数据库的可移植性,但显然目前没有办法做你想要的......