Spring 3.0 Hibernate Template Utility Project Part 1

The following topics will be discussed in this article:

  • Downloading & Installing SpringSource Tool Suite (STS) Version: 2.8.1.
  • Setting up a Spring Hibernate Template Utility project.
  • Executing the packaged Hibernate Test Case.
  • A detailed walk through of the Spring Hibernate Template Utility project components.

Downloading & Installing SpringSource Tool Suite (STS) Version: 2.8.1.
SpringSource Tool Suite (STS) can be downloaded for free from the Spring website: Spring STS Download
Note: For this example I am downloading springsource-tool-suite-2.8.1.RELEASE-e3.7.1-win32-installer.exe installed at C:\springsource using java version “1.6.0_16″. I followed the default installation options until complete.

Once the installation is complete launch STS. Close the welcome screen, your setup should look very similar to this:

Spring Source Tools Home Screen

Figure1: Spring Source Tools Home Screen

Setting up the Spring Hibernate Template Utility Project
Next lets create Spring Hibernate Template Utility Project. In STS execute the following steps:

  1. Click on File –> New –> Spring Template Project. Select Simple Spring Hibernate Utility Project and click Next. (I set my project name to ‘SpringHibernateTemplateProject’ and defined the top level package as ‘fm.devhub.myspringutility’).
  2. You will see an alert notifying you to download the necessary resources, click Yes. What this will do is pull down the necessary libraries for your project to build correctly.

Note: Ensure your proxy settings are configured if you use one. Otherwise the files will not be able to download. You can set them by going to the Window menu –> Preferences –> General –> Network Connections.

Figure 2: New Spring 3.0 Hibernate Utility Project

Figure 2: New Spring 3.0 Hibernate Utility Project

Executing the packaged Hibernate Test Case.
The goal of the Hibernate Utility Template is to provide all the libraries you need to get started with using Hibernate and a simple test case with a few beans configured, this will allow you expand/extend Hibernate functionality with ease. Upon execution of the provided test case (OrderPersistenceTests) we can verify that the project as provided is working correctly.

To run the provided test case right click on ‘OrderPersistenceTests’ in the fm.devhub.myspringutility package of the src/test/java directory. Click Run as –> JUnit Test. You should see as JUnit Panel in the left indicating that all of the configured test executed without any errors.

Figure 3: Spring3.0 Hibernate Utility Test Success

Figure 3: Spring3.0 Hibernate Utility Test Success

A detailed walk through of the Spring Hibernate Template Utility project components.
In this section we will step through most of the files & code included in the Hibernate Utility Project. Although this should be considered skimming the surface of both Spring and Hibernate, you should come away with a basic understanding of how both frameworks work together. Also, Part 2 of this tutorial will cover both frameworks more deeply as well as incorporating the use of a non-embedded database (MySQL for example).

HibernateConfiguration.java

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package fm.devhub.myspringutility;
import java.util.Properties;
import javax.sql.DataSource;
import org.hibernate.dialect.H2Dialect;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.orm.hibernate3.HibernateTransactionManager;
import org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean;
@Configuration
public class HibernateConfiguration {
@Value("#{dataSource}")
private DataSource dataSource;
@Bean
public AnnotationSessionFactoryBean sessionFactoryBean() {
Properties props = new Properties();
props.put("hibernate.dialect", H2Dialect.class.getName());
props.put("hibernate.format_sql", "true");
AnnotationSessionFactoryBean bean = new AnnotationSessionFactoryBean();
bean.setAnnotatedClasses(new Class[]{Item.class, Order.class});
bean.setHibernateProperties(props);
bean.setDataSource(this.dataSource);
bean.setSchemaUpdate(true);
return bean;
}
@Bean
public HibernateTransactionManager transactionManager() {
return new HibernateTransactionManager( sessionFactoryBean().getObject() );
}
}

Line 14:
The @Configuration annotation denotes that the Bean is a configuration bean. Annotating a class with the @Configuration indicates that the class can be used by the Spring IoC container as a source of bean definitions and in this case its being used to configure the Hibernate Datasource. In order to understand how annotations and IOC works, i would recommend reading this article (its also referenced in the additional reading section below): Martin Fowler: IOC & Dependency Injection

