Search code examples
javaoraclejpaeclipselinkjpa-2.0

JPA eclipselink Inheritance between entities : oracle database


I'm facing a little problem with my web application which is in vaadin and i'm using jpa and eclipselink for the mapping. I have three entities :

                    encaiss (@MappedSuperclass contains just Id)
                       |
                       |
                  Encaissement (it contains the main and common properties)
                     /              \
                    /                \
   Encaissement_Technique          Encaissement_espece

When i create an entity "Encaissement" with "Espece" as type, it is well created in the table Encaissement but it doesn't exist in the table Encaissement_espece.

I guess that I should join the two tables according to the identifier (ID) which is in a @MappedSuperclass class. I would appreciate any help for managing my subordinate class (that is Encaissement_Technique and Encaissement_espece) because my next step would be to add records to those two tables from a simple form (so if i have a field "libelle" which is present in Encaissement but not in Encaissement_Espece how can make such instruction :

Encaissement_Espece  espece= new Encaissement_Espece();
espece.setLibelle(field.getValue().toString()); 

Those are my entities :

encaiss, this class contain just the Id for all the classes

@MappedSuperclass
public abstract class encaiss {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO, generator="encaiss_seq_gen")
    @SequenceGenerator(name="encaiss_seq_gen", sequenceName="ENCAISSEMENT_SEQ", allocationSize = 1, initialValue = 1)
    protected Integer id_encaissement;

    public Integer getId_encaissement() {
        return id_encaissement;
    }

    public void setId_encaissement(Integer id_encaissement) {
        this.id_encaissement = id_encaissement;
    }
}

Encaissement (wich extend encaiss just to have an Id)

@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")
    private Client Client;
@Column(name="ENCAISS_TYPE")
    protected String encaiss_type;
    @Column(name="LIBELLE")
    protected String libelle;
    @Column(name="PIECE_JOINTE")
    protected String piece_jointe;
    @Embedded
    protected Avis_Recette avis_recette;

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

    public Encaissement(){

    }

}

Encaissement_Espece, inherits from Encaissement

@Entity
@DiscriminatorValue("Espece")
@Table(name="ENCAISSEMENT_ESPECE")
public class Encaissement_Espece extends Encaissement{

    public Caisse getCaisse() {
        return caisse;
    }

    public void setCaisse(Caisse caisse) {
        this.caisse = caisse;
    }

    public float getMontant() {
        return montant;
    }

    public void setMontant(float montant) {
        this.montant = montant;
    }

    @ManyToOne(cascade = CascadeType.PERSIST, fetch = FetchType.LAZY)
    @JoinColumn(name = "ID_CAISSE")
    private Caisse caisse;

    @Column(name = "MONTANT")
    private float montant;

    public Encaissement_Espece(float montant){
        this.montant=montant;
    }

    public Encaissement_Espece(){

    }

}

Encaissement_Technique, inherits from Encaissement

@Entity
@DiscriminatorValue("Technique")
@Inheritance(strategy=InheritanceType.JOINED)
@DiscriminatorColumn(name="ENCAISS_TECHNIQUE_TYPE")
@Table(name="ENCAISSEMENT_TECHNIQUE")
public class Encaissement_Technique extends Encaissement implements Serializable{

    public Banque getBanque() {
        return banque;
    }

    public void setBanque(Banque banque) {
        this.banque = banque;
    }

    public float getPrimeCoass() {
        return primeCoass;
    }

    public void setPrimeCoass(float primeCoass) {
        this.primeCoass = primeCoass;
    }
    public Set<Periode> getPeriode() {
        return periode;
    }

    public void setPeriode(Set<Periode> periode) {
        this.periode = periode;
    }

    public String getEncaiss_technique_type() {
        return encaiss_technique_type;
    }

    public void setEncaiss_technique_type(String encaiss_technique_type) {
        this.encaiss_technique_type = encaiss_technique_type;
    }
@Column(name="PRIMECOASS")
    protected float primeCoass;
    @Column(name="ENCAISS_TECHNIQUE_TYPE")
    protected String encaiss_technique_type;

    public Encaissement_Technique(float primeCoass, String encaiss_technique_type){
        this.primeCoass=primeCoass;
        this.encaiss_technique_type=encaiss_technique_type;
    }

    public Encaissement_Technique(){

    }

}

This is a screen shot of the tables' description

I hope i will find a pertinent answer as i searched for this in vain. It'll help me a lot.

Thank you.


Solution

  • "When i create an entity "Encaissement" with "Espece" as type, it is well created in the table Encaissement but it doesn't exist in the table Encaissement_espece." This statement suggests you have an instance of Encaissement and expect JPA to turn it into an instance of Encaissement_Espece just by changing the encaiss_type value. Java object inheritance doesn't work that way, which is what JPA inheritance tries to map to a relational database. An object in java cannot change what it is simply by setting a flag - you need to create a new instance if you want the data represented differently.

    In this case, you need to create an instance of the Encaissement_Espece class. Because this class maps to the Encaissement and Encaissement_espece tables, JPA will automatically insert a row into both to represent this object. When you create Encaissement instance, a row goes into the Encaissement table, while when you create Encaissement_Technique instances, a row goes into both Encaissement_Technique and Encaissement tables. If you wish to change the object's type once it is persisted, you need to remove the old instance, flush, then persist the new one.

    As mentioned in another answer, the encaiss_type is controlled through the class type itself and so does not need a mapping. Having one might be handy for queries or access (though you can just use instance of etc); it should be marked as insertable=false, updatable=false so that you do not attempt to modify the value directly.