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

cli*_*ers 19 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;
Run Code Online (Sandbox Code Playgroud)

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;
Run Code Online (Sandbox Code Playgroud)

问题是我似乎无法更改集合表和用作映射键的实体的表之间的外键的约束名称.

我已经使用@ForeignKey为@OneToMany,@ ManyToMany和其他@ElementCollections指定约束名称没有问题.我试过@ ForiegnKey的"inverseName"属性,但它似乎被忽略了.@MapKeyJoinColumn似乎没有任何会影响它的属性.

有谁知道有没有办法做到这一点?

Dan*_*iel 6

我不得不修补Hibernate来创建不同的外键名称,因为Hibernate为我创建的那些并不是真的有用.

我使用了Hibernate源代码,并将类的Source 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();
    }
Run Code Online (Sandbox Code Playgroud)

这会自动返回类似"_Entity_attributeName_id"的漂亮字符串,这些字符串将用于创建"fk_Entity_attributeName_id"之类的外键!永远不必再手动指定我的名字:)))


mer*_*no1 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
Run Code Online (Sandbox Code Playgroud)

您将获得表名、约束名称(如 FK1BCA4A883A97C498)、类型(如 UNIQUE 约束)和列名称。这应该足以返回有意义的错误消息。

我知道这不是很好,因为你失去了数据库的可移植性,但显然目前没有办法做你所要求的事情......