Saltar al contenido

Spring data JPA: ¿cómo habilitar la eliminación en cascada sin una referencia al niño en el padre?

Esta división ha sido probado por especialistas para garantizar la veracidad de nuestro tutorial.

Solución:

No es posible en el nivel de JPA sin crear una relación bidireccional. Debe especificar el tipo de cascada en User clase. User debe ser propietario de la relación y debe proporcionar la información sobre cómo tratar con PasswordResetToken.

Pero si no puede tener una relación bidireccional, le recomendaría configurar la relación directamente en el script SQL de generación de esquemas.

Si crea su esquema a través de un script SQL y no a través de la autogeneración JPA (creo que todos los proyectos serios deben seguir este patrón), puede agregar ON DELETE CASCADE restricción allí.

De alguna manera se verá así:

CREATE TABLE password_reset_tokens (
  -- columns declaration here
  user_id INT(11) NOT NULL,
  CONSTRAINT FK_PASSWORD_RESET_TOKEN_USER_ID
  FOREIGN KEY (user_id) REFERENCES users (id)
    ON DELETE CASCADE
);

Aquí está la documentación sobre cómo usar las herramientas de migración de DB con Spring Boot. Y aquí está la información sobre cómo generar secuencias de comandos de esquema desde hibernación (eso simplificará el proceso de escribir su propia secuencia de comandos).

Entidad matriz:

@OneToOne
@JoinColumn(name = "id")
private PasswordResetToken passwordResetToken;

Entidad secundaria:

@OneToOne(mappedBy = "PasswordResetToken", cascade = CascadeType.ALL, orphanRemoval = true)
private User user;

Si desea que el cliente oculte la entidad Contraseña, puede escribir una respuesta personalizada y ocultarla. O si quieres ignorarlo usando @JsonIgnore

Si no desea la referencia en la entidad principal (usuario), debe anular el método predeterminado Delete() y escriba su lógica para encontrar y eliminar el Token para cambiar la contraseña primero y luego el Usuario.

Puede usar Entity listener y Callback method @PreRemove para eliminar un ‘Token’ asociado antes del ‘Usuario’.

@EntityListeners(UserListener.class)
@Entity
public class User 

    private String name;


@Component
public class UserListener 

    private static TokenRepository tokenRepository;

    @Autowired
    public void setTokenRepository(TokenRepository tokenRepository) 
        PersonListener.tokenRepository = tokenRepository;
    

    @PreRemove
    void preRemove(User user) 
        tokenRepository.deleteByUser(user);
    

donde deleteByPerson es un método muy simple de su repositorio ‘Token’:

public interface TokenRepository extends JpaRepository 
    void deleteByUser(User user);
 

Presta atención a static declaración de tokenRepository – sin este resorte no podría inyectar TokenRepository porque, según puedo entender, UserListener es instanciado por Hybernate (ver información adicional aquí).

También como podemos leer en el manual,

¡un método de devolución de llamada no debe invocar los métodos EntityManager o Query!

Pero en mi prueba simple todo funciona bien.

Ejemplo de trabajo y prueba.

Si posees algún escollo o capacidad de reaccionar nuestro ensayo eres capaz de ejecutar una nota y con mucho gusto lo estudiaremos.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *