nibs
nibs

Reputation: 181

Unmarshalling JPA entity using JAXB

I'm having trouble in my JAX-RS service unmarshalling a JSON string back into my JPA entity with JAXB. Marshalling works and I get the following JSON string from the service:

{
    "id":1,
    "items":[{
        "id":{"pairName":"PAIR-1","eventId":1},
        "pair":{"name":"PAIR-1","val":1.0},"quantity":2}
    ]}
}

However, sending this string back to my service gives an error:

Internal Exception: java.sql.SQLIntegrityConstraintViolationException: Column EVENT_ID'  cannot accept a NULL value.
Error Code: -1
Call: INSERT INTO ITEM (QUANTITY, EVENT_ID, PAIR_NAME) VALUES (?, ?, ?) bind => [2, null, PAIR-1]

EVENT_ID is in the string, how do I get the object back? I'm using Java EE 5, JPA 1.0 with Jersey and EclipseLink.

JPA Entities

@Entity
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Event implements Serializable {    
    @Id
    private long id;

    @OneToMany(mappedBy = "event")
    @XmlInverseReference(mappedBy = "event")
    private List<Item> items;           
}

@Entity
@XmlAccessorType(XmlAccessType.FIELD)
public class Item implements Serializable {
    @EmbeddedId
    private ItemPk id;

    @ManyToOne(cascade = { CascadeType.ALL })
    private Pair pair;

    @ManyToOne
    @JoinColumn(name = "EVENT_ID")
    @XmlTransient
    private Event event;

    private int quantity;
}

@Embeddable
@XmlAccessorType(XmlAccessType.FIELD)
public class ItemPk implements Serializable {   
    @Column(name="PAIR_NAME", insertable=false, updatable=false)
    private String pairName;

    @Column(name="EVENT_ID", insertable=false, updatable=false)
    private long eventId;
}

@Entity
public class Pair implements Serializable { 
    @Id
    private String name;

    private float val;
}

JAX-RS service

@Path("/events")
public class EventService {

    private EntityManagerFactory entityManagerFactory;

    @SuppressWarnings("unchecked")
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public List<Event> list() {
        if (entityManagerFactory == null) {
            entityManagerFactory = Persistence.createEntityManagerFactory("service");
        }
        EntityManager entityManager = entityManagerFactory.createEntityManager();
        Query query = entityManager.createNamedQuery("Event.findAll");
        return query.getResultList();
    }

    @PUT
    @Consumes(MediaType.APPLICATION_JSON)
    public void update(Event event) {
        if (entityManagerFactory == null) {
            entityManagerFactory = Persistence.createEntityManagerFactory("service");
        }
        EntityManager entityManager = entityManagerFactory.createEntityManager();
        entityManager.getTransaction().begin();
        entityManager.merge(event);
        entityManager.getTransaction().commit();
    }
}

Upvotes: 2

Views: 807

Answers (1)

Nikos Paraskevopoulos
Nikos Paraskevopoulos

Reputation: 40318

It could be that ItemPk.eventId is insertable=false, updatable=false, so JPA does not try to insert this field. Instead it tries to insert the field Item.event as SQL EVENT_ID. BUT the Item.event is @XmlTransient, thus not read from the JSON, thus null.

Maybe you should set insertable=false, updatable=false to the relations in Item (fields pair and event) and let the fields of the primary key (ItemPk) be insertable and updateable.

(I get the feeling that this will cause other problems, so some extra tweaking will be required.)

Upvotes: 1

Related Questions