2016-09-18 45 views
0

我有一个多对多关系和一个关系问题。人可以有一些角色,每个角色都与某些人有关。因此,当hibernate持续存在时,整个实体会尝试插入与退出的人相关的角色。与休眠存在多重关系的问题

这是堆栈跟踪

ep 18, 2016 7:52:02 PM org.apache.coyote.AbstractProtocol start 
INFORMACIÓN: Starting ProtocolHandler ["ajp-nio-8009"] 
sep 18, 2016 7:52:02 PM org.apache.catalina.startup.Catalina start 
INFORMACIÓN: Server startup in 14614 ms 
Hibernate: 
    insert 
    into 
     CLIENTE 
     (ALIAS, DESCRIPCION, EDAD_MAX, EDAD_MIN, VALORACION) 
    values 
     (?, ?, ?, ?, ?, ?) 
Hibernate: 
    insert 
    into 
     PERSONA 
     (APELLIDOS, ID_CLIENTE, IS_CLIENTE, FECHA_NACIMIENTO, LOCALIDAD, MAIL, NOMBRE, PASSWORD, SEXO, TELEFONO, USUARIO) 
    values 
     (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) 
Hibernate: 
    insert 
    into 
     USER_PROFILE 
     (TIPO) 
    values 
     (?) 
sep 18, 2016 7:58:17 PM org.apache.catalina.core.StandardWrapperValve invoke 
GRAVE: El Servlet.service() para el servlet [dispatcher] en el contexto con ruta [/aphroditesocial] lanzó la excepción [Request processing failed; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement] con causa raíz 
com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry 'CLIENTE' for key 'TIPO' 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source) 
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source) 
    at java.lang.reflect.Constructor.newInstance(Unknown Source) 

我有这些实体

@Component 
@Entity 
@Table(name = "PERSONA") 
public class PersonalData implements Serializable 
{ 

    /** 
    * 
    */ 
    private static final long serialVersionUID = -4725368930330921397L; 

    @Id 
    @Column(name = "ID_PERSONA", nullable = false) 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private Integer id = 0; 

    @Column(name = "NOMBRE", nullable = false) 
    private String nombre; 

    @Column(name = "APELLIDOS", nullable = false) 
    private String apellidos; 

    @Column(name = "FECHA_NACIMIENTO", nullable = false) 
    private String fechaNacimiento; 

    @Column(name = "MAIL", nullable = false) 
    private String mail; 

    @Column(name = "USUARIO", nullable = false, unique=true) 
    private String usuario; 

    @Column(name = "PASSWORD", nullable = false) 
    private String password; 

    @Column(name = "TELEFONO", nullable = false) 
    private String telefono; 

    @Column(name = "SEXO", nullable = false) 
    private String sexo; 

    @Column(name = "IS_CLIENTE", nullable = false) 
    private boolean cliente; 

    @Column(name = "LOCALIDAD", nullable = false) 
    private String localidad; 

    @OneToOne(cascade = {CascadeType.ALL}) 
    @JoinColumn(name="ID_CLIENTE") 
    private ClientData clientData; 

    @NotEmpty 
    @ManyToMany(
      fetch = FetchType.LAZY 
      , cascade = CascadeType.ALL 
      ) 
    @JoinTable(name = "PERSONA_USER_PROFILE", 
      joinColumns = { @JoinColumn(name = "ID_PERSONA" 
      //, referencedColumnName="ID_PERSONA" 
      )}, 
      inverseJoinColumns = { @JoinColumn(name = "ID_USER_PROFILE") }) 
    private Set<UserProfile> userProfiles = new HashSet<UserProfile>(); 

    public String getNombre() { 
     return nombre; 
    } 
    public void setNombre(String nombre) { 
     this.nombre = nombre; 
    } 
    public String getApellidos() { 
     return apellidos; 
    } 
    public void setApellidos(String apellidos) { 
     this.apellidos = apellidos; 
    } 
    public String getFechaNacimiento() { 
     return fechaNacimiento; 
    } 
    public void setFechaNacimiento(String fechaNacimiento) { 
     this.fechaNacimiento = fechaNacimiento; 
    } 
    public String getMail() { 
     return mail; 
    } 
    public void setMail(String mail) { 
     this.mail = mail; 
    } 
    public String getUsuario() { 
     return usuario; 
    } 
    public void setUsuario(String usuario) { 
     this.usuario = usuario; 
    } 
    public String getPassword() { 
     return password; 
    } 
    public void setPassword(String password) { 
     this.password = password; 
    } 
    public String getTelefono() { 
     return telefono; 
    } 
    public void setTelefono(String telefono) { 
     this.telefono = telefono; 
    } 
    public String getSexo() { 
     return sexo; 
    } 
    public void setSexo(String sexo) { 
     this.sexo = sexo; 
    } 
    public boolean isCliente() { 
     return cliente; 
    } 
    public void setCliente(boolean cliente) { 
     this.cliente = cliente; 
    } 
    public String getLocalidad() { 
     return localidad; 
    } 
    public void setLocalidad(String localidad) { 
     this.localidad = localidad; 
    } 

    public ClientData getClientData() { 
     return clientData; 
    } 
    public void setClientData(ClientData clientData) { 
     this.clientData = clientData; 
    } 

    public Integer getId() { 
     return id; 
    } 
    public void setId(Integer id) { 
     this.id = id; 
    } 
    public Set<UserProfile> getUserProfiles() { 
     return userProfiles; 
    } 
    public void setUserProfiles(Set<UserProfile> userProfiles) { 
     this.userProfiles = userProfiles; 
    } 
    @Override 
    public String toString() { 
     return "PersonalData [id=" + id + ", nombre=" + nombre + "]"; 
    } 

    @Override 
    public int hashCode() { 
     final int prime = 31; 
     int result = 1; 
     result = prime * result + id; 
     result = prime * result + ((usuario == null) ? 0 : usuario.hashCode()); 
     return result; 
    } 

    @Override 
    public boolean equals(Object obj) { 
     if (this == obj) 
      return true; 
     if (obj == null) 
      return false; 
     if (getClass() != obj.getClass()) 
      return false; 
     PersonalData other = (PersonalData) obj; 
     if (id != other.id) 
      return false; 
     if (usuario == null) { 
      if (other.usuario != null) 
       return false; 
     } else if (!usuario.equals(other.usuario)) 
      return false; 
     return true; 
    } 


} 

实体PO​​R用户配置文件,这个表不应该是可编辑的,它之前已经填充。但与表格的关系应该。

@Entity 
@Table(name="USER_PROFILE") 
public class UserProfile implements Serializable{ 

    /** 
    * 
    */ 
    private static final long serialVersionUID = 3901763913690001763L; 

    @Id @GeneratedValue(strategy=GenerationType.IDENTITY) 
    //@Column(name = "ID_USER_PROFILE", nullable = false) 
    private Integer id_user_profile;  

    //TODO HACER NULLABLE LOS ATRIBUTOS 
    @Column(name="TIPO", length=15, unique=true, nullable=false) 
    private String tipo = UserProfileType.CLIENTE.getUserProfileType(); 

    public UserProfile (Integer id, String tipo){ 
     this.id_user_profile = id; 
     this.tipo = tipo; 
    } 

    public UserProfile(){ 
     super(); 
    } 

    public String getTipo() { 
     return tipo; 
    } 

    public void setTipo(String type) { 
     this.tipo = type; 
    } 

    public Integer getId_user_profile() { 
     return id_user_profile; 
    } 

    public void setId_user_profile(Integer id_user_profile) { 
     this.id_user_profile = id_user_profile; 
    } 

    @Override 
    public int hashCode() { 
     final int prime = 31; 
     int result = 1; 
     result = prime * result + ((id_user_profile == null) ? 0 : id_user_profile.hashCode()); 
     result = prime * result + ((tipo == null) ? 0 : tipo.hashCode()); 
     return result; 
    } 

    @Override 
    public boolean equals(Object obj) { 
     if (this == obj) 
      return true; 
     if (obj == null) 
      return false; 
     if (!(obj instanceof UserProfile)) 
      return false; 
     UserProfile other = (UserProfile) obj; 
     if (id_user_profile == null) { 
      if (other.id_user_profile != null) 
       return false; 
     } else if (!id_user_profile.equals(other.id_user_profile)) 
      return false; 
     if (tipo == null) { 
      if (other.tipo != null) 
       return false; 
     } else if (!tipo.equals(other.tipo)) 
      return false; 
     return true; 
    } 

    @Override 
    public String toString() { 
     return "UserProfile [id=" + id_user_profile + ", type=" + tipo + "]"; 
    } 

} 

并创建表格的句子。

CREATE TABLE PERSONA (
    ID_PERSONA bigint NOT NULL auto_increment, 
    NOMBRE VARCHAR(50) not null, 
    APELLIDOS VARCHAR(50) not null, 
    FECHA_NACIMIENTO VARCHAR(50) not null, 
    MAIL VARCHAR(50) not null, 
    USUARIO VARCHAR(50) not null, 
    PASSWORD VARCHAR(256) not null, 
    TELEFONO VARCHAR(50) not null, 
    SEXO VARCHAR(50) not null, 
    LOCALIDAD VARCHAR(20) NOT NULL, 
    IS_CLIENTE bool not null, 
    ID_CLIENTE bigint REFERENCES CLIENTE(ID_CLIENTE) ON DELETE CASCADE, 
    PRIMARY KEY (ID_PERSONA), 
    UNIQUE (USUARIO) 
); 

create table USER_PROFILE(
    ID_USER_PROFILE BIGINT NOT NULL auto_increment, 
    TIPO VARCHAR(30) NOT NULL, 
    PRIMARY KEY (ID_USER_PROFILE), 
    UNIQUE (TIPO) 
); 

/* JOIN TABLE for MANY-TO-MANY relationship*/ 
CREATE TABLE PERSONA_USER_PROFILE (
    ID_PERSONA BIGINT NOT NULL, 
    ID_USER_PROFILE BIGINT NOT NULL, 
    PRIMARY KEY (ID_PERSONA, ID_USER_PROFILE), 
    CONSTRAINT FK_APP_USER FOREIGN KEY (ID_PERSONA) REFERENCES PERSONA (ID_PERSONA), 
    CONSTRAINT FK_USER_PROFILE FOREIGN KEY (ID_USER_PROFILE) REFERENCES USER_PROFILE (ID_USER_PROFILE) 
); 

如果我注释掉为cascadetype.ALL声明多行至多行的行,我会得到这个堆栈跟踪。

Hibernate: 
    select 
     this_.id_user_profile as id_user_1_5_0_, 
     this_.TIPO as TIPO2_5_0_ 
    from 
     USER_PROFILE this_ 
    order by 
     this_.TIPO asc 
Hibernate: 
    insert 
    into 
     CLIENTE 
     (ALIAS, DESCRIPCION, EDAD_MAX, EDAD_MIN, ORIENTACION_SEXUAL, VALORACION) 
    values 
     (?, ?, ?, ?, ?, ?) 
Hibernate: 
    insert 
    into 
     PERSONA 
     (APELLIDOS, ID_CLIENTE, IS_CLIENTE, FECHA_NACIMIENTO, LOCALIDAD, MAIL, NOMBRE, PASSWORD, SEXO, TELEFONO, USUARIO) 
    values 
     (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) 
Hibernate: 
    insert 
    into 
     PERSONA_USER_PROFILE 
     (ID_PERSONA, ID_USER_PROFILE) 
    values 
     (?, ?) 
sep 18, 2016 9:13:54 PM org.apache.catalina.core.StandardWrapperValve invoke 
GRAVE: El Servlet.service() para el servlet [dispatcher] en el contexto con ruta [/application] lanzó la excepción [Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessApiUsageException: object references an unsaved transient instance - save the transient instance before flushing: com.aphroditesocial.web.model.UserProfile; nested exception is org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.aphroditesocial.web.model.UserProfile] con causa raíz 
org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.aphroditesocial.web.model.UserProfile 
    at org.hibernate.engine.internal.ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:294) 
    at org.hibernate.type.EntityType.getIdentifier(EntityType.java:537) 
    at org.hibernate.type.ManyToOneType.nullSafeSet(ManyToOneType.java:165) 
    at org.hibernate.persister.collection.AbstractCollectionPersister.writeElement(AbstractCollectionPersister.java:899) 
    at org.hibernate.persister.collection.AbstractCollectionPersister.recreate(AbstractCollectionPersister.java:1308) 
    at org.hibernate.action.internal.CollectionRecreateAction.execute(CollectionRecreateAction.java:67) 
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:465) 
+0

向我们展示如何保存'Persona'或/和'UserProfile'。 –

+0

请分享用于在数据库中保存Persona和UserProfile对象的代码。 –

回答

0

变化PersonalData类如下:

@ManyToMany(
     fetch = FetchType.LAZY 
     , cascade = CascadeType.ALL 
     ) 

到:

@ManyToMany(
     fetch = FetchType.LAZY 
     ) 

希望这有助于。