Stefano Zenny
Stefano Zenny

Reputation: 61

HIbernate - JPA: foreign key not set in ManyToOne relationship

I know this might be a common problem but so far I couldn't find any solution.

I have the following 2 entities: Mission and Representation. Both entities have composed primary keys, respectively:

There's a one-to-many relationship between Representation and Mission, meaning that each mission has a single representation and each representation can be used in different missions.

I use JPA repositories to persist the entities in my database:

public interface RepresentationDao extends JpaRepository <Representation, RepresentationId> 

public interface MissionDao extends JpaRepository <Mission, MissionId> 

I need to save first a set of representations, and THEN a set of missions. The representations work correctly, but when I try to save a mission the foreign key to the representation remains empty.

This is my code:

// here representations are already persisted (in a separate transaction)..

RepresentationId representationId = new RepresentationId(idImpXml, codeRepresentation);
Representation representation = representationDao.findOne(representationId);

// representation is retrieved correctly

MissionId missionId = new MissionId(idImpXml, code, categorie);
Mission mission = new Mission(missionId, representation, label);

// I try to save the mission
missionDao.saveAndFlush(mission);

// THE FOREIGN KEY THAT SHOULD REFERENCE THE REPRESENTATION (CODE_REPRESENTATION) REMAINS NULL

Mission

@Entity
@Table(name = "MISSION", schema = "dbo", catalog ="TEST")
public class Mission implements java.io.Serializable {

    private MissionId id;
    private Representation representation;
    private String label;

    public Mission() {
    }

    public Mission(MissionId id, Representation representation, String label) {
        this.id = id;
        this.representation = representation;
        this.label = label;
    }

    @EmbeddedId
    @AttributeOverrides({
            @AttributeOverride(name = "idImpXml", column = @Column(name = "ID_IMP_XML", nullable = false, precision = 38, scale = 0)),
            @AttributeOverride(name = "code", column = @Column(name = "CODE", nullable = false)),
            @AttributeOverride(name = "categorie", column = @Column(name = "CATEGORIE", nullable = false)) })
    public MissionId getId() {
        return this.id;
    }

    public void setId(MissionId id) {
        this.id = id;
    }


    @MapsId("ID_IMP_XML")
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumns(
        value={ @JoinColumn(name = "ID_IMP_XML", referencedColumnName = "ID_IMP_XML", updatable=false),
                @JoinColumn(name = "CODE_REPRESENTATION", referencedColumnName = "CODE_REPRESENTATION", insertable=true, updatable=true)
            })
    public Representation getRepresentation() {
        return this.representation;
    }

    public void setRepresentation(Representation representation) {
        this.representation = representation;
    }

    @Column(name = "LABEL", nullable = false)
    public String getLabel() {
        return this.label;
    }

    public void setLabel(String label) {
        this.label = label;
    }


}

MissionId

@Embeddable
public class MissionId implements java.io.Serializable {

    private Long idImpXml;
    private String code;
    private int categorie;

    public MissionId() {
    }

    public MissionId(Long idImpXml, String code, int categorie) {
        this.idImpXml = idImpXml;
        this.code = code;
        this.categorie = categorie;
    }

    @Column(name = "ID_IMP_XML", nullable = false, precision = 38, scale = 0)
    public Long getIdImpXml() {
        return this.idImpXml;
    }

    public void setIdImpXml(Long idImpXml) {
        this.idImpXml = idImpXml;
    }

    @Column(name = "CODE", nullable = false)
    public String getCode() {
        return this.code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    @Column(name = "CATEGORIE", nullable = false)
    public int getCategorie() {
        return this.categorie;
    }

    public void setCategorie(int categorie) {
        this.categorie = categorie;
    }

    public boolean equals(Object other) {
        if ((this == other))
            return true;
        if ((other == null))
            return false;
        if (!(other instanceof MissionId))
            return false;
        MissionId castOther = (MissionId) other;

        return ((this.getIdImpXml() == castOther.getIdImpXml()) || (this.getIdImpXml() != null
                && castOther.getIdImpXml() != null && this.getIdImpXml().equals(castOther.getIdImpXml())))
                && ((this.getCode() == castOther.getCode()) || (this.getCode() != null && castOther.getCode() != null
                        && this.getCode().equals(castOther.getCode())))
                && (this.getCategorie() == castOther.getCategorie());
    }

    public int hashCode() {
        int result = 17;

        result = 37 * result + (getIdImpXml() == null ? 0 : this.getIdImpXml().hashCode());
        result = 37 * result + (getCode() == null ? 0 : this.getCode().hashCode());
        result = 37 * result + this.getCategorie();
        return result;
    }

}

Representation

@Entity
@Table(name = "REPRESENTATION", schema = "dbo", catalog ="TEST")
public class Representation implements Serializable {

