19

I add entity to my database and it works fine. But when i retrieve the List, i get the old entity, the new entities i add are not shown until i undeploy the application and redeploy it again. This means are my entities cached by default? But, I haven't made any settings for caching entities in my persistence.xml or any such file.

I have even tried calling flush(), refresh() and merge(). But still it shows the old entities only. Am i missing something? Please help me.

Pascal Thivent
  • 535,937
  • 127
  • 1,027
  • 1,106
TCM
  • 16,242
  • 43
  • 150
  • 245

5 Answers5

21

Welcome to JPA. If you use it, it means you will have huge problems if you update the database outside of JPA unless you know what you're doing and are very careful. This means you have to figure out how to flush any cached entities so they can be reloaded.

Basically, don't update entities outside JPA if you can at all help it and if you do you will probably have to get into the workings of the caching model used by your particular JPA provider. If you need to update outside JPA a lot then JPA probably isn't the right choice for you.

cletus
  • 578,732
  • 155
  • 890
  • 933
  • 1
    But i am not updating database outside of JPA. I used persist method of jpa and record is seen in database. But when i retrieve list, i don't see the newly added entity. Please help me. – TCM Apr 25 '10 at 10:53
  • Also, even more weird is the fact that if i change the provider from TopLink to EclipseLink, everything works fine! With TopLink only this problem is coming. I am using Netbeans 6.8 and Glassfish v3. – TCM Apr 25 '10 at 10:59
  • @Nitesh are you using transactions? If so are you committing them? – cletus Apr 25 '10 at 11:43
  • 2
    I am not using any transaction using entitymanager.getTransaaction or any container managed transaction. I could see the record in database but not in the list i retrieve. Basically, what happens is say there are employee and department tables. Department table has employee collection. So if i persist employee record, then it is seen in database but not in collection of employees in department until i explicitly add it to the collection of employees. Is this necessary step? if i have 10 tables relating to one entity. Do i have to add it to collection of all 10 tables? That's too tedious? – TCM Apr 26 '10 at 02:47
  • 1
    @Nitesh oh different problem. Yes you absolutely must manage the Java objects by putting it into that collection. – cletus Apr 26 '10 at 02:50
  • So, if i have 10 tables, i must remember all the table names and add it to those collections? I thought, ORM is super smart to detect the links and modify it accordingly. – TCM Apr 26 '10 at 03:05
  • 2
    @Nitesh it's the other way: you update the objects and the database is updated to reflect that. You have to consider if you want your one-to-many relationships to be unidirectional or bidirectional too. Just because you can have a collection of entities on the one side doesn't mean you should. – cletus Apr 26 '10 at 03:16
  • Everything you do over 3rd-party programs e.g. Adminer, is not noticed by the JPA's entity manager. Do not attempt to tell it by a "flush all and refetch" button. That is an over-kill of your web application. Instead write for whatever you do over the 3rd-party app a seperate JSF view. – Roland Feb 05 '20 at 00:41
13

This means are my entities cached by default?

JPA 1.0 does not define a L2 cache ("shared cache"), JPA 1.0 only defines an L1 cache ("transactional cache") but JPA providers can support a shared object cache, and most do. This is the case of TopLink Essentials which supports L1 and L2 cache through JPA Extensions for Caching (per JVM).

Now, as explained in the great article Understanding the cache of TopLink Essentials(GlassFish JPA):

  • All EntityManagers from same persistence unit shares the session cache (that's how TopLink calls the 2nd-level cache).
  • Session cache is turned on by default.
  • If there is modifications/deletions of entities in the persistence context they are synchronized to session cache after a transaction committed, so the state of session cache is updated (or such a cache wouldn't be usable at all).

So there must be something else wrong with your setup. You can try do disable the shared session cache for testing purpose (and only for testing purpose) by adding the following property:

<property name="toplink.cache.shared.default" value="false"/>

But I would be surprised if this changes anything. As I said, I think there is another problem somewhere.

PS: This doesn't answer the question but, if you are using GlassFish v3, why don't you use EclipseLink?

Update: answering a comment of the OP

So if i persist employee record, then it is seen in database but not in collection of employees in department until i explicitly add it to the collection of employees. Is this necessary step?

Well, if you don't create the link between entities at the Java level, JPA won't be able to create it at the database (JPA only does what you tell him to do). So, yes, you need to create the link and, in case of a bidirectional association, you even need to set both sides of the link (for example add the employee to the collection of employees on the Department and set the department of an Employee).

Pascal Thivent
  • 535,937
  • 127
  • 1,027
  • 1,106
  • 3
    Hi Pascal Thivent, i provider to EclipseLink in my persistence.xml and everything worked fine. But still i have another doubt, that i asked to cletus also :- Basically, what happens is say there are employee and department tables. Department table has employee collection. So if i persist employee record, then it is seen in database but not in collection of employees in department until i explicitly add it to the collection of employees. Is this necessary step? if i have 10 tables relating to one entity. Do i have to add it to collection of all 10 tables? That's too tedious? – TCM Apr 26 '10 at 02:50
1

JPA 2.0 defines a shared (L2) cache, but does not specify the default. EclipseLink enables caching by default, other providers do not.

An EntityManager will always have a persistence context (L1) cache until you call clear() or create a new one.

You can disable the shared cache,

See, http://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Basic_JPA_Development/Caching

But your problem is that you are not maintain both sides of your relationship. When you set the 1-1 you need to add to the 1-m, otherwise your objects are invalid.

For more information on caching see,

http://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Basic_JPA_Development/Caching

James
  • 19,367
  • 9
  • 72
  • 129
0

Are you using the EntityManager? if not give it a try http://docs.oracle.com/javaee/5/api/javax/persistence/EntityManager.html

Are you using a DataSource to manage connections to your database? you should try it also. Is an xml that is configured in your server. Give more information about your architecture so we can help you.

memozac
  • 83
  • 2
  • 7
0

I am using the context of eclipselink and ejb,i found that when I query entities,it will auto be cached,but I also run a function to change record in database,so I may get old data in the cache,so I disable cache by adding the following to the file persistence.xml:

<shared-cache-mode>NONE</shared-cache-mode>

it do works!

Sanchit Patiyal
  • 4,716
  • 1
  • 12
  • 31
godtree
  • 1
  • 3