Line 17:
@Bean plays the same role as the Bean XML tag in a spring configuration file. We are simply moving the configuration to Java instead of XML. Whether or not you would like to use annotations is completely up to you.

Line 21:
AnnotationSessionFactoryBean is a factory that produces SessionFactory automatically (Spring handles this internally). So in essence the inclusion of AnnotationSessionFactoryBean ensures that the bean will receive an immutable instance of a Hibernate Session on which Hibernate operations can be executed.

Line 35:
The HibernateTransactionManager creates a Transaction Manager to manage database transactions for our bean. In Part 2 of this tutorial we will delve further into transaction managers and transaction intercepters.

So in summary the class above using Java annotations have substituted the need for the a Spring bean configuration in XML.

Item.java

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
package fm.devhub.myspringutility;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
/**
* An item in an order
*/
@Entity
public class Item {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@ManyToOne
private Order order;
private String product;
private double price;
private int quantity;
/**
* @return the order
*/
public Order getOrder() {
return order;
}
/**
* @return the product
*/
public String getProduct() {
return product;
}
/**
* @param product
* the product to set
*/
public void setProduct(String product) {
this.product = product;
}
/**
* @return the price
*/
public double getPrice() {
return price;
}
/**
* @param price
* the price to set
*/
public void setPrice(double price) {
this.price = price;
}
/**
* @return the quantity
*/
public int getQuantity() {
return quantity;
}
/**
* @param quantity
* the quantity to set
*/
public void setQuantity(int quantity) {
this.quantity = quantity;
}
/**
* @return the id
*/
public Long getId() {
return id;
}
}

Line 13:
This is the Entity Bean declaration. The concept in Spring for an Entity bean mirrors the J2EE concept of an Entity bean in the sense that Entity beans represent a business object in a persistent storage mechanism. Basically an entity defines a table in a relational database where each instance of the bean would correlate to a row in that table.

Lines 16-17:
The Bean ID is equivalent to a unique ID associated with a row in a database table. There are five different strategies for generating Bean id’s and they are TABLE, SEQUENCE, IDENTITY, AUTO, and NONE. In this case we are using AUTO.

They are defined as follows:

AUTO Indicates that the persistence provider should pick an appropriate strategy for the particular database.
IDENTITY Indicates that the persistence provider must assign primary keys for the entity using database identity column.
SEQUENCE Indicates that the persistence provider must assign primary keys for the entity using database sequence column.
TABLE Indicates that the persistence provider must assign primary keys for the entity using an underlying database table to ensure uniqueness.

Line 20:
A @ManyToOne annotation is used to denote that the relationship is associated with the Order object, indicating that an Order can contain many Products.

Order.java

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
package fm.devhub.myspringutility;
import java.util.Collection;
import java.util.LinkedHashSet;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.Table;
/**
* An order.
*/
@Entity
@Table(name="T_ORDER")
public class Order {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
private String customer;
@OneToMany(cascade=CascadeType.ALL)
@JoinColumn(name="ORDER_ID")
private Collection items = new LinkedHashSet();
/**
* @return the customer
*/
public String getCustomer() {
return customer;
}
/**
* @param customer the customer to set
*/
public void setCustomer(String customer) {
this.customer = customer;
}
/**
* @return the items
*/
public Collection getItems() {
return items;
}
/**
* @param items the items to set
*/
public void setItems(Collection items) {
this.items = items;
}
/**
* @return the id
*/
public Long getId() {
return id;
}
}

Line 20:
This is the Entity Bean declaration. The concept in Spring for an Entity bean mirrors the J2EE concept of an Entity bean in the sense that Entity beans represents a business object in a persistent storage mechanism. Basically an entity defines a table in a relational database where each instance of the bean would correlate to a row in that table.

Line 21:
@Table(name=”T_ORDER”) creates a table called T_ORDER which is mirrored to our Order.java class.

Lines 24-25:
As mentioned above, the Bean ID is equivalent to a unique ID associated with a row in a database table. There are five different strategies for generating Bean id’s and they are TABLE, SEQUENCE, IDENTITY, AUTO, and NONE. In this case we are using AUTO.

They are defined as follows:

