JPA / Hibernate: упорядоченный список создает исключение ConstraintViolationException - PullRequest
0 голосов
/ 20 сентября 2019

В настоящее время я работаю с Hibernate 5.3.7 и пытаюсь использовать упорядоченный список - что делается аннотацией JPA @OrderColumn.Мои сущности выглядят так:

@Entity
@Table(name = "test_order", uniqueConstraints = {
        @UniqueConstraint(name = "TestOrderNumberIndex", columnNames = { "number" }) })
public class TestOrderEntity extends AbstractEntity {
    private Long id;
    private String number;
    private String customer;
    private List<TestOrderItemEntity> items;

    ...

    @OneToMany(mappedBy = "order", targetEntity = TestOrderItemEntity.class, cascade = { CascadeType.PERSIST,
            CascadeType.MERGE, CascadeType.REMOVE })
    @OrderColumn(name = "item_index", nullable = false)
    public List<TestOrderItemEntity> getItems() {
        return this.items;
    }

    public void setItems(List<TestOrderItemEntity> items) {
        this.items = items;
    }
}

@Entity
@Table(name = "test_order_item", uniqueConstraints = {
        @UniqueConstraint(name = "TestOrderItemOrderArticleNumberIndex", columnNames = { "order_id",
                "article_number" }) })
public class TestOrderItemEntity extends AbstractEntity {
    private Long id;
    private TestOrderEntity order;
    private String articleNumber;
    private Integer amount;

    ...

    @ManyToOne(targetEntity = TestOrderEntity.class, cascade = { CascadeType.PERSIST, CascadeType.MERGE,
            CascadeType.REMOVE })
    @JoinColumn(name = "order_id", referencedColumnName = "id", foreignKey = @ForeignKey(name = "FKTestOrderItemTestOrder"))
    public TestOrderEntity getOrder() {
        return this.order;
    }

    public void setOrder(TestOrderEntity order) {
        this.order = order;
    }
}

DDL, созданный Hibernate, выглядит следующим образом:

create table test_order (
    id bigint not null,
    customer varchar(255) not null,
    number varchar(255) not null,
    primary key (id)
);

create table test_order_item (
    id bigint not null,
    amount integer not null,
    article_number varchar(255) not null,
    order_id bigint,
    item_index integer not null,
    primary key (id)
);

create unique index TestOrderNumberIndex on test_order (number)

create unique index TestOrderItemOrderArticleNumberIndex on test_order_item (order_id, article_number)

alter table test_order_item
    add constraint FKTestOrderItemTestOrder foreign key (order_id) references test_order

item_index можно увидеть в операторе create table test_order_item.Таким образом, Hibernate замечает аннотацию @OrderColumn.Я выполняю следующий код в одной транзакции:

EntityManager em;
TestOrderEntity o;
TestOrderItemEntity i1, i2;

o = new TestOrderEntity();
o.setNumber("123");
o.setCustomer("ACME");

i1 = new TestOrderItemEntity();
i1.setArticleNumber("ABC-123");
i1.setAmount(Integer.valueOf(123));

i2 = new TestOrderItemEntity();
i2.setArticleNumber("XYZ-321");
i2.setAmount(Integer.valueOf(321));

o.setItems(new ArrayList<>(i1, i2));
i1.setOrder(o);
i2.setOrder(o);

em.persist(o);

Я ожидал бы, что JPA / Hibernate просто сохранит сущности в базе данных и автоматически заполнит item_index (тем более, что у меня нетдоступ к нему - в TestOrderItemEntity нет соответствующего поля).Но я получаю следующее исключение (сокращенная форма):

javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: could not execute statement
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:154)
    ...
Caused by: org.hibernate.exception.ConstraintViolationException: could not execute statement
    at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:59)
    ...
Caused by: java.sql.SQLIntegrityConstraintViolationException: Column 'ITEM_INDEX'  cannot accept a NULL value.
    at org.apache.derby.impl.jdbc.SQLExceptionFactory.getSQLException(Unknown Source)
    ...
Caused by: ERROR 23502: Column 'ITEM_INDEX'  cannot accept a NULL value.
    at org.apache.derby.iapi.error.StandardException.newException(Unknown Source)
    ...

Кто-то знает, что я делаю неправильно?Я пропустил другую аннотацию или параметр аннотации?На основании других источников в Интернете, а также документации все правильно.

https://docs.jboss.org/hibernate/orm/5.3/userguide/html_single/chapters/domain/collections.html#collections-list

РЕДАКТИРОВАТЬ:

Как я читал, некоторые люди решилипроблема, заменив cascade = { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE } на cascade = { CascadeType.ALL }, я тоже попробовал.Но это ничего не изменило.

1 Ответ

0 голосов
/ 20 сентября 2019

После многих попыток я обнаружил свою ошибку (и в чем разница между всеми рабочими примерами и моим подходом): я использовал аннотацию @OrderColumn(name = "item_index", nullable = false) - во всех примерах используется @OrderColumn(name = "item_index").Первоначально я добавил nullable = false, так как подумал: «Да, чувак, я всегда хочу иметь такой критерий / индекс сортировки для своего списка, так почему он должен быть обнуляемым?».Но кажется, что параметры служат другой цели - , если какая-либо цель вообще (может быть, кто-то, у кого есть больше информации об этом, может поделиться своими знаниями в комментариях).

Использование @OrderColumn(name = "item_index") Iв журнале можно увидеть следующее (если ведение журнала SQL для Hibernate активировано):

Hibernate: 
    /* insert org.example.TestOrderEntity
        */ insert 
        into
            test_order
            (customer, number, id) 
        values
            (?, ?, ?)
Hibernate: 
    /* insert org.example.TestOrderItemEntity
        */ insert 
        into
            test_order_item
            (amount, article_number, order_id, id) 
        values
            (?, ?, ?, ?)
Hibernate: 
    /* insert org.example.TestOrderItemEntity
        */ insert 
        into
            test_order_item
            (amount, article_number, order_id, id) 
        values
            (?, ?, ?, ?)
Hibernate: 
    update
        test_order_item 
    set
        item_index=? 
    where
        id=?
Hibernate: 
    update
        test_order_item 
    set
        item_index=? 
    where
        id=?

До этого момента я думал, что item_index будет вставлено во время начальной вставки сущности.Но это не так.Поэтому наличие столбца NOT NULL убивает подход Hibernate.Также мне интересно, почему Hibernate использует для этого дополнительные операторы SQL, так как позиция индекса известна заранее.Конечно, идентификатор будет создан во время первоначальной вставки.Но это не нужно знать во время начальной вставки, которая могла включать значение столбца item_index.

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