2

I am using classes which are JPA annotated to map xml data into a database and the other way around via JAXB. Problem is that objects created by JAXB do not include foreign key fields and therefore are null. This conerns ownerId in example below.

Is there a way to fix this without looping through the whole tree again and add foreign keys ?

@Entity    
public class Element {
    @Id
    String id;

    @OneToMany(mappedBy = "owner", fetch = FetchType.LAZY, cascade = CascadeType.ALL)    
    private List<Property> properties;     
}

@Entity    
public class Property {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int propertyId;

    @ManyToOne(optional = false, cascade = CascadeType.ALL)
    @PrimaryKeyJoinColumn(name = "ownerId", referencedColumnName = "id")
    private Element owner;
}
JInsider
  • 43
  • 5
  • do you use the same model in JPA and JAXB or do you map the JAXB beans to JPA beans? – S. Pauk Apr 09 '15 at 18:16
  • Yes it's the same model. There are jaxb annotations on the classes and getter and setter methods which I left out in the example above. – JInsider Apr 09 '15 at 20:59

2 Answers2

0

The relationship is owned by the Property so the Property has to know related Element object to have it saved to DB. Adding a property to the list inside the element is not enough.

for (Property p : element.getProperties()) p.setOwner(element);

will solve the problem with the key.

If you read data from XML, typically your Property will not contained the referenced Element, only Element would have the list of Included properties.

You may also want to remove CascateType.ALL from the ManyToONe in Property, as removing a Property will trigere removing its parent Element and all the related Properties, which is probably not what you wanted). But you may want to add orphanRemoval = true, to the OneToMany in Element, so if a property is removed from the list, it is also deleted in the DB.

Zielu
  • 8,312
  • 4
  • 28
  • 41
  • Thanks for your help. Unfortunatelly looping through all the properties sounds like quite a performance killer. I was hoping there would be another way. – JInsider Apr 09 '15 at 21:05
  • You can change the mapping, so that the relationship is managed by the Element not the property. As for the performance, any "automagical" solution would probably also loop throuhg a list, checked out an object cache etc. General rule is not to overoptimise before it is needed, inserting those objects into DB is at least 100 times slower than looping through them. – Zielu Apr 09 '15 at 21:18
  • I tried setting the element object in each property as you suggested. The foreign key in the database still remains NULL. Do I have to explicitly set the ownerId as well ? It is my understanding JPA should do that for me. – JInsider Apr 10 '15 at 08:54
0

What about adding ownerId property into your Property class like this?

    @Column("ownerId", insertable=false, updatable="false")
    private ownerId;

In this case you will have both ownerId and owner in your class. ownerId is read only and owner is used to assign/update values.

If you want to make it the opposite way around move insertable=false, updatable=false to owner property annotations.

Dmitry
  • 419
  • 3
  • 9