10 abr 2012

JPA setup: entities in JAR file

In this post, we'll see how to package our entities in a JAR file that will be used as a dependency for a WAR webapp file.

The setup is really simple, but a bit tricky too. The key is to place persistence.xml file in the META-INF folder of the JAR file, along with our entities. We should end up with the following directory tree:
my-core.jar:
META-INF/persistence.xml
bar/foo/MyEntity.class
//other core files

my-webapp.war:
WEB-INF/lib/my-core.jar
WEB-INF/web.xml
//other webapp files
That's it. We can now easily package our webapps as multi-module projects (eg Maven).

14 sept 2010

Howto: Hibernate second-level cache with Ehcache Part 2

In Part 1, we explained briefly what is Hibernate's second level cache and how it works.

Let's see how to configure our project. We'll asume a working Hibernate project using JPA annotations. The project will be built with Maven, using the standard folder layout for webapps (src, resources, webapp, etc).
  1. First, we must add Ehcache dependency to pom.xml:
    <dependency>
    <groupId>net.sf.ehcache</groupId>
    <artifactId>ehcache</artifactId>
    <version>2.0.1</version>
    <type>pom</type>
    </dependency>
  2. We have to configure Hibernate to use a second-level cache with Ehcache. We're using hibernate.properties file in this example:
    hibernate.cache.use_second_level_cache=true
    hibernate.cache.use_query_cache=true
    hibernate.cache.region.factory_class=net.sf.ehcache.hibernate.SingletonEhCacheRegionFactory
  3. For setup and development purposes, it's always a good idea to enable Hibernate cache specific logging. The logger is org.hibernate.cache
  4. Now, let's annotate our domain entity to be cacheable:
    @Entity
    @Table(name = "FooEntity")
    @org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
    public class FooEntity {
    ...
    // implementation for FooEntity
    ...
    @Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
    public Set getBars() { ... }
    }
    We use the Hibernate specific @Cache annotation to define a cacheable entity or collection. The usage attribute defines cache concurrency strategies that implies different isolation levels for cache read-write.
  5. Next, we have to configure Ehcache. This is done with a ehcache.xml file that must exist at the root of the classpath for our project (WEB-INF/classes probably). The location of this file can be cofigured with a Hibernate configuration property net.sf.ehcache.configurationResourceName = org/mycompany/ehcache.xml (this is a relative path to the project's classpath root). Take a look at Ehcache's web site for a full explanation of this configuration file:
    <?xml version="1.0" encoding="UTF-8" ?>
    <ehcache>
    <diskStore path="java.io.tmp" />

    <defaultCache
    maxElementsInMemory="10000"
    eternal="false"
    timeToIdleSeconds="120"
    timeToLiveSeconds="120"
    overflowToDisk="true" />

    <cache name="org.myconpany.model.FooEntity"
    maxElementsInMemory="50"
    eternal="false"
    timeToIdleSeconds="600"
    timeToLiveSeconds="600"
    overflowToDisk="false" />
    </ehcache>

    <cache name="org.myconpany.model.BarEntity"
    maxElementsInMemory="500"
    eternal="false"
    timeToIdleSeconds="600"
    timeToLiveSeconds="600"
    overflowToDisk="false" />
    </ehcache>
  6. We're done! With that, FooEntity instances loaded via Session's get() and load() methods will be stored in the second-level Ehcache.
References: