Hibernate заставляет внешний ключ быть ненулевым

Я хочу, чтобы у продукта был необязательный ProductType. Но во время генерации схемы Hibernate по какой-то причине игнорирует мое определение и создает столбец, не допускающий значения NULL, для внешнего ключа. Мы используем Hibernate для управления схемой и SQL Server 16.

Вот что Hibernate выводит из системы во время создания схемы:

Hibernate: drop table if exists my_product
Hibernate: drop table if exists my_producttype
create table my_product (id uniqueidentifier not null, name varchar(255) not null, typeId uniqueidentifier not null, primary key (id))
create table my_producttype (id uniqueidentifier not null, name varchar(255) not null, primary key (id))
alter table pg_product add constraint FK123456789 foreign key (typeId) references my_producttype

Это схема, определенная в Java:

@Entity
@Table(name = "my_product")
public class Product extends CoreModel<Product> {

    @NotNull
    private String name;

    @ManyToOne(cascade = CascadeType.REMOVE, fetch = FetchType.LAZY)
    @JoinColumn(name = "typeId", nullable = true)
    @JsonIgnore
    @org.springframework.lang.Nullable
    private ProductType productType;
}

и этот абстрактный класс модели

@MappedSuperclass
public abstract class CoreModel<T extends CoreModel<T>> {

    @JsonProperty(access = JsonProperty.Access.READ_ONLY)
    @Column(updatable = false)
    @GeneratedValue(strategy = GenerationType.UUID)
    @Id
    private UUID id;
}

и, наконец, указанный объект

@Entity
@Table(name = "my_producttype")
public class ProductType extends CoreModel<ProductType> {


    @NotNull
    private String name;
}

соответствующий application.yml

spring:
  datasource:
    driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver
  jpa:
    database: sql_server
    open-in-view: false
    hibernate:
      ddl-auto: create
      naming:
        implicit-strategy: org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
        physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
    properties:
      hibernate:
        dialect: org.hibernate.dialect.SQLServerDialect
        jdbc:
          time_zone: UTC

Что я пробовал:

Системная информация

  • Spring 3.3.0
  • Спящий режим 6.5.2
  • MS SQL-сервер 16.00.4125
  • mssql-jdbc 12.6.1

@JohnWilliams внешний ключ может быть совершенно нулевым, SQL не запрещает это (ссылка может быть необязательной). Таким образом, вам не нужны фиктивные отношения в вашей базе данных.

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

Ответы 1

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

Виновник найден, и я должен извиниться, так как вы не смогли этого понять.

Свойство productType является частным и поэтому имеет геттеры и сеттеры, которые я пропустил. Важно отметить, что во время рефакторинга я забыл удалить там аннотацию @NotNull - и сегодня я узнал, что Spring/Hibernate также анализирует их во время генерации схемы, а не только аннотации полей.

Исправление должно было измениться:

    public @NotNull ProductType getProductType() {
        return productType;
    }

    public void setProductType(@NotNull ProductType productType) {
        this.productType = productType;
    }

к этому

    public ProductType getProductType() {
        return productType;
    }

    public void setProductType(ProductType productType) {
        this.productType = productType;
    }

Извините, но спасибо, что были моей резиновой уткой.

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