Reputation: 11
I am using Google App Engine with JPA to implement a one-to-many bidirectional relationship. Everything works just fine when I debug and test my application on my machine at home, but after I deploy it to the App Engine persistence seems to break down.
This is the model I have (stripped down for simplicity):
User.java:
@Entity
class User implements Serializable
{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Key id;
@OneToMany(mappedBy = "owner",
cascade = CascadeType.ALL,
fetch = FetchType.EAGER)
private List<Book> books;
public getBooks() { return this.books; }
}
Book.java:
@Entity
class Book implements Serializable
{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Key id;
@ManyToOne(fetch = FetchType.LAZY)
private User owner;
private String name;
}
To create a new User
:
User user = new User()
// This is done just for testing. It works fine.
user.getBooks().add(new Book("TEST"))
EntityManager em = /* ... */
EntityTransaction transaction = em.getTransaction();
try
{
transaction.begin();
em.persist(user);
transaction.commit();
}
/* Exceptions handling. */
finally
{
if (transaction.isActive())
transaction.rollback();
em.close();
}
And to add a book:
User user = /* ... */
Book book = new Book("A new book");
user.getBooks().add(book);
EntityManager em = /* ... */
EntityTransaction transaction = em.getTransaction();
try
{
transaction.begin();
/* user.getBooks().add(book); - placing this here doesn't change anything */
em.merge(user);
transaction.commit();
}
/* Exceptions handling. */
finally
{
if (transaction.isActive())
transaction.rollback();
em.close();
}
What I saw, before I added the 'test' book which is created along with the User, is that creation of the first book entity works just fine, but whenever I create another one, the previous one is somehow removed from the Datastore and is replaced by the new one which I just created (I can tell because of the books' names). So I cannot create more than one book for the same user.
I tried to see if I somehow messed up persistence of the Book entity, and for that reason I added the 'TEST' book. The problem persists, only that now I have the first book ("TEST") and I keep replacing the second book on the list whenever I try to add a new one.
Again, this doesn't happen when I debug my application, only after I deploy.
I tried calling em.persist(book)
before the call to em.merge(user)
, but that caused an exception saying the book's owner was already set when it was persisted and cannot be changed. I tried setting the relationship myself (like in this thread), but that caused a failed transaction when adding a book.
I'm not sure if its relevant, but the type of the 'books' column I see is datastore_types.Key.from_path
, as in:
[datastore_types.Key.from_path(u'User', 9001L, u'Book', 1L, _app=u's~myapp'),
datastore_types.Key.from_path(u'User', 9001L, u'Book', 2001L, _app=u's~myapp')]
Any help would be appreciated, Thank you!
Upvotes: 1
Views: 616
Reputation: 17269
Can you try below:
User user = /* ... */
Book book = new Book("A new book");
book.setOwner(user);
EntityManager em = /* ... */
EntityTransaction transaction = em.getTransaction();
try{
transaction.begin();
em.persist(user);
transaction.commit();
}finally{
if (transaction.isActive())
transaction.rollback();
em.close();
}
Upvotes: 1