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.
La razón por la que podría estar recibiendo este error se debe al hecho de que merge
copia el contenido de una entidad separada en una entidad gestionada. Por lo tanto, si estás pasando como argumento para merge
una User
o Admin
entidad (de ahora en adelante referido como PERSON
) que contiene un unifamiliar copia de una Credentials
entidad persistió en el PP; entonces definitivamente va a obtener este problema. La razón de esto es:
merge
copiará todo el estado de laPERSON
discusión en la correspondiente entidad gestionada contextoPERSON
entidad.- Esta copia incluirá la
Credentials
entidad dentro delPERSON
argumento. - Desde la
Credentials
entidad se separó, el gestor de persistencia asumirá esta entidad corresponde a una entidad no persistido aún. - El contexto de persistencia, al lavar la sesión, se guardará el fusionaron
Credentials
utilizando unINSERT
(persisten la nuevaCredentials
) en lugar de unaUPDATE
. - El
INSERT
activará la violación restricción duplicado en ellogin
campo que está recibiendo, porque el originalCredentials
existir registro con ellogin
valor que se utiliza en elINSERT
.
EDIT: (¿Cómo unir)
Si no está actualizando el Credentials
en PERSON
, a continuación, cuando la fusión en su PERSON_DAO
, usted podría:
- Retire temporalmente
Credentials
dePERSON
(null
) antes de la fusión. - Combinar
PERSON
. - Añadir el original
Credentials
de nuevo a su recién fusionadaPERSON
Como no tengo acceso a su DAO
có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 service
capa encima de la dao
capa. 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.