Chapter 13. Hibernate with...

Preview:

Citation preview

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/

Recommended