Sample-spring-hibernate » History » Revision 3
Revision 2 (Henning Blohm, 18.09.2012 10:10) → Revision 3/20 (Henning Blohm, 18.09.2012 10:30)
h1. A sample using Hibernate and Spring on Z2 This sample is very similar to [[Sample-hibernate-basic]] but differs in that we use the Spring framework throughout... * for assembly within the modules and to wire services between modules * for declarative transaction demarcation * for JPA entity manager injection This is another practical application of [[How to Spring]]. This sample is stored in "z2-samples.spring-hibernate":http://redmine.z2-environment.net/projects/z2-samples/repository/z2-samples-spring-hibernate. h2. Prerequisites You need the *z_tx_tests* database on a local MySQL database system. Start the MySQL client as the root user and run: <pre><code class="SQL"> create database z_tx_tests; grant all on z_tx_tests.* to tx@localhost identified by 'tx'; </code></pre> h2. Run it Like all samples, also this sample can be run as in [[How to run a sample]]. If you have the database, the fastest way to verify whether it runs is: <pre><code class="ruby"> mkdir install cd install git clone -b master http://git.z2-environment.net/z2-base.core git clone -b master http://git.z2-environment.net/z2-samples.spring-hibernate # on Linux / Mac OS: cd z2-base.core/run/bin ./gui.sh # on Windows: cd z2-base.core\run\bin gui.bat </code></pre> When running, go to http://localhost:8080/spring-hibernate. You should see this: !spring-hibernate.png! h2. Details Similar to [[Sample-hibernate-basic]], the assumption of this example is that of a re-use domain module *com.zfabrik.samples.spring-hibernate.domain* that implements a "Thingy Repository" and is used from a web application that is in another module *com.zfabrik.samples.spring-hibernate.web*. The domain module exposes the Thingy Repository as a Z2 component - from a Spring application context defined bean - that is imported into the application context of the Web application and injected into the controller filter by Spring. The controller uses declarative transaction demarcation. The domain module makes use of Hibernate's JPA implementation using Spring's entity manager injection and integrates with the transaction management provided by *com.zfabrik.jta*. h3. The domain module and its persistence context The domain module *com.zfabrik.samples.spring-hibernate.domain* defines a persistence unit "thingies" in "java/src.impl/META-INF/persistence.xml":http://redmine.z2-environment.net/projects/z2-samples/repository/z2-samples-spring-hibernate/revisions/master/entry/com.zfabrik.samples.spring-hibernate.domain/java/src.impl/META-INF/persistence.xml, i.e. in its implementation. That makes sense, as the XML file will be looked up with a class loader and we do not intent to retrieve from another module. Or, put differently, the persistence unit is not part of the module's API. In order to integrate with the built-in transaction management the <code>persistence.xml</code> declares the JTA data source <pre><code class="xml"> <jta-data-source>components:com.zfabrik.samples.hibernate-basic.domain/DB</jta-data-source> </code></pre> and the _Transaction Manager Lookup_ <pre><code class="xml"> <property name="hibernate.transaction.manager_lookup_class" value="com.zfabrik.hibernate.TransactionManagerLookup" /> </code></pre> The former points to the data source component "com.zfabrik.samples.spring-hibernate.domain/DB":http://redmine.z2-environment.net/projects/z2-samples/repository/z2-samples-hibernate-basic/revisions/master/entry/com.zfabrik.samples.hibernate-basic.domain/DB.properties, while the latter makes sure Hibernate can register with the transaction manager implementation. The persistence unit defines only one entity. The Thingy as in "Thingy.java":http://redmine.z2-environment.net/projects/z2-samples/repository/z2-samples-spring-hibernate/revisions/master/entry/com.zfabrik.samples.spring-hibernate.domain/java/src.api/com/zfabrik/samples/spring_hibernate/thingies/Thingy.java. That is an API-exposed type. We use the simplified pattern of exposing persistent objects in the API rather than using Data Transfer Objects (DTOs). The application context of the module is defined in "java/src.impl/META-INF/applicationContext.xml":http://redmine.z2-environment.net/projects/z2-samples/repository/z2-samples-spring-hibernate/revisions/master/entry/com.zfabrik.samples.spring-hibernate.domain/java/src.impl/META-INF/applicationContext.xml and looks like this: <pre><code class="xml"> <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> <!-- annotation based config --> <context:component-scan base-package="com.zfabrik.samples.spring_hibernate" /> <context:annotation-config /> <!-- EntityManager injection --> <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" /> <!-- The actual EMF we use --> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="persistenceUnitName" value="thingies" /> </bean> </beans> </code></pre> In short: * We make sure we can use annotations * We enable entity manager injection * We initialize the entity manager factory from Spring In the implementation class "ThingyRepositoryImpl":http://redmine.z2-environment.net/projects/z2-samples/repository/z2-samples-spring-hibernaterevisions/master/entry/com.zfabrik.samples.spring-hibernate.domain/java/src.impl/com/zfabrik/samples/spring_hibernate/impl/thingies/ThingyRepositoryImpl.java we make use of these capabilities and declare a Spring bean "thingyRepository": <pre><code class="java"> @Repository("thingiesRepository") public class ThingyRepositoryImpl implements ThingyRepository { @PersistenceContext private EntityManager em; @Override public void store(Thingy thingy) { this.em.persist(thingy); } @SuppressWarnings("unchecked") @Override public Collection<Thingy> findAll() { return this.em.createQuery("select t from Thingy t").getResultList(); } @Override public void delete(int id) { Thingy t = this.em.find(Thingy.class, id); if (t != null) { this.em.remove(t); } } } </code></pre> In order to expose that bean as a Z2 component for re-use from other modules, we declare a component "com.zfabrik.samples.spring-hibernate/repository":http://redmine.z2-environment.net/projects/z2-samples/repository/z2-samples-spring-hibernate/revisions/master/entry/com.zfabrik.samples.spring-hibernate.domain/repository.properties: <pre><code class="ruby"> com.zfabrik.component.type=org.springframework.bean # # Expose Spring defined data source # # # the context that defines the bean (more than one # bean can be exposed like this) # bean.context=com.zfabrik.samples.spring-hibernate.domain/applicationContext # # the bean name # bean.name=thingiesRepository </code></pre> that is based on the application context component "com.zfabrik.samples.spring-hibernate/applicationContext":http://redmine.z2-environment.net/projects/z2-samples/repository/z2-samples-spring-hibernate/revisions/master/entry/com.zfabrik.samples.spring-hibernate.domain/applicationContext.properties: <pre><code class="ruby"> com.zfabrik.component.type=org.springframework.context # # context config location is where the context is # actually defined. # context.contextConfigLocation=classpath:META-INF/applicationContext.xml </code></pre> See also [[How to Spring]] for more details on these component types.