user1928773
user1928773

Reputation: 11

GAE/J OneToMany JPA Persistence Failure When Deployed

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

Answers (1)

JR Galia
JR Galia

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

Related Questions