JPA - Hibernate ManyToMany关系保存

时间:2012-05-24 20:16:27

标签: java spring hibernate jpa

嘿,我一直在网上搜索以下问题而没有成功......

嗯......我正在测试惠特Hibernate和JPA注释,我开发了一个通常的用户案例ManyToMany关系。我试图用现有的组保存一个新用户并且测试用例抛出异常,请参阅下面的测试代码和异常*:

概率pd。在查看查询时,在这种情况下奇怪的行为是,这个测试中的逻辑路径第一个方法查找持久化组并且因为它们已经退出已经将新用户记录保存在其表中并在链接表中插入新记录..但是就像Hibernate假设Groups是新记录并尝试将它们插入到组表中一样,当然这会抛出重复的异常...但我还没想出来......

我该怎么办?我在这里做错了什么?

提前致谢。

@Test
    public void guardarUsuario(){
        assertThat(servicio, is(notNullValue()));
        Usuario u = new Usuario();
        u.setNombre("Elsy");
        u.setApellido("Cadenas");
        u.setCedula("4375792");     

        List<Grupo> grupos = servicio.buscarGrupos();

        u.getGrupos().addAll(grupos);

        servicio.guardarUsuario(u);


    }

Hibernate: select grupo0_.nombre as nombre1_, grupo0_.descripcion as descripc2_1_ from public.grupo grupo0_
Hibernate: select usuarios0_.idgrupo as idgrupo1_1_, usuarios0_.idusuario as idusuario1_, usuario1_.cedula as cedula0_0_, usuario1_.apellido as apellido0_0_, usuario1_.nombre as nombre0_0_, usuario1_.version as version0_0_ from usuario_grupo usuarios0_ inner join public.usuario usuario1_ on usuarios0_.idusuario=usuario1_.cedula where usuarios0_.idgrupo=?
Hibernate: select usuarios0_.idgrupo as idgrupo1_1_, usuarios0_.idusuario as idusuario1_, usuario1_.cedula as cedula0_0_, usuario1_.apellido as apellido0_0_, usuario1_.nombre as nombre0_0_, usuario1_.version as version0_0_ from usuario_grupo usuarios0_ inner join public.usuario usuario1_ on usuarios0_.idusuario=usuario1_.cedula where usuarios0_.idgrupo=?
Hibernate: select usuario0_.cedula as cedula0_0_, usuario0_.apellido as apellido0_0_, usuario0_.nombre as nombre0_0_, usuario0_.version as version0_0_ from public.usuario usuario0_ where usuario0_.cedula=?
Hibernate: insert into public.usuario (apellido, nombre, version, cedula) values (?, ?, ?, ?)
Hibernate: insert into public.grupo (descripcion, nombre) values (?, ?)
Hibernate: insert into public.grupo (descripcion, nombre) values (?, ?)
2469 [main] WARN  org.hibernate.util.JDBCExceptionReporter  - SQL Error: 0, SQLState: 23505
2469 [main] ERROR org.hibernate.util.JDBCExceptionReporter  - Batch entry 0 insert into public.grupo (descripcion, nombre) values ('usuarios', 'USUARIO') was aborted.  Call getNextException to see the cause.
2469 [main] WARN  org.hibernate.util.JDBCExceptionReporter  - SQL Error: 0, SQLState: 23505
2469 [main] ERROR org.hibernate.util.JDBCExceptionReporter  - ERROR: duplicate key value violates unique constraint "pk_grupo"

User.class

@Entity()
@Table(name = "usuario", schema = "public")
@NamedQuery(name = "Usuario.findByCedula", query = "select u from Usuario u where u.cedula = :cedula")
public class Usuario implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private String nombre;
    private String apellido;
    @Id
    @Column(length = 8)
    private String cedula;
    @Version
    private Integer version;
    @JoinTable(name = "usuario_grupo", joinColumns = { @JoinColumn(name = "idusuario", referencedColumnName = "cedula") }, inverseJoinColumns = { @JoinColumn(name = "idgrupo", referencedColumnName = "nombre") })
    @ManyToMany(cascade =  { CascadeType.PERSIST }, fetch = FetchType.LAZY)
    private Set<Grupo> grupos = new HashSet<Grupo>();

    Constructors... Getters and setters...

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((cedula == null) ? 0 : cedula.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;
        Usuario other = (Usuario) obj;
        if (cedula == null) {
            if (other.cedula != null)
                return false;
        } else if (!cedula.equals(other.cedula))
            return false;
        return true;
    }

    public void addGrupo(Grupo g) {
        if (!getGrupos().contains(g)) {
            getGrupos().add(g);
        }
        if (!g.getUsuarios().contains(this)) {
            g.getUsuarios().add(this);
        }
    }

Group.class

@Entity
@Table(name="grupo", schema="public")
public class Grupo implements Serializable{


    private static final long serialVersionUID = 1L;
    @Id
    private String nombre;
    private String descripcion;
    @JoinTable(name="usuario_grupo", joinColumns={@JoinColumn(name="idgrupo")}, inverseJoinColumns=@JoinColumn(name="idusuario"))
    @ManyToMany(cascade={CascadeType.PERSIST}, fetch=FetchType.EAGER)
    private Set<Usuario> usuarios = new HashSet<Usuario>(); 

    Constructors... Getters and Setters...

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result
                + ((descripcion == null) ? 0 : descripcion.hashCode());
        result = prime * result + ((nombre == null) ? 0 : nombre.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;
        Grupo other = (Grupo) obj;
        if (descripcion == null) {
            if (other.descripcion != null)
                return false;
        } else if (!descripcion.equals(other.descripcion))
            return false;
        if (nombre == null) {
            if (other.nombre != null)
                return false;
        } else if (!nombre.equals(other.nombre))
            return false;
        return true;
    }
}

SQL:

USER Table


-- Table: usuario

-- DROP TABLE usuario;

CREATE TABLE usuario
(
  nombre character varying(50),
  apellido character varying(50),
  cedula character varying(8) NOT NULL,
  "version" integer,
  CONSTRAINT pk_usuario PRIMARY KEY (cedula)
)
WITH (
  OIDS=FALSE
);
ALTER TABLE usuario OWNER TO postgres;

GROUP表

-- Table: grupo

-- DROP TABLE grupo;

CREATE TABLE grupo
(
  nombre character varying(20) NOT NULL,
  descripcion character varying(50),
  CONSTRAINT pk_grupo PRIMARY KEY (nombre)
)
WITH (
  OIDS=FALSE
);
ALTER TABLE grupo OWNER TO postgres;

链接表

-- Table: usuario_grupo

-- DROP TABLE usuario_grupo;

CREATE TABLE usuario_grupo
(
  idusuario character varying(8) NOT NULL,
  idgrupo character varying(20) NOT NULL,
  CONSTRAINT pk_id_grupo PRIMARY KEY (idusuario, idgrupo),
  CONSTRAINT fk_miembro_grupo FOREIGN KEY (idgrupo)
      REFERENCES grupo (nombre) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT fk_miembro_usuario FOREIGN KEY (idusuario)
      REFERENCES usuario (cedula) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION
)
WITH (
  OIDS=FALSE
);
ALTER TABLE usuario_grupo OWNER TO postgres;

1 个答案:

答案 0 :(得分:0)

我认为Usuario和Grupo之间的ManyToMany关系可能是持久存在于Grupo表中的值。当它说它的PK的唯一约束被破坏时,例外是非常自我描述的。

不要级联持续操作,你应该没事。