3

When a Book object is persisted, a trigger on Insert runs to create a transaction record (in a separate table).

When I create an instance of Book and save it, I'd expect to see this record in the transactions() array, but it's continually empty.

Book book = new Book("Moby Dick", "Melville", "hardcover");
book = bookRepository.saveAndFlush(book);
if( book != null)
    assertTrue("There is no transaction history", book.transactions().size() > 0 );

This always fails. So does this (my gyrations to try to get the data reloaded):

public int addBook()
{
    int bookID;
    Book book = new Book("Moby Dick", "Melville", "hardcover");
    book = bookRepository.saveAndFlush(book);
    if( book != null)
        bookID = book.getID();
    return bookID;
}

@Test
public void testNewBookTrans()
{
    int aBook = addBook();
    bookRepository.findAll();
    transactionRepository.findAll();
    Book book = bookRepository.findOne(bookID);
    if( book != null )
        assertTrue("Still no transactions", book.getTransactions().size() > 0);
}

Yet, if I let this test fail, restart JUnit and then query the same book, it has the transaction that the trigger added.

So, there must be some way to invalidate or reload the db cache but I'm not seeing it.

user1944491
  • 559
  • 1
  • 8
  • 24

1 Answers1

3

Thats the normal behavior cause the new entity instance is cached. You must refresh it.

See this answer

Edit: In response to your comment.

About the cache scope, depends on how do you manipulate it in your app and platform used. In a common container managed transaction and persistence context case, the "*1st level" cache scope is attacth to the persistence context which lifecycle depends on the underlying tranaction. It is created when the transactional scope begins and disposed when the it ends.

I suppose that the mentioned solutions are not viable for you because you not want to care about refershing the instance and its collection in every place you already find for. So if the scope of persistence context is the mentioned you could just do the trick to refersh the instance after save it and call method flush.

I mean, you can just do the edit the code to refersh after save instance and flush (you must flush to the database)

Book book = new Book("Moby Dick", "Melville", "hardcover");
book = bookRepository.saveAndFlush(book);
book = bookRepository.refresh(book);
if( book != null)

After refresh method (you probably must to implement the custom method), you will have the book and its collection fresh.

If you want to refresh the associated transaction enities (they are entities?) yoo can add CascadeType.REFRESH to Book.transactions collection too.

Community
  • 1
  • 1
Guillermo
  • 1,523
  • 9
  • 19
  • Actually, I saw that immediately after I posted, but neither of the options in that answer are really viable for me, so I left my question intact. I'm hoping there is another way. What is the scope of the caching? Can I create the conditions under which it'll check the db again? – user1944491 Aug 13 '15 at 12:44
  • 2
    I appreciate your trying to help, but there is no `refresh()` method (as noted in your comment above). The _body_ of the mythical refresh method is what the question is asking about (how do you refresh??), so this doesn't get me any further along. – user1944491 Aug 14 '15 at 19:21
  • Ah je, how did you define the `BookRepository`? Just as inteface (for add query methods)? In other case post it. – Guillermo Aug 14 '15 at 20:33
  • I was going to edit the post, but before let's be sure: refersh is some custom command or just another way of refreshing? :-D @Guillermo – funder7 Jun 24 '20 at 21:36