简体   繁体   English

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

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

I have two entites linked by a many-to-many relationship , the owner of the relationship has a composite primary key which is a class annotated with @Emebbedable. 我有两个通过多对多关系链接的实体,该关系的所有者具有复合主键,该主键是用@Emebbedable注释的类。 Here are the entity classes : 这是实体类:

Reservation.java : 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 : 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 : 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; 

when i try to persist an instance of Reservation containing a List of Composant by using getCurrentSession.save() i get this error : 当我尝试使用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)

I can see in the log file that hibernate is trying to insert a record into the relationship table using an id_reserv = 0 is there any way to make hibernate use the correct id when inserting records into the relationship table ? 我可以在日志文件中看到hibernate尝试使用id_reserv = 0将记录插入关系表中,有什么方法可以使hibernate在将记录插入关系表中时使用正确的ID?

i tried to modify my save methode located in my service layer by trying to save the Reservation object first before linking the list of composant and then updating the reservation but i get the same error. 我试图通过尝试先保存保留对象,然后再链接composant列表,然后更新保留,来修改位于服务层中的保存方法,但是我遇到了同样的错误。 for reference here are my DAO and service layer's save method : 供参考的是我的DAO和服务层的save方法:

saveDao : 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 : 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;

    }

}

Thanks in advance. 提前致谢。

change the data types of properties marked with @Id annotation to primitive wrapper classes wherever primitive data type is used as primary key. 在将原始数据类型用作主键的地方,将标有@Id注释的属性的数据类型更改为原始包装器类。 While saving a new entity, id property will have value zero whereas when primitive wrapper is used value will be NULL. 保存新实体时,id属性的值为零,而使用原始包装器时,值为NULL。 While persisting new entity , id value should be null whereas here it is 0. 在保留新实体时,id值应为null,而此处为0。

Do the following changes: 进行以下更改:

//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