Bad cache!( warp-persist, JPA-hibernate)

88 views
Skip to first unread message

Bevis.Zhao

unread,
Sep 5, 2010, 11:24:29 PM9/5/10
to warp-core, dha...@gmail.com
Dear Dhanji :

It's a very difficult JPA problem to me. When i update an
entity with EntityManager.merge(T), it update database success. but
when get it with em.find(), I got an random cache data. for example :

User.name = "Dhanji"
update to "Bevis"
update to "Warp"
update to "Guice"

In this process. I refresh page to view User. It show me
random name in ["Dhanji", "Bevis", "Warp", "Guice"]. (Not a page cache
i checked)
*What a bad JPA cache!*

Does anybody know what's wrong with that? It made me insane!
WOW...

Bevis.Zhao

unread,
Sep 5, 2010, 11:24:36 PM9/5/10
to warp-core, dha...@gmail.com

Dhanji R. Prasanna

unread,
Sep 6, 2010, 5:26:30 AM9/6/10
to Bevis.Zhao, warp-core
Hmm. Im not sure--can you tell us more about the setup? JPA provider, and your warp-persist config?

Sounds like it could be that you are not flushing after merge. Btw, merge will copy the given objects data into the EM but not "reattach" the object. So you have to keep merging if you change the object. This behaves differently to Hibernate. I think you should investigate the JPA side a little bit. It's probably there.

Dhanji.

Bevis Zhao

unread,
Sep 6, 2010, 6:07:50 AM9/6/10
to Dhanji R. Prasanna, warp-core
Thanks for your answer, under this scenario I described in detail :
  • I did flush after merge. 
  • I query the data by find or QL like "select u from User where id = :id", they execute and send SQL both. But the result is not sync data like what i say in last mail.
  • I watch the data in Eclipse by breakpoint. I saw the entity and every fields have IDs, they are not db column, same to cache identity, created by JPA.
  • My environment : Hibernate-JPA-2.0, Warp-persist 2.0 (Guice 2.0), Struts 2
JPA persistence.xml file is in the attachment files.

Warp-persist config is very simple: 

public void configure() {
bindConstant().annotatedWith(JpaUnit.class).to("defaults");
install(PersistenceService.usingJpa().across(UnitOfWork.REQUEST)
.forAll(Matchers.any(), Matchers.annotatedWith(Transactional.class))
.buildModule());

bind(Initializer.class).asEagerSingleton();

                // others
install(new ComponentInjectionModule());
install(new SettingsModule());

}

       @Singleton
public static class Initializer {
private final Logger logger = Logger.getLogger(getClass());
@Inject
Initializer(PersistenceService service) {
service.start();
logger.info("warp-persist initialized success.");
}
}

Need more setup information ?
This problem has troubled me for two weeks, really hope to fix it as soon as possible.

PS: I write letter need help of translator tools. excuse my bad writing ability.


Best regards 
--
Bevis
persistence.xml

Bevis Zhao

unread,
Sep 7, 2010, 10:17:57 AM9/7/10
to Dhanji R. Prasanna, warp-core
My friend let me know, i did not set my DAO class as Singleton.
I back to watch my code, yes he is right, but i remember i didn't setup that cause it throw an exception that "No transaction in process" when i run an update operation.
I think this is most important point. It take my god you an inspiration?

Bevis.Zhao
Tel : 13426000026

Dhanji R. Prasanna

unread,
Sep 8, 2010, 1:25:26 AM9/8/10
to Bevis Zhao, warp-core
On Tue, Sep 7, 2010 at 7:17 AM, Bevis Zhao <avenge...@gmail.com> wrote:
My friend let me know, i did not set my DAO class as Singleton.
I back to watch my code, yes he is right, but i remember i didn't setup that cause it throw an exception that "No transaction in process" when i run an update operation.
I think this is most important point. It take my god you an inspiration?


OK so your problem is fixed? 

Sometimes, if autocommit is enabled, "No transaction in progress" is not thrown.

If you have a Singleton Dao, you should be injecting Provider<> of the entity manager. That way a new one is created for each request or transaction.

Dhanji.


Bevis Zhao

unread,
Sep 8, 2010, 2:25:58 AM9/8/10
to Dhanji R. Prasanna, warp-core
emmmmm... no.

Now I setup all dao as Singleton, And Inject entity manager with provider. now in different request, I got difference em, but the problem still be there. I think because their cache not same. I merge data in em1, and view in em2. so the data jump to and fro.

but if i direct inject em, whatever "hibernate.connection.autocommit" is enable, it always throw "no transaction in process". I write some code to begin transaction before merge() and flush(), the bug looks like be fixed. But i know this is not a right way.  Could you give me a better (with Provider)? 


Bevis.Zhao 

Bevis Zhao

unread,
Sep 8, 2010, 4:25:23 AM9/8/10
to Dhanji R. Prasanna, warp-core
I got an another bad solution - modify method get(PK) of my base dao implement : 
old codes :
 return em.get().find(entityClass, id);
new : 
entity = em.find(entityClass, id); 
em.refresh(entity);
return entity;
It works!

but, that still not kill the source of the bug. i am confused.

Bevis.Zhao
Tel : 13426000026

Dhanji R. Prasanna

unread,
Sep 8, 2010, 9:27:04 AM9/8/10
to Bevis Zhao, warp-core
On Wed, Sep 8, 2010 at 1:25 AM, Bevis Zhao <avenge...@gmail.com> wrote:
I got an another bad solution - modify method get(PK) of my base dao implement : 
old codes :
 return em.get().find(entityClass, id);
new : 
entity = em.find(entityClass, id); 
em.refresh(entity);

I was just going to suggest this, actually. The problem is with the use of merge(). There appears to be cache staleness even though you have made an update to that entity in another thread and it is persisted to the db. This is really a problem with your JPA provider (is it Hibernate? OpenJPA?) and best solved on their forums--it could be a bug in their implementation.

Dhanji.

Reply all
Reply to author
Forward
0 new messages