JPA не генерирует ограничения FK "при удалении установленного нуля" - PullRequest
10 голосов
/ 20 января 2009

У меня есть два связанных предложения с аннотацией JPA. Тревога и Статус. Один сигнал тревоги может иметь один статус.

Мне нужно иметь возможность удалить одно состояние и «передать» нулевое значение тем аварийным сигналам, которые находятся в этом статусе, который был удален.

То есть мне нужно, чтобы внешний ключ был определен как " при удалении set null ".

@Entity
public class Alarm {
    @Id
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="sequence")
    @SequenceGenerator(name="sequence", sequenceName="alarm_pk_seq")
    private Integer id;

    @OneToOne(cascade=CascadeType.ALL)
    @JoinColumn(name="idStatus")
    private Status status;

    // get/set
}

@Entity
public class Status {
    @Id
    @Column(name="idStatus")
    private Integer id;

    private String description;

    // get/set
}

Пример:

До:

STATUS
id  description
1   new
2   assigned
3   closed

ALARMS
id  status
1   1
2   2
3   2

После (удаление статуса с id = 2)

STATUS
id  description
1   new
3   closed

ALARMS
id  status
1   1
2   NULL
3   NULL

Я использую Hibernate и PostgreSQL, автоматически генерируя базу данных из исходного кода. Я пытался с каждым возможным CascadeType безуспешно.

Что-то не так в коде? Можно ли это сделать с помощью JPA?

Ответы [ 5 ]

3 голосов
/ 25 января 2009

Просто добавьте это, используя аннотацию Hibernate:

@OnDelete(action=OnDeleteAction.CASCADE)

генерирует внешний ключ как: «В ОБНОВЛЕНИИ НЕТ ДЕЙСТВИЯ В УДАЛЕНИИ КАСКАДА;»

Но никаких действий нет = OnDeleteAction.SET_NULL

Более того, я не люблю связывать свой код с Hibernate, если это возможно (но я могу жить с ним, если он работает).

Этот поток обсуждает это. Я не могу поверить, что в JPA (или в расширениях Hibernate) нет простого способа генерации внешнего ключа.

2 голосов
/ 06 февраля 2009

В вашем случае вы генерируете базу данных из классов. Это будет означать, что вы не будете использовать базу данных для других целей (поскольку это заставит вас иметь сценарии DDL). Это означает, что это правило, реализованное в базе данных или в коде Java, не имеет значения.

Мы также знаем, что Hibernate вызовет временное исключение в случае, когда один удалит один или несколько статусов и попытается ссылаться на него при фиксации без каскада.

Также база данных будет сгенерирована с использованием ограничения внешнего ключа.

Все это означает, что ограничение ДОЛЖНО соблюдаться, чтобы приложение работало.

Если ваши сущности находятся в банке сами по себе, вы можете добавить временный метод к сигналу тревоги или интерфейсу состояния, чтобы удалить состояние при соблюдении правила.

Кроме того, программисты при использовании сущностей будут вынуждены соблюдать правило, иначе код не будет работать. Но чтобы упростить задачу, вы можете сделать отношение двунаправленным, чтобы упростить задачу отслеживания аварийных сигналов по статусам.

Если вы можете, используйте перехватчик / прослушиватель ondelete, чтобы установить для свойства alarm.status значение null.

1 голос
/ 09 июня 2009

Не знаю о других реализациях без гибернации, но вот проблема JIRA, за которой я следил в Hibernate ...

http://opensource.atlassian.com/projects/hibernate/browse/HHH-2707

0 голосов
/ 16 октября 2012

OpenJPA имеет

@ForeignKey(deleteAction=ForeignKeyAction.NULL)

но нет стандартного способа JPA сделать это (и, очевидно, это невозможно в Hibernate).

Заставляет меня хотеть вернуться в JDO.

0 голосов
/ 22 января 2009

Вы уверены, что с вашим @OneToOne? Мне кажется, что вы бы предпочли использовать @ManyToOne (поскольку на статус могут влиять несколько аварий):

@Entity
public class Alarm {
    ...

    @ManyToOne(cascade=CascadeType.ALL)
    @JoinColumn(name="idStatus", nullable=true)
    private Status status;

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