Cómo Actualizar en cascada a entidad secundaria en Hibernate

Igor RMS:

Tengo tres entidades: Credenciales, el usuario y de administrador. Tanto las entidades de usuario y de administrador tienen unas credenciales de campo, que se relaciona con el uso de credenciales entidad de anotación OneToOne.

Al actualizar un usuario existente o la entrada de administración, a través de EntityManager.merge, estoy consiguiendo llave duplicada sobre la columna Credentials.login, que tiene restricción única.

@Entity
@Table
public class Credentials {
    @Id
    @Column(name="id", unique=true, nullable=false)
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(unique=true, nullable=false, length=50)
    private String login;

    @Column(nullable=false, length=50)
    private String password;

    /*********************************************
    *  getters and setters here
    **********************************************/
}

@Entity
@Table
public class User{
    @Id
    @Column(name="id", unique=true, nullable=false)
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    /*********************************************
    *  Specific user columns here
    **********************************************/

    @OneToOne(cascade = {CascadeType.ALL})
    @JoinColumn(nullable=false, name = "idCredentials")
    private Credentials credentials;

    /*********************************************
    *  getters and setters here
    **********************************************/
}

@Entity
@Table
public class Admin{
    @Id
    @Column(name="id", unique=true, nullable=false)
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    /*********************************************
    *  Specific admin columns here
    **********************************************/

    @OneToOne(cascade = {CascadeType.ALL})
    @JoinColumn(nullable=false, name = "idCredentials")
    private Credentials credentials;

    /*********************************************
    *  getters and setters here
    **********************************************/
}

Espero tener user.credentials de usuario y actualizadas en respectivas tablas de la base después de llamar EntityManager.merge (usuario), pero estoy consiguiendo el error "Entrada duplicada 'nombredeusuario' para la llave 'login_UNIQUE. Lo mismo sucede con la entidad de administración.

Gracias de antemano por cualquier ayuda.

Marco R. :

La razón por la que podría estar recibiendo este error se debe al hecho de que mergecopia el contenido de una entidad separada en una entidad gestionada. Por lo tanto, si estás pasando como argumento para mergeuna Usero Adminentidad (de ahora en adelante referido como PERSON) que contiene un unifamiliar copia de una Credentialsentidad persistió en el PP; entonces definitivamente va a obtener este problema. La razón de esto es:

  1. mergecopiará todo el estado de la PERSONdiscusión en la correspondiente entidad gestionada contexto PERSON entidad.
  2. Esta copia incluirá la Credentialsentidad dentro del PERSONargumento.
  3. Desde la Credentialsentidad se separó, el gestor de persistencia asumirá esta entidad corresponde a una entidad no persistido aún.
  4. El contexto de persistencia, al lavar la sesión, se guardará el fusionaron Credentials utilizando un INSERT(persisten la nueva Credentials) en lugar de una UPDATE.
  5. El INSERTactivará la violación restricción duplicado en el logincampo que está recibiendo, porque el original Credentialsexistir registro con el loginvalor que se utiliza en el INSERT.

EDIT: (¿Cómo unir)

Si no está actualizando el Credentialsen PERSON, a continuación, cuando la fusión en su PERSON_DAO, usted podría:

  1. Retire temporalmente Credentialsde PERSON( null) antes de la fusión.
  2. Combinar PERSON.
  3. Añadir el original Credentialsde nuevo a su recién fusionada PERSON

Como no tengo acceso a su DAOcódigo, aquí es un pseudo código de la anterior:

    public PERSON mergeSafely(PERSON person) {
        Credentials originalCredentials = person.getCredentials();
        person.setCredentials(null);
        person = em.merge(person);
        person.setCredentials(originalCredentials);
        return person;
    }

En caso de que desee combinar también Credentials, entonces usted debe (por causa limpieza) utilizar la servicecapa encima de la daocapa. Un pseudo código de un método de utilidad para lograr esto en esa capa se vería así:

    public PERSON mergeCompletely(PERSON person) {
        Credentials mergedCredentials = credentialsDAO.merge(person.getCredentials());
        person.setCredentials(mergedCredentials);
        person = personDAO.merge(person);
        return person;
    }

Espero que esto ayude.

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=207056&siteId=1
Recomendado
Clasificación