2
votes

I am using JPA annotations and when i have relation OneToMany - ManyToOne, when i see my entity in the ManyToOne, the joinColumn is always with null value.

Next i will show my example, i have Product:

  @Entity
  @Table(name = "PC_PRODUCT")

  public class Product extends LaunchEntity {

  private static final long serialVersionUID = 1L;

  @XmlElement(name = "Product_Name", required = true)
  protected String productName;

  @XmlElement(name = "Product_Description")
  protected String productDescription;

  @XmlElement(name = "Product_To_Charge")
  @OneToMany(mappedBy = "product", cascade=CascadeType.MERGE)
  protected List<ChargeRelation> productToCharge;

And, this is my ChargeRelation class:

@Entity
@Table(name="PC_CHARGE_RELATION")
public class ChargeRelation
    extends RelationEntity
{

    private static final long serialVersionUID = 1L;

    @XmlElement(name = "Charge", required = true)
    @OneToOne(cascade = CascadeType.MERGE)
    protected Charge charge;

    @XmlTransient
    @ManyToOne(cascade=CascadeType.MERGE)
    @JoinColumn(name="PRODUCT_ID")
    protected Product product;

I am reading a xml file, convert data for a string, make unmarshall for my root object and persist this object.

The problem is when i found a charge relation in my string, the values are inserted on the charge relation table but the column with the product_id is always null.

I have all setters and getters defined. How i can force this to make the manual insert? thanks

2

2 Answers

2
votes

Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB 2 (JSR-222) expert group.

EclipseLink JAXB (MOXy) has an extension called @XmlInverseReference that allows you to map the back-pointer.

Product

@Entity
@Table(name = "PC_PRODUCT")
public class Product extends LaunchEntity {

    @XmlElement(name = "Product_To_Charge")
    @OneToMany(mappedBy = "product", cascade=CascadeType.MERGE)
    protected List<ChargeRelation> productToCharge;

}

ChargeRelation

The @XmlInverseReference annotation is used where you previously had @XmlTransient. @XmlInverseReference acts like @XmlTransient during the marshal operation, and will populate the back-pointer during an unmarshal operation.

@Entity
@Table(name="PC_CHARGE_RELATION")
public class ChargeRelation extends RelationEntity {

    @XmlInverseReference(mappedBy = "productToCharge")
    @ManyToOne(cascade=CascadeType.MERGE)
    @JoinColumn(name="PRODUCT_ID")
    protected Product product;
}

For More Information

2
votes

Note that JPA provider reflects the state of many-to-one side of relationship when saving it to the database.

However, JAXB only populates one-to-many side during XML unmarshalling, therefore you need to populate many-to-one side manually after unmarshalling.