chapter 13. hibernate with...
TRANSCRIPT
1 / 24Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University
Database Programming
Chapter 13. Hibernate with Spring
What Is Spring?
Writing a Data Access Object (DAO)
Creating an Application Context
Putting It All Together
2 / 24Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University
Database Programming
What is Spring?
The Spring Framework is an Inversion of Control (IoC) containerwith a number of additional integrated features and modules.
– To some it is just an IoC container;to others it is an entire platform for application development.
Spring Framework
– Created by Rod Johnson in 2000.
– Spring rose to prominence as an alternative to Enterprise Java Beans (EJBs).
– Rod's seminal text, Expert One-on-One J2EE Design and Development, published by WROX in 2002, introduced a large number of developers to the idea of replacing EJBs with a simple IoC container and a number of APIs that served to isolate your programs from the rougher edges in Sun's APIs.
3 / 24Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University
Database Programming
What is Inversion of Control (IoC) ?
There's no single definition of IoC, but a central concept is Dependency Injection.
– To some it is just an IoC container;to others it is an entire platform for application development.
From Wikipedia:
– ... a pattern in which responsibility for object creation and object linking is removed from the objects and transferred to a factory.
Spring, the lightweight container, assumes responsibility for wiring together a set of components, and injects dependencies either via JavaBean properties or constructor arguments.
If you are interested in a longer description of both Dependency Injection and Inversion of Control, you should read Martin Fowler's Inversion of Control Containers and the Dependency Injection Pattern.
4 / 24Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University
Database Programming
Combining Spring and Hibernate
Adding the Spring framework as a project dependency
build.gradle :
dependencies {
compile( 'org.springframework:spring-core:4.+' ) {
exclude group: 'commons-logging', module: 'commons-logging'
}
compile 'org.springframework:spring-context:4.+'
compile 'org.springframework:spring-orm:4.+'
runtime 'org.slf4j:jcl-over-slf4j:1.+'
}
5 / 24Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University
Database Programming
Writing a Data Access Object
What is a Data Access Object (DAO) ?
The DAO pattern:
– Consolidates all CRUD operations (create, read, update, delete) into a single interface usually organized by table or object type.
– Provides one or more swappable implementations of this interface which can use any number of different persistence APIs and underlying storage media.
public interface AlbumDAO {void create(Album album);Album read(Integer id);int update(Album album);int delete(Album album);
}
public class AlbumHibernateDAO implements AlbumDAO {public void create(Album album) { … };public Album read(Integer id) { … };public int update(Album album) { … };public int delete(Album album) { … };
}
6 / 24Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University
Database Programming
Book Example DAOs
Three Entities
– Artist, Album, Track
Three DAOs
– ArtistDAO, AlbumDAO, TrackDAO
public interface ArtistDAO {Artist persist(Artist artist);void delete(Artist artist);Artist uniqueByName(String name);Artist getArtist(String name, boolean create);
}
7 / 24Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University
Database Programming
ArtistDAO interface
package com.oreilly.hh.dao;
import com.oreilly.hh.data.Artist;
public interface ArtistDAO {
public Artist persist(Artist artist);
public void delete(Artist artist);
public Artist uniqueByName(String name);
public Artist getArtist(String name, boolean create);
}
8 / 24Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University
Database Programming
ArtistHibernateDAO (Old Style: HibernateTemplate)
public class ArtistHibernateDAO extends HibernateDaoSupport implements ArtistDAO {
public Artist persist(Artist artist) {return (Artist) getHibernateTemplate().merge(artist);
}public void delete(Artist artist) {
getHibernateTemplate().delete(artist);}public Artist uniqueByName(final String name) {
return (Artist) getHibernateTemplate().execute(new HibernateCallback() {public Object doInHibernate(Session session) {
Query query = getSession().getNamedQuery("com.oreilly.hh.artistByName");
query.setString("name", name);return (Artist) query.uniqueResult();
}});
}public Artist getArtist(String name, boolean create) {
Artist found = uniqueByName(name);if (found == null && create) {
found = new Artist(name, new HashSet<Track>(), null);found = persist(found);
}if (found != null && found.getActualArtist() != null) {
return found.getActualArtist();}return found;
}}
ch13-0-spring-annotation
ch13-1-dao-service-annotation
9 / 24Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University
Database Programming
ArtistHibernateDAO (New Style 1: xml injection)
public class ArtistHibernateDAO implements ArtistDAO {private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory) {this.sessionFactory = sessionFactory;
}
public Artist persist(Artist artist) {sessionFactory.getCurrentSession().saveOrUpdate(artist);
return artist;}
public void delete(Artist artist) {sessionFactory.getCurrentSession().delete(artist);
}
public Artist uniqueByName(final String name) {Query query = sessionFactory.getCurrentSession().getNamedQuery("com.oreilly.hh.artistByName");query.setString("name", name);return (Artist) query.uniqueResult();
}
public Artist getArtist(String name, boolean create) {…
}}
ch13-2-hibernate-api-dao-annotation
10 / 24Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University
Database Programming
ArtistHibernateDAO (New Style 2: annotation injection)
@Repositorypublic class ArtistHibernateDAO implements ArtistDAO {
@Autowiredprivate SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory) {this.sessionFactory = sessionFactory;
}
public Artist persist(Artist artist) {sessionFactory.getCurrentSession().saveOrUpdate(artist);
return artist;}
public void delete(Artist artist) {sessionFactory.getCurrentSession().delete(artist);
}
public Artist uniqueByName(final String name) {Query query = sessionFactory.getCurrentSession()
.getNamedQuery("com.oreilly.hh.artistByName");query.setString("name", name);return (Artist) query.uniqueResult();
}
public Artist getArtist(String name, boolean create) {…
}}
ch13-3-autowired-annotation
11 / 24Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University
Database Programming
Why would I want to use a DAO?
Increased Flexibility
– Since you are coding to an interface, you can easily swap in a new DAO implementation if you need to use a different O/R mapping service or storage medium.
– When you put a DAO interface between your application's logic and the persistence layer, you've made it easier to swap in other implementations for a particular DAO class or method.
– iBatis, TopLink, Hibernate, Spring Template
Isolation
– This flexibility and isolation goes both ways—it is easier to replace both the implementation of a specific DAO class, and it is easier to reuse your persistence layer when you need to rewrite or upgrade your application logic.
12 / 24Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University
Database Programming
Creating an Applicatin Context of Spring
We discussed how Spring would assume responsibility for creating and connecting the components in our application.
For Spring to do this,we need to
tell it about the various components (which Spring calls beans)in our system and
how they are connected to each other.
We do this using an XML documentthat describes the class of each bean, assigns it an ID,and establishes its relationships to other beans.
This XML document is then used by Spring to create an ApplicationContextobject from which we can retrieve our components by name.
13 / 24Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University
Database Programming
Our Spring Application Context
Figure 13-2. Our Spring application context
Three test components are connected to three DAO objects.
The DAO objects all have a reference to the sessionFactory object.
14 / 24Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University
Database Programming
Example 13-8. Spring applicationContext.xml …
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" … >
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"><property name="annotatedClasses"><list><value>com.oreilly.hh.data.Album</value><value>com.oreilly.hh.data.AlbumTrack</value><value>com.oreilly.hh.data.Artist</value><value>com.oreilly.hh.data.StereoVolume</value><value>com.oreilly.hh.data.Track</value>
</list></property><property name="hibernateProperties"><props><prop key="hibernate.show_sql">false</prop><prop key="hibernate.format_sql">true</prop><prop key="hibernate.transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</prop><prop key="hibernate.connection.pool_size">0</prop><prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect </prop><prop key="hibernate.connection.driver_class">org.hsqldb.jdbcDriver</prop ><prop key="hibernate.connection.url">jdbc:hsqldb:data/music;shutdown=true</prop><prop key="hibernate.connection.username">sa</prop><prop key="hibernate.connection.password"></prop>
</props></property>
</bean>
15 / 24Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University
Database Programming
Example 13-8. Spring applicationContext.xml …
<!-- enable the configuration of transactional behavior based on annotations -- >
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"><property name="sessionFactory"><ref local="sessionFactory"/>
</property></bean>
<!-- A default RequiredAnnotationBeanPostProcessor will be registered bythe "context:annotation-config" and "context:component-scan" XML tags.
--><bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBean PostProcessor"/><context:annotation-config />
16 / 24Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University
Database Programming
Example 13-8. Spring applicationContext.xml …
<!-- Define our Data Access beans -->
<bean id="albumDAO" class="com.oreilly.hh.dao.hibernate.AlbumHibernateDAO"><property name="sessionFactory" ref="sessionFactory"/>
</bean>
<bean id="artistDAO" class="com.oreilly.hh.dao.hibernate.ArtistHibernateDAO"><property name="sessionFactory" ref="sessionFactory"/>
</bean>
<bean id="trackDAO" class="com.oreilly.hh.dao.hibernate.TrackHibernateDAO"><property name="sessionFactory" ref="sessionFactory"/>
</bean>
17 / 24Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University
Database Programming
Example 13-8. Spring applicationContext.xml
<!-- Define our Test beans -->
<bean id="createTest" class="com.oreilly.hh.CreateTest"><property name="trackDAO" ref="trackDAO"/><property name="artistDAO" ref="artistDAO"/>
</bean>
<bean id="queryTest" class="com.oreilly.hh.QueryTest"><property name="trackDAO" ref="trackDAO"/>
</bean>
<bean id="albumTest" class="com.oreilly.hh.AlbumTest"><property name="albumDAO" ref="albumDAO"/><property name="artistDAO" ref="artistDAO"/><property name="trackDAO" ref="trackDAO"/>
</bean>
</beans>
18 / 24Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University
Database Programming
Service Layer : the Test interface
Example 13-9. The Test interface
The Transactional annotation takes care of binding a Session to the current Thread, starting a transaction, andeither committing the transaction if the method returns normally,or rolling it back if there is an exception.
package com.oreilly.hh;
import org.springframework.transaction.annotation.Transactional;
/*** A common interface for our example classes. We'll need this* because TestHarness needs to cast CreateTest, QueryTest, or* AlbumTest to a common interface after it retrieves the bean* from the Spring application context.*/
public interface Test {/*** Runs a simple example*/
@Transactional(readOnly=false)public void run();
}
19 / 24Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University
Database Programming
How do I activate the transactional annotation?
applicationContext.xml
The tx:annotation-driven element simply activates the Transactional annotation and points it to a PlatformTransactionManager.
HibernateTransactionManager is an implementation of the Spring Framework's PlatformTransactionManager. It takes care of binding a Hibernate Session from the sessionFactory to the current Thread using SessionFactoryUtils.
The Transactional annotation ensures that the same Session will remain open and bound to the current Thread during the execution of the annotated method.
In this application, we're relying on the Transactional annotation to make sure that all of the code in any run() method implementation has access to the same Hibernate Session object.
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"><property name="sessionFactory"><ref local="sessionFactory"/>
</property></bean>
20 / 24Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University
Database Programming
Adapting CreateTest, QueryTest, and AlbumTest …
Example 13-10. CreateTest adapted for use in our Spring context
public class CreateTest implements Test {
private ArtistDAO artistDAO;private TrackDAO trackDAO;
private static void addTrackArtist(Track track, Artist artist) {track.getArtists().add(artist);
}
public void run() {StereoVolume fullVolume = new StereoVolume();Track track = new Track("Russian Trance", "vol2/album610/track02.mp3",
Time.valueOf("00:03:30"), new HashSet<Artist>(), new Date(),fullVolume, SourceMedia.CD, new HashSet<String>());
addTrackArtist(track, artistDAO.getArtist("PPK", true));trackDAO.persist(track);
}
public ArtistDAO getArtistDAO() { return artistDAO; }public void setArtistDAO(ArtistDAO artistDAO) { this.artistDAO = artistDAO; }
public TrackDAO getTrackDAO() { return trackDAO; }public void setTrackDAO(TrackDAO trackDAO) { this.trackDAO = trackDAO; }
}
21 / 24Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University
Database Programming
Adapting CreateTest, QueryTest, and AlbumTest …
Example 13-12. QueryTest adapted for use with Spring
public class QueryTest implements Test {
private static Logger log = Logger.getLogger(QueryTest.class);
private TrackDAO trackDAO;
public void run() {// Print the tracks that will fit in five minutesList<Track> tracks = trackDAO.tracksNoLongerThan( Time.valueOf("00:05:00") );
for (Track track : tracks) {// For each track returned, print out the title and the playTimelog.info("Track: \"" + track.getTitle() + "\", " + track.getPlayTime());
}}
public TrackDAO getTrackDAO() { return trackDAO; }
public void setTrackDAO(TrackDAO trackDAO) { this.trackDAO = trackDAO; }}
22 / 24Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University
Database Programming
Adapting CreateTest, QueryTest, and AlbumTest …
Example 13-13. Reimplementing AlbumTest
public class AlbumTest implements Test {
private static Logger log = Logger.getLogger(AlbumTest.class);
private AlbumDAO albumDAO;private ArtistDAO artistDAO;private TrackDAO trackDAO;
public void run() {Artist artist = artistDAO.getArtist("Martin L. Gore", true);
Album album = new Album("Counterfeit e.p.", 1, new HashSet<Artist>(),new HashSet<String>(), new ArrayList<AlbumTrack>(5), new Date());
album.getArtists().add(artist);album = albumDAO.persist(album);
addAlbumTrack(album, "Compulsion", "vol1/album83/track01.mp3",Time.valueOf("00:05:29"), artist, 1, 1);
addAlbumTrack(album, "In a Manner of Speaking", "vol1/album83/track02.mp3",Time.valueOf("00:04:21"), artist, 1, 2);
album = albumDAO.persist( album );log.info(album);
}…
}
23 / 24Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University
Database Programming
Running CreateTest, QueryTest, and AlbumTest
13-15. Executing TestRunner from Gradle
task ctest(dependsOn: classes, type: JavaExec) {main = 'com.oreilly.hh.TestRunner'args 'createTest'classpath = sourceSets.main.runtimeClasspath
}
task qtest(dependsOn: classes, type: JavaExec) {main = 'com.oreilly.hh.TestRunner'args 'queryTest'classpath = sourceSets.main.runtimeClasspath
}
task atest(dependsOn: classes, type: JavaExec) {main = 'com.oreilly.hh.TestRunner'args 'albumTest'classpath = sourceSets.main.runtimeClasspath
}
24 / 24Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University
Database Programming
Materials for Further Study
Hibernate Home
– http://www.hibernate.org/
Hibernate Manual
– Hibernate Getting Started Guide 3.6
• http://docs.jboss.org/hibernate/core/3.6/quickstart/en-US/html/
– Hibernate Reference Documentation 3.6
• http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/
• http://docs.jboss.org/hibernate/core/3.6/reference/en-US/pdf/hibernate_reference.pdf
– Hibernate Reference Documentation 4.3 and 5.0
Hibernate Tutorial
– http://www.mkyong.com/tutorials/hibernate-tutorials/