Search code examples
javaoraclejpamany-to-manyeclipselink

many to many extra column eclipselink doesn't work


I'm trying to represent a many to many association with an extra column (date) as follows :

Encaissement(id)-----Etat_Encaissement(id_etat) (many to many relationship)

The new association is EncaissementEtatEncaissement that will have the both IDs of the two entities and an extra column Date-Etat.

I've followed this documentation and did exactly the same steps. Here is my classes : ====================Entity Encaissement======================

@Entity
@Inheritance(strategy=InheritanceType.JOINED)
@DiscriminatorColumn(name="ENCAISS_TYPE")
@Table(name="ENCAISSEMENT")
public class Encaissement extends encaiss implements Serializable{

    @ManyToOne(cascade = CascadeType.PERSIST, fetch = FetchType.LAZY)
    @JoinColumn(name = "ID_CLIENT")
    protected Client Client;


    @OneToMany(cascade = CascadeType.PERSIST, fetch = FetchType.LAZY, mappedBy="encaissement")
    protected Set<EncaissementEtatEncaissement> etats_enc_etats;

    // Ajouter un etat a l'encaissement.
    public void addEtat(Etat_Encaissement etat, Date dateEtat) {
      EncaissementEtatEncaissement encaiss_etat_encaiss = new EncaissementEtatEncaissement();
      encaiss_etat_encaiss.setEtat_encaissements(etat);
      encaiss_etat_encaiss.setEncaissement(this);
      encaiss_etat_encaiss.setId_etat_encaissement(etat.getId_etat_encaissement());
      encaiss_etat_encaiss.setId_encaissement(this.getId_encaissement());
      encaiss_etat_encaiss.setDateEtat(dateEtat);

      this.etats_enc_etats.add(encaiss_etat_encaiss);
      // Also add the association object to the etat.
      etat.getEncaissements().add(encaiss_etat_encaiss);
    }

    @Column(name="LIBELLE")
    protected String libelle;
    @Column(name="PIECE_JOINTE")
    protected String piece_jointe;
    public Set<EncaissementEtatEncaissement> getEtats_enc_etats() {
        return etats_enc_etats;
    }

    public void setEtats_enc_etats(Set<EncaissementEtatEncaissement> etats_enc_etats) {
        this.etats_enc_etats = etats_enc_etats;
    }

    @Temporal(TemporalType.DATE)
    @Column(name="DATE_ENCAISSEMENT")
    protected Date date_encaissement;
    @Embedded
    protected Avis_Recette avis_recette;

    public Encaissement(String libelle, String piece_jointe, Date date_encaissement){
        this.libelle=libelle;
        this.piece_jointe=piece_jointe;
        this.date_encaissement=date_encaissement;
    }

    public Encaissement(){

    }

}

====================Entity Etat_Encaissement======================

@Entity
@Table(name="ETAT_ENCAISSEMENT")
public class Etat_Encaissement implements Serializable{

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO, generator="etat_encaissement_seq_gen")
    @SequenceGenerator(name="etat_encaissement_seq_gen", sequenceName="ETAT_ENCAISSEMENT_SEQ", allocationSize = 1, initialValue = 1)
    private long id_etat_encaissement; 

    //@ManyToMany(mappedBy="etats", cascade = CascadeType.PERSIST, fetch = FetchType.LAZY)
    //private Set<Encaissement> Encaissements;

    @OneToMany(mappedBy="etat_encaissements")
    private Set<EncaissementEtatEncaissement> encaissements;


    @Column(name="LIBELLE")
    private String libelle;

    public Etat_Encaissement(String libelle){ 
        this.libelle=libelle;
    }

    public Etat_Encaissement(){

    }

}

================Entity Encaissement_Etat_Encaissement==================== This entity is contain the id of Encaissement and Etat_Encaissement plus a date column

@Entity
@Table(name="ENCAISSEMENT_ETAT_ENCAISSEMENT")
@IdClass(EncaissementEtatEncaissementId.class)
public class EncaissementEtatEncaissement {

