JPA & RequestFactory: Persistence of Foreign Keys

315 views
Skip to first unread message

Alexander Orlov

unread,
Jul 5, 2011, 12:59:48 PM7/5/11
to Google Web Toolkit
In my JPA Entity class I have:
@Entity
public class Booking {
@Id
@SequenceGenerator(name = "BOOKING", allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator =
"BOOKING")
private Integer id;

@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(nullable = false)
private User user;

// ...
}

In my GWT View I have:

MainRequestFactory.BookingRequest bookingRequest =
reqFactory.bookingRequest();
BookingProxy bookingProxy =
bookingRequest.create(BookingProxy.class);
UserProxy userProxy = bookingRequest.create(UserProxy.class);

userProxy.setId(12);

bookingProxy.setUser(userProxy);

Request<Void> persistRequest =
bookingRequest.persist().using(bookingProxy);
persistRequest.fire(new Receiver<Void>() {
@Override
public void onSuccess(Void response) {
GWT.log("persisted");
}
});

/////////////////////

Users and Bookings persistence without the User Constraint works fine.
But with the above code I want/have to assign the user with the ID
"12" to a newly created booking. But I cannot assign a new booking to
an already existing user ID 12. I get the following error:

[EL Warning]: 2011-07-05 18:48:45.464--UnitOfWork(267787945)--
Exception [EclipseLink-4002] (Eclipse Persistence Services -
2.3.0.v20110604-r9504):
org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.firebirdsql.jdbc.FBSQLException: GDS
Exception. 335544665. violation of PRIMARY or UNIQUE KEY constraint
"INTEG_388" on table "USERS2"

It's because an user with the ID "12" already exists and JPA wants to
create a new user with the same ID instead of just creating a new
booking with the user ID "12" as its foreign key.

How can I tell RequestFactory NOT to create a new user but instead
just to assign the user ID of an already existing user to a new
booking entry?

Jens

unread,
Jul 5, 2011, 2:33:24 PM7/5/11
to google-we...@googlegroups.com
I think its not a RequestFactory problem but more a JPA problem. For some reason EclipseLink things it has to insert the User object although it already exists and has an id. 

I recently had the same JPA issue (I am not using RequestFactory) and the problem was that the object EclipseLink wants to insert was a detached entity and thus not known to the current EntityManager. If you then call persist on the detached entity an INSERT will be done.

In your case I think you have to do something like: 

User attachedUser = entityManager.merge(booking.getUser());
booking.setUser(attachedUser); //maybe thats not needed.
entityManager.persist(booking).

That way you tell the EntityManager that the user already exists. 

A second way would be to fetch the already existing user: 

User attachedUser = entityManager.find(User.class, booking.getUser().getId());
booking.setUser(user); //maybe thats not needed
entityManager.persist(booking);

Hope that helps.

-- J.

Alexander Orlov

unread,
Jul 5, 2011, 7:29:00 PM7/5/11
to Google Web Toolkit
On Jul 5, 8:33 pm, Jens <jens.nehlme...@gmail.com> wrote:
> I think its not a RequestFactory problem but more a JPA problem. For some

I suppose so.

> reason EclipseLink things it has to insert the User object although it
> already exists and has an id.

Exactly.

> In your case I think you have to do something like:
>
> User attachedUser = entityManager.merge(booking.getUser());
> booking.setUser(attachedUser); //maybe thats not needed.
> entityManager.persist(booking).

I've added the following annotation: @OneToOne(fetch = FetchType.LAZY,
cascade = CascadeType.DETACH/MERGE) which reports the following error
now:
com.google.web.bindery.requestfactory.server.UnexpectedException: The
persisted entity with id 1 has a null version


>
> That way you tell the EntityManager that the user already exists.
>
> A second way would be to fetch the already existing user:
>
> User attachedUser = entityManager.find(User.class,
> booking.getUser().getId());
> booking.setUser(user); //maybe thats not needed
> entityManager.persist(booking);

Same as above.

-Alex

khiem nguyen

unread,
Jul 6, 2011, 5:43:12 AM7/6/11
to google-we...@googlegroups.com
i think the problem lies here:


 @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
   @JoinColumn(nullable = false)
   private User user;


cascadetype.all  means when u create new Booking, persist it will also persist the user, which leads to id-conflict

 



--
You received this message because you are subscribed to the Google Groups "Google Web Toolkit" group.
To post to this group, send email to google-we...@googlegroups.com.
To unsubscribe from this group, send email to google-web-tool...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/google-web-toolkit?hl=en.


Reply all
Reply to author
Forward
0 new messages