与hibernate有很多关系的问题

时间:2016-09-18 19:19:42

标签: java spring hibernate jpa

我遇到了多对多关系的问题。人可以有一些角色,每个角色都与某些人有关。因此,当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;
    }


}

用户个人资料的实体,此表格不可编辑,之前已填充。但是与表的关系应该是。

@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)

1 个答案:

答案 0 :(得分:0)

在PersonalData类中更改以下内容:

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

为:

@ManyToMany(
        fetch = FetchType.LAZY
        )
希望这有帮助。