开发者

JPA2 Entities Caching

开发者 https://www.devze.com 2023-03-30 19:34 出处:网络
As it stands I am using a JSF request scoped bean to do all my CRUD operations. As I\'m sure you most likely know Tomcat doesn\'t provide container managed persistence so in my CRUD request bean I am

As it stands I am using a JSF request scoped bean to do all my CRUD operations. As I'm sure you most likely know Tomcat doesn't provide container managed persistence so in my CRUD request bean I am using EnityManagerFactory to get fold of enity manager. Now about the validity of my choice to use request scoped bean for this task, it's probably open for a discussion (again) but I've been trying to put it in the context of what I've read in the articles you gave me links to, specifically the first and second one. From what I gather EclipseLink uses Level 2 cache by default which stored cached entity. On ExlipseLink Examples - JPA Caching website it says that:

The shared cache exists for the duration of the persistence unit ( EntityManagerFactory, or server)

Now doesn't that make my cached entities live for a fraction of time during the call that is being made to the CRUD request bean because the moment the bean is destroyed and with it EntityManagerFactory then so is the cache. Also the last part of the above sentence "EntityManagerFactory, or server" gets me confused .. what precisely is meant by or server in this context and how does one control it. If I use the @Cache annotation and set appropriate amount of expire attribute, will that do the job and keep the e开发者_运维百科ntities stored on the servers L2 cache than, regardless of whether my EntityManagerFactory has been destroyed ?

I understand there is a lot of consideration to do and each application has specific requirements . From my point of view configuring L2 cache is probably the most desirable (if not only, on Tomcat) option to get things optimized. Quoting from your first link:

The advantages of L2 caching are:

  • avoids database access for already loaded entities
  • faster for reading frequently accessed unmodified entities

The disadvantages of L2 caching are:

  • memory consumption for large amount of objects
  • stale data for updated objects
  • concurrency for write (optimistic lock exception, or pessimistic lock)
  • bad scalability for frequent or concurrently updated entities

You should configure L2 caching for entities that are:

  • read often
  • modified infrequently
  • not critical if stale

Almost all of the above points apply to my app. At the heart of it, amongst other things, is constant and relentless reading of entities and displaying them on the website (the app will serve as a portal for listing properties). There's also a small shopping cart being build in the application but the products sold are not tangible items that come as stock but services. In this case stale entities are no problem and also, so I think, isn't concurrency as the products (here services) will never be written to. So the entities will be read often, and they will be modified infrequently (and those modified are not part of the cart anyway, an even those are modified rarely) and therefore not critical if stale. Finally the first two points seem to be exactly what I need, namely avoidance of database access to already loaded entities and fast reading of frequently accessed unmodified enteties. But there is one point in disadvantages which still concerns me a bit: memory consumption for large amount of objects. Isn't it similar to my original problem?

My current understanding is that there are two options, only one of which applies to my situation:

  1. To be able to delegate the job of longer term caching to the persistence layer than I need to have access to PersistenceContext and create a session scoped bean and set PersistenceContextType.EXTENDED. (this options doesn't apply to me, no access to PersistenceContext).

  2. Configure the L2 @Cache annotation on entities, or like in option 1 above create a session scoped bean that will handle long term caching. But aren't these just going back to my original problem?

I'd really like to hear you opinion and see what do you think could be a reasonable way to approach this, or perhaps how you have been approaching it in your previous projects. Oh, and one more thing, just to confirm.. when annotating an entity with @Cache all linked entities will be cached along so I don't have to annotate all of them?

Again all the comments and pointers much appreciated.


Thanks for you r answer .. when you say

"In Tomcat you would be best to have some static manager that holds onto the EntityManagerFactory for the duration of the server."

Does it mean I could for example declare and initialize static EntityManagerFactory field in an application scoped been to be later used by all the beans throughout the life of the application ?


EclipseLink uses a shared cache by default. This is shared for all EntityManagers accessed from an EntityManagerFactory. You do not need to do anything to enable caching.

In general, you do not want to be creating a new EntityManagerFactory per request, only a new EntityManager. Creating a new EntityManagerFactory is quite expensive, so not a good idea, even ignoring caching (it has its own connection pool, must initialize the meta-data, etc.).

In Tomcat you would be best to have some static manager that holds onto the EntityManagerFactory for the duration of the server. Either never close it, or close it when a Servlet is destroyed.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号