    private RepresentationId id;
    private Long colorPattern;
    private String typePattern;
    private Integer thickness;

    public Representation() {
    }

    public Representation(RepresentationId id) {
        this.id = id;
    }

    public Representation(RepresentationId id, Long colorPattern, String typePattern,
            Integer thickness, Long codeCouleurPattern2, String typePattern2, Integer epaisseurPattern2) {
        this.id = id;
        this.colorPattern = colorPattern;
        this.typePattern = typePattern;
        this.thickness = thickness;
    }

    @EmbeddedId

    @AttributeOverrides({
            @AttributeOverride(name = "idImpXml", column = @Column(name = "ID_IMP_XML", nullable = false, precision = 38, scale = 0)),
            @AttributeOverride(name = "codeRepresentation", column = @Column(name = "CODE_REPRESENTATION", nullable = false)) })
    public RepresentationId getId() {
        return this.id;
    }

    public void setId(RepresentationId id) {
        this.id = id;
    }

    @Column(name = "COLOR_PATTERN")
    public Long getColorPattern() {
        return this.colorPattern;
    }

    public void setColorPattern(Long colorPattern) {
        this.colorPattern = colorPattern;
    }

    @Column(name = "TYPE_PATTERN")
    public String getTypePattern() {
        return this.typePattern;
    }

    public void setTypePattern(String typePattern) {
        this.typePattern = typePattern;
    }

    @Column(name = "THICKNESS")
    public Integer getThickness() {
        return this.thickness;
    }

    public void setThickness(Integer thickness) {
        this.thickness = thickness;
    }

}

RepresentationId

@Embeddable
public class RepresentationId implements java.io.Serializable {

    private Long idImpXml;
    private int codeRepresentation;

    public RepresentationId() {
    }

    public RepresentationId(Long idImpXml, int codeRepresentation) {
        this.idImpXml = idImpXml;
        this.codeRepresentation = codeRepresentation;
    }

    @Column(name = "ID_IMP_XML", nullable = false, precision = 38, scale = 0)
    public Long getIdImpXml() {
        return this.idImpXml;
    }

    public void setIdImpXml(Long idImpXml) {
        this.idImpXml = idImpXml;
    }

    @Column(name = "CODE_REPRESENTATION", nullable = false)
    public int getCodeRepresentation() {
        return this.codeRepresentation;
    }

    public void setCodeRepresentation(int codeRepresentation) {
        this.codeRepresentation = codeRepresentation;
    }

    public boolean equals(Object other) {
        if ((this == other))
            return true;
        if ((other == null))
            return false;
        if (!(other instanceof RepresentationId))
            return false;
        RepresentationId castOther = (RepresentationId) other;

        return ((this.getIdImpXml() == castOther.getIdImpXml()) || (this.getIdImpXml() != null
                && castOther.getIdImpXml() != null && this.getIdImpXml().equals(castOther.getIdImpXml())))
                && (this.getCodeRepresentation() == castOther.getCodeRepresentation());
    }

    public int hashCode() {
        int result = 17;

        result = 37 * result + (getIdImpXml() == null ? 0 : this.getIdImpXml().hashCode());
        result = 37 * result + this.getCodeRepresentation();
        return result;
    }

}

Upvotes: 1

Views: 1520

Answers (1)

scricci85
scricci85

Reputation: 43

try to override column definition by adding another field in your object and set the insertable and updatable properties to false in the @JoinColum, like this:

@MapsId("ID_IMP_XML")
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumns(
    value={ @JoinColumn(name = "ID_IMP_XML", referencedColumnName = "ID_IMP_XML", insertable=false, updatable=false),
            @JoinColumn(name = "CODE_REPRESENTATION", referencedColumnName = "CODE_REPRESENTATION", insertable=false, updatable=false)
        })
public Representation getRepresentation() {
    return this.representation;
}

private Integer representationCode;
@Column(name = "CODE_REPRESENTATION")
public Integer getRepresentationCode() {
    return this.representationCode;
}

Upvotes: 1

Related Questions