AUTO Indicates that the persistence provider should pick an appropriate strategy for the particular database.
IDENTITY Indicates that the persistence provider must assign primary keys for the entity using database identity column.
SEQUENCE Indicates that the persistence provider must assign primary keys for the entity using database sequence column.
TABLE Indicates that the persistence provider must assign primary keys for the entity using an underlying database table to ensure uniqueness.

Lines 30-31:
The cascade option is used to cascade the required operations to the associated entity. If the cascade option is set to CascadeType.ALL then all the operations will be cascaded. For this example we have CascadeType.ALL on the ‘private Collection items = new LinkedHashSet();’ object in association with line 31 “@JoinColumn(name=”ORDER_ID”)”. In other words of an Item is created, then an Order will be created as well.

Specifically Cascade.ALL does the following:

CascadeType.PERSIST: cascades the persist (create) operation to associated entities persist() is called or if the entity is managed
CascadeType.MERGE: cascades the merge operation to associated entities if merge() is called or if the entity is managed
CascadeType.REMOVE: cascades the remove operation to associated entities if delete() is called
CascadeType.REFRESH: cascades the refresh operation to associated entities if refresh() is called
CascadeType.DETACH: cascades the detach operation to associated entities if detach() is called

CascadeType.ALL: all of the above

You can find more information on this in the Hibernate Reference Documentation: Hibernate Reference Documentation

OrderPersistenceTests.java

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
package fm.devhub.myspringutility;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import org.hibernate.SessionFactory;
import org.hibernate.classic.Session;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;
@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
public class OrderPersistenceTests {
@Autowired
private SessionFactory sessionFactory;
@Test
@Transactional
public void testSaveOrderWithItems() throws Exception {
Session session = sessionFactory.getCurrentSession();
Order order = new Order();
order.getItems().add(new Item());
session.save(order);
session.flush();
assertNotNull(order.getId());
}
@Test
@Transactional
public void testSaveAndGet() throws Exception {
Session session = sessionFactory.getCurrentSession();
Order order = new Order();
order.getItems().add(new Item());
session.save(order);
session.flush();
// Otherwise the query returns the existing order (and we didn't set the
// parent in the item)...
session.clear();
Order other = (Order) session.get(Order.class, order.getId());
assertEquals(1, other.getItems().size());
assertEquals(other, other.getItems().iterator().next().getOrder());
}
@Test
@Transactional
public void testSaveAndFind() throws Exception {
Session session = sessionFactory.getCurrentSession();
Order order = new Order();
Item item = new Item();
item.setProduct("foo");
order.getItems().add(item);
session.save(order);
session.flush();
// Otherwise the query returns the existing order (and we didn't set the
// parent in the item)...
session.clear();
Order other = (Order) session
.createQuery( "select o from Order o join o.items i where i.product=:product")
.setString("product", "foo").uniqueResult();
assertEquals(1, other.getItems().size());
assertEquals(other, other.getItems().iterator().next().getOrder());
}
}

Lines 15-16:
These annotations load the default configuration context for Spring as well as the ‘SpringJUnit4ClassRunner.class’ for JUnit testing. What SpringJUnit4ClassRunner.class does is provide JUnit4.4 functionality alongside with Spring TestContext framework functionality. If you notice on Line 23 for example, we are using the @Transactional annotation which is apart of the TestContext framework. I would recommend reading this article if you are not familiar with Springs TestContext: Spring 3.0.5 TestContext Framework

Lines 19-20:
@Autowired in this case is basically ensuring that the Hibernate SessionFactory is injected into the Bean prior to the execution of any other Bean configuration items. @AutoWired ensures that fields are injected right after construction of a bean, before any config methods are invoked. In this case we are applying to the SessionFactory which makes sense as none of the test cases can execute without a Hibernate Session available.

Lines 22-23:
@Test is a JUnit annotation made accessible to us by the SpringJunit4ClassRunner which was loaded on line 16. The Test annotation tells JUnit that the public void method to which it is attached can be run as a test case. @Transactional enables transactions for the particular method.

Lines 25-30:
Here we are executing a basic test case asserting that an Order ID is returned after an order has been added to the database.

Additional Reading:
Martin Fowler: IOC & Dependency Injection
Spring 3.0.5 TestContext Framework

Thanks for reading! If you find any technical inaccuracies or deficiencies in this article, please make devhub.fm aware by posting a comment. Any feedback is welcome & encouraged.