      @Id
      private long id_etat_encaissement;
      @Id
      private long id_encaissement;


      @Temporal(TemporalType.DATE)
      @Column(name="DATE_ETAT_ENCAISS")
      private Date dateEtat;

      @ManyToOne
      @PrimaryKeyJoinColumn(name="ID_ETAT_ENCAISSEMENT", referencedColumnName="ID_ETAT_ENCAISSEMENT")

      private Etat_Encaissement etat_encaissements;

    @ManyToOne
      @PrimaryKeyJoinColumn(name="ID_ENCAISSEMENT", referencedColumnName="ID_ENCAISSEMENT")
false, referencedColumnName = "id")

      private Encaissement encaissement;


        public EncaissementEtatEncaissement(Date dateEtat){
            this.dateEtat=dateEtat;
        }

        public EncaissementEtatEncaissement(){

        }
}

And finaly the Id of this last class :

public class EncaissementEtatEncaissementId implements Serializable{

    private long id_etat_encaissement;

    private long id_encaissement;

    public int hashCode() {
        return (int)(id_etat_encaissement + id_encaissement);
      }

    public boolean equals(Object object) {
        if (object instanceof EncaissementEtatEncaissementId) {
            EncaissementEtatEncaissementId otherId = (EncaissementEtatEncaissementId) object;
          return (otherId.id_etat_encaissement == this.id_etat_encaissement) && (otherId.id_encaissement == this.id_encaissement);
        }
        return false;
      }

}

==============i use this simple code to associated an instance of Etat_encaissement to Encaissement, normally a new row will be added to Encaissement_Etat_Encaissement =============================

private Etat_Encaissement etat_record;

    //Code here

etat_record=saut.getEtatFromLibelle("source_identifiee");//This just return an instance of Etat

encaissEspece.addEtat(etat_record, new java.util.Date()); // here i call addEtat which trigger the problem 

Problem :

I get java.lang.Exception in the addEtat method which is in the class Encaissement [ this.etats_enc_etats.add(encaiss_etat_encaiss); ] and the log indicates that etats_enc_etats is null So i can not add the Encaissement_Etat (record in this case) to the Encaissement (encaissEspece in this case) and all of this because an instance of etats_enc_etats==null

( again :

@OneToMany(cascade = CascadeType.PERSIST, fetch = FetchType.LAZY, mappedBy="encaissement")
    protected Set<EncaissementEtatEncaissement> etats_enc_etats; //)

Can anyone help me with this. Thank you.


Solution

  • The problem you are encountering is likely due to having @ID on basic mappings that you are not setting. Since these are null, JPA inserts null into the PK values. You have to manually set the ID mappings in your current setup, which requires first persisting the Encaissement and Etat_Encaissement instances and flushing so that their IDs are assigned, then use those values to set the EncaissementEtatEncaissement instance's id_etat_encaissement and id_encaissement values.

    If you are using JPA 2.1, you can mark the EncaissementEtatEncaissement etat_encaissements and encaissement relationships with @ID, and JPA will set the values for you:

    @Entity
    @Table(name="ENCAISSEMENT_ETAT_ENCAISSEMENT")
    @IdClass(EncaissementEtatEncaissementId.class)
    public class EncaissementEtatEncaissement {
    
      @Temporal(TemporalType.DATE)
      @Column(name="DATE_ETAT_ENCAISS")
      private Date dateEtat;
    
      @Id
      @ManyToOne
      @JoinColumn(name="ID_ETAT_ENCAISSEMENT", referencedColumnName="ID_ETAT_ENCAISSEMENT")
      private Etat_Encaissement etat_encaissements;
    
      @Id
      @ManyToOne
      @JoinColumn(name="ID_ENCAISSEMENT", referencedColumnName = "id")
      private Encaissement encaissement;
    ..
    }
    

    You can also use the @MapsId annotation and keep the id_etat_encaissement and id_encaissement attributes, but if you don't use them, you don't need them.