2012-03-30 28 views
27

He podido tener JPA/Hibernate para replicar la funcionalidad ON DELETE CASCADE con éxito (parece el comportamiento predeterminado) pero ahora estoy tratando de replicar el ON DELETE SET NULL funcionalidad y estoy enfrentando problemas.Tener JPA/Hibernate para replicar la funcionalidad "ON DELETE SET NULL"

Estos son mis dos clases:

@Entity 
@Table(name = "teacher") 
public class Teacher 
{ 
    @Id 
    @GeneratedValue 
    @Column(name = "id", nullable = false, length = 4) 
    private int id; 

    @OneToMany(mappedBy = "teacher") 
    private List<Student> studentList; 

    // ... 
} 

@Entity 
@Table(name = "student") 
public class Student 
{ 
    @Id 
    @GeneratedValue 
    @Column(name = "id", nullable = false, length = 4) 
    private int id; 

    @ManyToOne(optional = true) 
    @JoinColumn(name = "teacher_id", nullable = true) 
    private Teacher teacher; 

    // ... 
} 

Cuando intento eliminar un maestro, aparece el siguiente error:

org.springframework.dao.DataIntegrityViolationException: No se pudo ejecutar la actualización por lotes JDBC; SQL [eliminar del profesor donde teacher_id =?]; restricción [nula]
...
causada por: org.hibernate.exception.ConstraintViolationException: No se pudo ejecutar la actualización por lotes JDBC
...
causada por: java.sql.BatchUpdateException: entrada por lotes 0 eliminar del maestro donde teacher_id = '1' fue abortado. Llame getNextException para ver la causa.

¿Estoy haciendo algo mal? ¿Es algo alcanzable?

Gracias.

+0

¿Desea establecer todas las columnas de ese registro en nulo? o todos los campos de la entidad estudiantil – kommradHomer

+0

Quiero que la columna 'teacher'' teacher' se convierta en 'null' después de que el' teacher' 'teacher' se elimine del sistema. – satoshi

+0

No es que desee cambiar su esquema para JPA, pero me gustaría tener curiosidad por el efecto de cambiarlo a ManyToMany con eliminación de cascada en la tabla de unión. Debe eliminar la asociación y dejar al alumno. – kevingallagher

Respuesta

29

Parece que no es posible en este momento con jpa/hibernate.

On delete set null in hibernate in @OneToMany

solución JBs parece limpia sin embargo:

for (Department child : parent.getChildren()) { 
    child.setParentDepartment(null); 
} 
session.delete(parent); 

También debe ser capaz de ponerlo en un PreRemove:

@PreRemove 
private void preRemove() { 
    for (Student s : studentList) { 
     s.setTeacher(null); 
    } 
} 
+0

Gracias, ambas soluciones funcionan perfectamente. Personalmente prefiero el segundo :) – satoshi

+7

La solución '@ PreRemove' no es portátil. Ver la sección de especificaciones JPA 3.5. * En general, el método del ciclo de vida de una aplicación portátil no debe [...] modificar las relaciones dentro del mismo contexto de persistencia .* – SpaceTrucker

2

¿Qué pasa con la definición

@ForeignKey(name = "fk_student_teacher", 
      foreignKeyDefinition = " /*FOREIGN KEY in sql that sets ON DELETE SET NULL*/") 

?

+2

Esto solo se usa para especificar restricciones de clave externa en la base de datos asociada, cuando la generación de esquema está en vigencia. – Tiny

0

creo que la mejor soultion es statament usuario de SQL para el conjunto de borrado seguimiento culo de acción:

CREATE TABLE table_name 
(
    column1 datatype null/not null, 
    column2 datatype null/not null, 
    ... 

    CONSTRAINT fk_column 
    FOREIGN KEY (column1, column2, ... column_n) 
    REFERENCES parent_table (column1, column2, ... column_n) 
    ON DELETE SET NULL 
); 

cuando el usuario elimina una fila por otra eliminación en cascada, donde se utiliza una tabla de referencia para esta fila eliminada, No se pudo usar la solución hibernate y la excepción return sql.

Cuestiones relacionadas