Monday, February 6, 2012

Persistence - Project 2

First, the persistence environment:
     Database: MySQL 14.14 distribution 5.5.17 for Win 32 (x86).
     JPA provider: Hibernate 3.6.7 - Note: there was a bug with the earlier version, and we had to upgrade. (The previous version's getCriteriaBuilder() would not return a valid criteriabuilder.)
     JTA and JNDI provider: See Container Configurations
     Database Administrator: MySQL Workbench  5.2CE

In this environment, we will not use a hibernate.cfg.xml.  We will start with the persistence.xml:
JSFDemoSpring.war/WEB-INF/classes/META-INF/persistence.xml

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
    <persistence-unit name="JSFDemoPU" transaction-type="JTA">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <jta-data-source>JSFDemoJNDI</jta-data-source>
        <exclude-unlisted-classes>false</exclude-unlisted-classes>
        <properties>
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
            <property name="hibernate.hbm2ddl.auto" value="update"/>
            <property name="hibernate.show_sql" value="true"/>
            <property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.SunONETransactionManagerLookup"/>
            <property name="hibernate.archive.autodetection" value="class"/>
        </properties>
    </persistence-unit>

    <persistence-unit name="localTestingPU" transaction-type="RESOURCE_LOCAL">
       <provider>org.hibernate.ejb.HibernatePersistence</provider>
       <class>com.sample.entities.PartEntity</class>
       <class>com.sample.entities.OrderPartsEntity</class>
       <class>com.sample.entities.OrderEntity</class>
       <properties>
         <property name="hibernate.hbm2ddl.auto" value="update"/>
         <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
         <property name="hibernate.archive.autodetection" value="class"/>
         <property name="hibernate.show_sql" value="true"/>
         <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
         <property name="hibernate.connection.password" value="ItWorks!"/>
         <property name="hibernate.connection.url" value="jdbc:mysql://localhost/jsfdemodb"/>
         <property name="hibernate.connection.username" value="JSFDemoUser"/>
         <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
       </properties>
     </persistence-unit>

</persistence>

We give our persistence unit a name and designate that we will be using container managed transactions:  <persistence-unit name="JSFDemoPU" transaction-type="JTA">
We then tell our persistence unit that Hibernate will be the provider, and it will be talking to MySQL.
The next two lines are just for convenience.  hibernate.hbm2ddl.auto value="update" simply says hibernate will evaluate the database upon startup, if there have been any changes, update the database to match the entities. Note: this would probably be very bad in a production environment, but is great for development.  And hibernate.show_sql allows us to log all the sql statements so we can see what our application is doing.
The next property will change depending on the container we are running in.  But, it tells hibernate how to find a transaction to use since the transactions are managed by the container.  <property name = "hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.SunONETransactionManagerLookup"/>

The last line tells hibernate to scan the code for entity annotations and register classes based on those annotations. <property name="hibernate.archive.autodetection" value="class"/>


The next persistence unit sets up a local persistence unit for testing.  This does not reference the container so it has a transaction type of RESOURCE_LOCAL.  It then defines what classes are to be included and give the Hibernate specific properties for making a local connection.

All in all, a simple, clear and concise persistence.xml.  Note: although we have hibernate specifics here, this is the only place we need to reference Hibernate.  Of course, we had to include the hibernate libraries.  Since I upgraded the version, I did not include any "optional" jars:
antlr-2.7.6.jar
cglib-2.2.jar
commons-collections-3.1.jar
dom4j-1.6.1.jar
hibernate-jpa-2.0-api-1.0.1.Final.jar
hibernate3.jar
javassist-3.12.0.GA.jar
jta-1.1.jar
slf4j-api-1.6.1.jar

Now that we have a persistence unit, we need to configure it in our web.xml.  Just add the lines:
    <persistence-unit-ref>
        <persistence-unit-ref-name>JSFDemoJNDI</persistence-unit-ref-name>
        <persistence-unit-name>JSFDemoPU</persistence-unit-name>
    </persistence-unit-ref>
This allows us to reference the JSFDemoPU.

Next we need to configure the JNDI in the JEE container, but for that will depend on our container, see the Container Configurations page.

And finally we need to reference it in Spring:
JSFDemoSpring.war/WEB-INF/applicationContext.xml

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
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/jee
http://www.springframework.org/schema/jee/spring-jee.xsd
">  
    <context:annotation-config/>
    <context:component-scan base-package="com.sample"/>
    <tx:annotation-driven/>
    <jee:jndi-lookup id="JSFDemoJNDI" jndi-name="JSFDemoJNDI"/>
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="persistenceUnitName" value="JSFDemoPU"/>
    </bean>
    <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager" />
    <bean id="persistenceAnnotation" class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
    <import resource="/spring/ServiceAndDaoBeans.xml"/>
</beans>

We start by telling Spring to be able to be configured by annotations.  Then we tell Spring what files (packages) to scan for those annotations.  Next we include transactions to be interpreted (declarative transactions).  We define what JNDI to look up.  We then define the EntityManagerFactory.  Note:  this defines the EntityManagerFactory to be JPA specific, not Hibernate.  Also, this entity manager factory is from the JSFDemoPU as defined in the web.xml.  The transaction manager is going to be Springs JTA transaction manager.  This will allow us to inject container transactions via Spring into our service layer.  And finally, we define what class Spring will use to process the persistence annotations which will be the JPA processor.

The last line imports an xml file to define our beans, but the rest of this file is defining our persistence / transaction layer. 

No comments:

Post a Comment