繁体   English   中英

Spring Hibernate:持久存在具有多对多关系和复合键的实体

[英]Spring hibernate : Persisting an entity with many-to-many relation and a composite key

我有两个通过多对多关系链接的实体,该关系的所有者具有复合主键,该主键是用@Emebbedable注释的类。 这是实体类:

Reservation.java:

@Entity
@NamedQuery(name="Reservation.findAll", query="SELECT r FROM Reservation r")
public class Reservation implements Serializable {
private static final long serialVersionUID = 1L;

@EmbeddedId
private ReservationPK id;

private int actif;

private String commentaire;

@Column(name="date_creation")
private Timestamp dateCreation;

@Column(name="date_liberation")
private Timestamp dateLiberation;

private int indice;

private String libelle;

private String nom;

//bi-directional many-to-many association to Composant
@LazyCollection(LazyCollectionOption.FALSE)
@ManyToMany
@JoinTable(
        name="resa_comp"
        , joinColumns={
                @JoinColumn(name="id_env", referencedColumnName="id_env"),
                @JoinColumn(name="id_reserv", referencedColumnName="id_reserv")
            }
        , inverseJoinColumns={
                @JoinColumn(name="id_comp")
            }
    )
@JsonBackReference
private List<Composant> composants;

// getters and setters ...

ReservationPK.java:

@Embeddable
public class ReservationPK implements Serializable {
//default serial version id, required for serializable classes.
private static final long serialVersionUID = 1L;

@Column(name="id_reserv")
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int idReserv;

@Column(name="id_env", insertable=false, updatable=false)
private int idEnv;

public ReservationPK() {
}
public int getIdReserv() {
    return this.idReserv;
}
public void setIdReserv(int idReserv) {
    this.idReserv = idReserv;
}
public int getIdEnv() {
    return this.idEnv;
}
public void setIdEnv(int idEnv) {
    this.idEnv = idEnv;
}

public boolean equals(Object other) {
    if (this == other) {
        return true;
    }
    if (!(other instanceof ReservationPK)) {
        return false;
    }
    ReservationPK castOther = (ReservationPK)other;
    return 
        (this.idReserv == castOther.idReserv)
        && (this.idEnv == castOther.idEnv);
}

public int hashCode() {
    final int prime = 31;
    int hash = 17;
    hash = hash * prime + this.idReserv;
    hash = hash * prime + this.idEnv;

    return hash;
}

Composant.java:

@Entity
@NamedQuery(name="Composant.findAll", query="SELECT c FROM Composant c")
public class Composant implements Serializable {
private static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="id_comp")
private int idComp;

@Size(max=250)
@Column(name="attribut_1")
private String attribut1;

@Size(max=250)
@Column(name="attribut_2")
private String attribut2;

@Size(max=250)
@Column(name="attribut_3")
private String attribut3;

@Size(max=250)
@Column(name="attribut_4")
private String attribut4;

@Size(max=250)
@Column(name="attribut_5")
private String attribut5;


//bi-directional many-to-many association to Reservation
@LazyCollection(LazyCollectionOption.FALSE)
@ManyToMany(mappedBy="composants")
@JsonManagedReference
private List<Reservation> reservations; 

当我尝试使用getCurrentSession.save() 保留包含Composant列表的Reservation实例时,出现以下错误:

com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails (`scott`.`resa_comp`, CONSTRAINT `fk_reservation_has_composant_reservation1` FOREIGN KEY (`id_reserv`, `id_env`) REFERENCES `reservation` (`id_reserv`, `id_env`) ON DELETE NO ACTION ON UPDATE N)

我可以在日志文件中看到hibernate尝试使用id_reserv = 0将记录插入关系表中,有什么方法可以使hibernate在将记录插入关系表中时使用正确的ID?

我试图通过尝试先保存保留对象,然后再链接composant列表,然后更新保留,来修改位于服务层中的保存方法,但是我遇到了同样的错误。 供参考的是我的DAO和服务层的save方法:

saveDao:

 @Override
public Reservation save(Reservation r) {
    // TODO Auto-generated method stub
    ReservationPK idResaPK =  (ReservationPK)   this.sessionFactory.getCurrentSession().save(r);
    System.out.println("id resa saved = "+idResaPK.getIdReserv());
    return this.getById(idResaPK);
}

saveService:

    @Override
public Reservation save(Reservation r) {
    // TODO Auto-generated method stub
    if(r.getComposants().isEmpty()) {
        logger.info("you are here ! empty");
        return this.resDao.save(r);
    }
    else {
        logger.info("you are here ! full");
        List<Composant> listComp = new ArrayList<Composant>();
        listComp.addAll(r.getComposants());
        for (Composant composant : r.getComposants()) {
            //listComp.add(composant);
            composant.setReservations(new ArrayList<Reservation>());
        }
        r.setComposants(new ArrayList<Composant>());
        if( r.getComposants() != null) {
            for (Composant comp : r.getComposants()) {
                logger.info("you are here jsdhjshqdlkhdjh :"+comp.getNom());
            }
        }
        Reservation resaSaved = this.resDao.save(r);
        logger.info("done saving : "+resaSaved.getId().getIdReserv());
        resaSaved.setComposants(listComp);
        ArrayList<Reservation> resaList = new ArrayList<Reservation>();
        resaList.add(r);
        for (Composant compo : listComp) {
            compo.setReservations(resaList);
        }
        this.resDao.update(resaSaved);
        logger.info("done updating");
        return r;

    }

}

提前致谢。

在将原始数据类型用作主键的地方,将标有@Id注释的属性的数据类型更改为原始包装器类。 保存新实体时,id属性的值为零,而使用原始包装器时,值为NULL。 在保留新实体时,id值应为null,而此处为0。

进行以下更改:

//ReservationPK class
@Column(name="id_reserv")
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer idReserv;//instead of int

@Column(name="id_env", insertable=false, updatable=false)
private Integer idEnv;//instead of int

//Composant class
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="id_comp")
private Integer idComp; //instead of int

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM