Укажите имя ограничения внешнего ключа при использовании Map и @ElementCollection с Hibernate - PullRequest
19 голосов
/ 10 февраля 2011

У меня есть своего рода экзотическое отображение для поля:

@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 без проблем. Я пробовал атрибут @ inieName @ ForiegnKey, но он, кажется, игнорируется. @MapKeyJoinColumn не имеет свойств, которые могли бы повлиять на это.

Кто-нибудь знает, есть ли способ сделать это?

Ответы [ 2 ]

6 голосов
/ 07 марта 2011

Мне пришлось пропатчить Hibernate для создания разных имен внешних ключей, потому что те, которые Hibernate для меня создавал, были не очень полезны.

Я взял исходный код Hibernate и поместил исходный код класса org.hibernate.mapping.Table в папку с исходным кодом, которая является началом пути к классам (полученный jar в моем проекте начинается с буквы ниже, чем hibernate.jar так что это даже работает в веб-приложениях).

Я заменил функцию 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"! Никогда больше не нужно указывать мои имена вручную:)))

0 голосов
/ 06 марта 2011

У меня была та же проблема, и потому что я не мог найти способ сделать это, я запросил саму базу данных для получения этой информации.

Выполнение этого запроса на 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), тип (например, ограничение UNIQUE) и имя столбца. Это должно быть достаточно, чтобы вернуть значимое сообщение об ошибке.

Я знаю, что это не очень хорошо, потому что вы теряете переносимость БД, но, по-видимому, сейчас нет способа сделать то, о чем вы просите ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...