Spring Hibernate Tutorial
Spring Hibernate Tutorial
6. Run the unit test and verify CRUD with DAO.
9. Create an action and model (DynaActionForm) for the web layer.
10. Run the unit test and verify CRUD with action.
11. Create JavaServer Pages (JSPs) to allow CRUD through a web browser.
� Tomcat 5.0+
� Ant 1.6.1+
� JAVA_HOME
� ANT_HOME
� CATALINA_HOME
� JAVA_HOME/bin
� ANT_HOME/bin
� CATALINA_HOME/bin
The approach
To develop a Java-based web application, developers usually download JARs, create a directory
structure, and create an Ant build file. For a Struts-only application, this can be simplified
by using the struts-blank.war, which is part of the standard Struts distribution. For a web app
using Spring’s MVC framework, you can use the webapp-minimal application that ships with
Spring. Both of these are nice starting points, but neither simplifies the Struts-Spring integration
nor takes into account unit testing. Therefore, I created Equinox, both for this book and
Equinox is a bare-bones starter application for creating a Spring-based web application. It has
a pre-defined directory structure, an Ant build file (for compiling, deploying and testing), and
all the JARs you will need for a Struts, Spring and Hibernate-based web app. Much of the
directory structure and build file in Equinox is taken from my open source AppFuse application.
Therefore, Equinox is really just an “AppFuse Light” that allows rapid web app development
with minimal setup. Because it is derived from AppFuse, you will see many references to
it in package names, database names and other areas. This is done purposefully so you can
In order to start MyUsers, download Equinox 1.0 from sourcebeat.com/downloads and
Create project directories and an Ant
build file
• To set up your initial directory structure and Ant build file, extract the
Equinox downloadonto your hard drive. I recommend putting
projects in C:\Source on Windows and ~/devon Unix or Linux.
For Windows users, now is a good time set your HOME
environment variable to C:\Source. The easiest way to get
started with Equinox is to extract it to your preferred source
location, cd into the equinox directory and run ant new
-Dapp.name=myusers from the command line.
• Warning: You must have the CATALINA_HOME environment
variable set, or building MyUsers will not work. This is because
its build.xml depends on a catalina-ant.jar file for running
Tomcat’s Ant tasks (covered shortly). As an alternative, you can
specify a Tomcat.home property in build.properties that points to
your Tomcat installation.
•
Directory structure
Type ant in the MyUsers directory
to see options
[echo] Available targets are:
[echo] compile --> Compile all Java files
<pathelement
path="${tomcat.home}/server/lib/catalina-ant.jar"/>
</classpath>
</taskdef>
depends="war">
<deploy url="${tomcat.manager.url}"
username="${tomcat.manager.username}"
password="${tomcat.manager.password}"
path="/${webapp.name}"
war="file:${dist.dir}/${webapp.name}.war"/>
</target>
<undeploy url="${tomcat.manager.url}"
username="${tomcat.manager.username}"
password="${tomcat.manager.password}"
path="/${webapp.name}"/>
</target>
path="/${webapp.name}"/>
</target>
<start url="${tomcat.manager.url}"
username="${tomcat.manager.username}"
password="${tomcat.manager.password}"
path="/${webapp.name}"/>
</target>
<stop url="${tomcat.manager.url}"
username="${tomcat.manager.username}"
password="${tomcat.manager.password}"
path="/${webapp.name}"/>
</target>
<list url="${tomcat.manager.url}"
username="${tomcat.manager.username}"
password="${tomcat.manager.password}"/>
</target>
Build.properties
# Properties for Tomcat Server
tomcat.manager.url=http://localhost:8080/ma
nager
tomcat.manager.username=admin
tomcat.manager.password=admin
• Edit $CATALINA_HOME/conf/tomcat-
users.xml to make sure this line is there.
<user username="admin"
password="admin" roles="manager"/>
Blackscreen test…type ant list
C:\equinox-1.0\myusers>ant list
Buildfile: build.xml
list:
[list] OK - Listed applications for virtual host localhost
[list] /:running:0:ROOT
[list] /manager:running:0:manager
[list] /StatefulCounterEJB:running:0:StatefulCounterEJB
[list] /myusers:running:0:myusers
[list] /ejb-examples-1.1:running:0:ejb-examples-1.1
[list] /blazeds:running:0:blazeds
[list] /HelloBean:running:0:HelloBean
[list] /jndiservlet:running:0:jndiservlet
[list] /docs:running:0:docs
[list] /openejb:running:0:openejb
[list] /LookupServlet:running:0:LookupServlet
[list] /ejb-examples:running:0:ejb-examples
[list] /myexamples:running:0:myexamples
[list] /hello-openejb:running:0:hello-openejb
[list] /HibernateWithMySQL:running:0:HibernateWithMySQL
[list] /examples:running:0:examples
[list] /host-manager:running:0:host-manager
[list] /HelloEjbService:running:0:
[list] /HibernateApp3:running:0:HibernateApp3
[list] /CurrentQuoteEJB:running:0:CurrentQuoteEJB
[list] /FtoCEJB:running:0:FtoCEJB
BUILD SUCCESSFUL
Total time: 1 second
C:\equinox-1.0\myusers>
installation
• Running ant deploy will deploy myusers.
•
Test by going to 8080/myusers
Running the HSQLDB
• Warning: In order for the in-memory
HSQLDB to work correctly with
MyUsers, start Tomcat from the same
directory from which you run Ant. Type
$CATALINA_HOME/bin/startup.sh on
Unix/Linux and %CATALINA_HOME
%\bin\startup.bat on Windows. You can
also change the database settings to
use an absolute path.
Create a UserDAOTest.java
1. Create a UserDAOTest.java class in the test/org/appfuse/dao directory. This class should
extend BaseDAOTestCase, which already exists in this package. This parent class
initializes Spring’s ApplicationContext from the web/WEB-INF/applicationContext.xml file.
Listing 2.6 is the code you will need to begin writing your UserDAOTest.java:
Listing 2.6
Note: Automatically importing necessary classes is a nice feature of modern IDEs like
Eclipse and IDEA. Equinox contains the project necessary for both of these IDEs.
This class won’t compile yet because you haven’t created your UserDAO interface. Before you
do that, write a couple of tests to verify CRUD works on the User object.
2. Add the testSave and testAddAndRemove methods to the UserDAOTest class, as
Listing 2.7
package org.appfuse.dao;
super.setUp();
}
super.tearDown();
dao = null;
}
}
You’ll need to use netbeans or eclipse add imports
(or search for them yourself)
• Add the testSave and testAddAndRemove methods to the UserDAOTest class, as
• shown
package org.appfuse.dao;
super.setUp();
}
super.tearDown();
dao = null;}}
user.setFirstName("Rod");
user.setLastName("Johnson");dao.saveUser(user);
log.info(user);
assertNotNull(user.getFirstName());
}
user.setFirstName("Bill");
user.setLastName("Joy");
dao.saveUser(user);
assertNotNull(user.getId());
assertEquals(user.getFirstName(), "Bill");
if (log.isDebugEnabled()) {
log.debug("removing user...");
}
dao.removeUser(user.getId());
assertNull(dao.getUser(user.getId()));
}
UserDAO
• From these test methods, you can see that you need to
create a UserDAO with the following
• methods:
• saveUser(User)
• removeUser(Long)
• getUser(Long)
• getUsers() (to return all the users in the database)
• 3. Create a UserDAO.java file in the src/org/appfuse/dao
directory and populate it with the
• code in Listing 2.8:
Create a UserDAO.java file in the
src/org/appfuse/dao directory
• package org.appfuse.dao;
• // use your IDE to handle imports
• public interface UserDAO extends DAO {
• public List getUsers();
• public User getUser(Long userId);
• public void saveUser(User user);
• public void removeUser(Long userId);
• }
• Finally, in order for the UserDAOTest and
UserDAO to compile, create a User
object to persist.
• Create a User.java class in the
src/org/appfuse/model directory and add
id, firstName
• and lastName as member variables, as
shown
class User
• package org.appfuse.model;
• public class User extends BaseObject {
• private Long id;
• private String firstName;
• private String lastName;
• /*
• Generate your getters and setters using your favorite
IDE:
• In Eclipse:
• Right-click -> Source -> Generate Getters and Setters
• */
• }
• Notice that you’re extending a
BaseObject class which is already
defined. It has methods: toString(),
equals() and hashCode(). The latter
two are required by Hibernate.
create a file named User.hbm.xml
• In the src/org/appfuse/model directory, create a file named User.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
</id>
not-null="true"/>
</class>
</hibernate-mapping>
Edit applicationContext.xml
• Add this mapping to Spring’s applicationContext.xml file in the
web/WEB-INF directory. Open this file and look for <property
name="mappingResources"> and change it to :
<property name="mappingResources">
<list>
<value>org/appfuse/model/User.hbm.xml</value>
</list>
</property>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/sampleContext.xml</param-value>
</context-param>
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName">
<value>org.hsqldb.jdbcDriver</value>
</property>
<property name="url">
<value>jdbc:hsqldb:db/appfuse</value>
</property>
<property name="username"><value>sa</value></property>
<!-- Make sure <value> tags are on same line - if they're not,
<property name="password"><value></value></property>
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate.LocalSessionFactoryBean">
<property name="dataSource">
<ref local="dataSource"/>
</property>
<property name="mappingResources">
<list>
<value>org/appfuse/model/User.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
continued
<prop key="hibernate.dialect">
net.sf.hibernate.dialect.HSQLDialect
</prop>
<prop key="hibernate.hbm2ddl.auto">create</prop>
</props>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate.HibernateTransactionManager">
<property name="sessionFactory">
<ref local="sessionFactory"/>
</property>
</bean>
</beans>
• The first bean (dataSource) represents an HSQL database, and the
second bean (session-Factory) has a dependency on that bean.
Spring just calls setDataSource (DataSource) on the
LocalSessionFactoryBean to make this work. If you wanted to
use a Java Naming and Directory Interface (JNDI) DataSource
instead, you could easily change this bean’s definition to
something similar to
• <bean id="dataSource"
• class="org.springframework.jndi.JndiObjectFactoryBean">
• <property name="jndiName">
• <value>java:comp/env/jdbc/appfuse</value>
• </property>
• </bean>
• Also note the hibernate.hbm2ddl.auto property in the
sessionFactory definition. This property creates the
database tables automatically when the application
starts. Other possible values are update and create-
drop.The last bean configured is the
transactionManager (and nothing is stopping you
from using a Java Transaction API — JTA —
transaction manager), which is necessary to perform
distributed transactions across two databases. If you
want to use a JTA transaction manager, simply
change this bean’s class attribute to
org.springframework.transaction.jta.Jta-
TransactionManager. Now you can implement the
UserDAO with Hibernate.
The UserDAOHibernate.java class in
src/org/appfuse/dao/hibernate (create dir
first)
package org.appfuse.dao.hibernate;
// organize imports using your IDE
public class UserDAOHibernate extends HibernateDaoSupport implements
UserDAO {
}
}
getHibernateTemplate().saveOrUpdate(user);
if (log.isDebugEnabled()) {
}
}
getHibernateTemplate().delete(user);
}
}
• Spring’s HibernateDaoSupport class is a
convenient super class for Hibernate DAOs. It
has
• handy methods you can call to get a Hibernate
Session, or a SessionFactory. The most
convenient
• method is getHibernateTemplate(), which
returns a HibernateTemplate. This
• template wraps Hibernate checked exceptions
with runtime exceptions, allowing your DAO
• interfaces to be Hibernate exception-free.
• Nothing is in your application to bind UserDAO to
UserDAOHibernate, so you must create
• that relationship.
• 2. For Spring to recognize the relationship, add the lines
in Listing 2.18 to the web/WEBINF/
• applicationContext.xml file.
<bean id="userDAO"
class="org.appfuse.dao.hibernate.UserDAOHibernate">
<property name="sessionFactory">
<ref local="sessionFactory"/>
</property>
</bean>
Note url…edit/add user
Added users…