Недействительное имя столбца со встроенным полем

В некоторых тестах у меня ошибка:

SqlExceptionHelper - Invalid column name 'contact_information_id'.

javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: could not execute statement

В БД вместо этого есть столбец primary_contact_information_id.

Это происходит, когда репозиторий пытается сохранить объект Организация. В классе организации есть поле Важный контакт, а в классе Важный контакт есть поле контакты.

Проект был перенесен с java7 на java8, и в настоящее время я работаю над переходом с Hibernate 3 на Hibernate 5.

Была стратегия именования org.hibernate.cfg.ImprovedNamingStrategy, поэтому для hibernate 5 я использовал CustomNamingStrategy

public class CustomNamingStrategy extends PhysicalNamingStrategyStandardImpl {

    public static final CustomNamingStrategy INSTANCE = new CustomNamingStrategy();

    @Override
    public Identifier toPhysicalTableName(Identifier name, JdbcEnvironment context) {
        return new Identifier(addUnderscores(name.getText()), name.isQuoted());
    }

    @Override
     public Identifier toPhysicalColumnName(Identifier name, JdbcEnvironment context) {
        return new Identifier(addUnderscores(name.getText()), name.isQuoted());
    }


    protected static String addUnderscores(String name) {
         final StringBuilder buf = new StringBuilder(name.replace('.', '_'));
        for (int i = 1; i < buf.length() - 1; i++) {
            if (
                    Character.isLowerCase(buf.charAt(i - 1)) &&
                        Character.isUpperCase(buf.charAt(i)) &&
                        Character.isLowerCase(buf.charAt(i + 1))) {
                buf.insert(i++, '_');
            }
        }
        return buf.toString().toLowerCase(Locale.ROOT);
    }
}

Организация

@Entity(name = "Organisation")
@Table(name = "organisation", uniqueConstraints = {@UniqueConstraint(name = "organisation_name_udx", columnNames = {"name"})})
@EntityListeners(EntityCreateListener.class)
public class Organisation implements Serializable, PatientListEntity {

    // Some fields here

    @Embedded
    @Valid
    private PrimaryContact primaryContact;

    // Some fields here
}

Важный контакт

@Embeddable
public class PrimaryContact extends Person implements Serializable {
    private static final long serialVersionUID = 1L;

    @Valid
    @OneToOne(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
    @JoinColumn(name = "primary_contact_information_id")
    private ContactInformation contactInformation;
}

Контакты

@Entity(name = "ContactInformation")
@Table(name = "contact_information")
@Data
@NoArgsConstructor
public class ContactInformation implements Serializable {
public static final int MAX_PHONENUMBERS = 5;

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Valid
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "address_id")
private Address address = new Address();

@RFCEmail
@Size(max = RFCEmailValidator.EMAIL_TOTAL_MAX_LENGTH)
private String email = "";

@Valid
@Embedded
@AttributeOverrides({@AttributeOverride(name = "number", column = @Column(name = "phone_number_0")),
        @AttributeOverride(name = "type", column = @Column(name = "phone_type_0"))})
private PhoneNumber phoneNumber0;

@Valid
@Embedded
@AttributeOverrides({@AttributeOverride(name = "number", column = @Column(name = "phone_number_1")),
        @AttributeOverride(name = "type", column = @Column(name = "phone_type_1"))})
private PhoneNumber phoneNumber1;

@Valid
@Embedded
@AttributeOverrides({@AttributeOverride(name = "number", column = @Column(name = "phone_number_2")),
        @AttributeOverride(name = "type", column = @Column(name = "phone_type_2"))})
private PhoneNumber phoneNumber2;

@Valid
@Embedded
@AttributeOverrides({@AttributeOverride(name = "number", column = @Column(name = "phone_number_3")),
        @AttributeOverride(name = "type", column = @Column(name = "phone_type_3"))})
private PhoneNumber phoneNumber3;

@Valid
@Embedded
@AttributeOverrides({@AttributeOverride(name = "number", column = @Column(name = "phone_number_4")),
        @AttributeOverride(name = "type", column = @Column(name = "phone_type_4"))})
private PhoneNumber phoneNumber4;

@OneToOne
@JoinColumn(name = "time_zone_code")
private TimeZone timeZone;
}

Как видите, под полем contactInformation есть @JoinColumn (name = "primary_contact_information_id"), но это не помогает.

!!! ОБНОВЛЕНО !!!

Похоже, такое странное поведение происходит из-за моей нестандартной стратегии именования. Итак, я решил его вообще удалить. Но теперь, добавив необходимые аннотации @Column, я получаю новую ошибку:

BatchUpdateException: The UPDATE statement conflicted with the FOREIGN KEY constraint "application_dme_provider_fk1". The conflict occurred in database "ruslans_00_develop_dev_easycare", table "dbo.application", column 'application_code'.], SQL: update application_dme_provider set application_code=? where application_code=? and party_id=? and party_role_type_code=?

Вы не опубликовали объект ContactInformation. Есть ли в нем поле contactInformationId?

MirMasej 27.12.2018 14:20

Добавлен объект ContactInformation, но нет поля contactInformationId

Ruslan Sheremet 27.12.2018 14:46
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
2
466
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Проблема возникает из-за стратегии именования по умолчанию в Hibernate 5. Он добавляет «_id» для каждого (OneToOne, OneToMany, ManyToMany) отношения. @JoinColumn(name = <correct_name_from_db>) исправит это.

В моем случае было еще одно поле Контакты без аннотации JoinColumn.

Другие вопросы по теме