unidirectional onetomany one many foreign example ejemplo java hibernate orm jpa foreign-keys

java - foreign - onetomany jpa bidirectional



JPA no genera restricciones "sobre eliminar conjunto nulo" FK (5)

¿Estás seguro con tu @OneToOne? Me parece que preferiría usar @ManyToOne (ya que un estado puede verse afectado por varias alarmas):

@Entity public class Alarm { ... @ManyToOne(cascade=CascadeType.ALL) @JoinColumn(name="idStatus", nullable=true) private Status status; ... }

Tengo dos clases relacionadas con la anotación JPA. Alarma y estado. Una alarma puede tener un estado.

Lo que necesito es poder eliminar un estado y "propagar" un valor nulo a las alarmas que están en ese estado que se ha eliminado.

Es decir, necesito que la clave externa se defina como " en eliminar establecer nulo ".

@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 }

Ejemplo:

Antes de:

STATUS id description 1 new 2 assigned 3 closed ALARMS id status 1 1 2 2 3 2

Después (borrar el estado con id = 2)

STATUS id description 1 new 3 closed ALARMS id status 1 1 2 NULL 3 NULL

Estoy usando Hibernate y PostgreSQL, generando automáticamente la base de datos desde el código fuente. Lo he intentado con todos los CascadeType posibles sin éxito.

¿Hay algo mal en el código? ¿Es posible hacerlo con JPA?


Solo agregue eso usando la anotación de Hibernate:

@OnDelete(action=OnDeleteAction.CASCADE)

genera la clave foránea como: "ON UPDATE NO ACTION ON DELETE CASCADE";

Pero no hay acción = OnDeleteAction.SET_NULL

Además, no me gusta vincular mi código a Hibernate si es posible (pero puedo vivir con él si funciona).

Este hilo lo discute. No puedo creer que no exista un método fácil en las extensiones JPA (o Hibernate) para generar la clave externa.


En su caso, está generando la base de datos de las clases. Esto implicaría que no utilizará la base de datos para otros fines (ya que hacerlo lo obligaría a tener scripts DDL). Eso significa que tener esta regla implementada en la base de datos o en el código de java no es importante.

También sabemos que Hibernate plantearía una excepción transitoria en el caso de que se eliminen uno o más estados e intenten hacer referencia a ellos cuando se cometan sin una cascada.

Además, la base de datos se generará utilizando una restricción de clave externa.

Todo eso significa que la restricción DEBE ser respetada para que la aplicación funcione.

Si sus entidades están en un contenedor por sí mismas, puede agregar un método transitorio a la alarma o la interfaz de estado para eliminar un estado respetando la regla.

Además, los programadores, al usar las entidades se verán obligados a respetar la regla o de lo contrario el código no funcionará. Pero para facilitar la tarea, puede hacer que la relación sea bidireccional, de modo que la tarea de rastrear las alarmas desde los estados se haga más fácil.

Si puede, utilice un interceptor / detector ondelete para establecer la propiedad alarm.status en null.



OpenJPA tiene

@ForeignKey(deleteAction=ForeignKeyAction.NULL)

pero no hay una forma estándar de JPA para hacer esto (y aparentemente es imposible con Hibernate).

Me hace querer volver a JDO.