Step
1
Download Hibernate 4 binaries from
http://hibernate.org/downloads/
and Spring binaries using following maven file.
http://hibernate.org/downloads/
and Spring binaries using following maven file.
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>4.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
<version>4.0.0.RELEASE</version>
</dependency>
</dependencies>
|
Step
2
Create a configuration file (if you are using eclipse create this file in src
folder and if this is web application it can go anywhere in WEB-INF but need to
configure the same in web.xml ) to tell Spring context factory what packages it
need to look for beans configured using annotations. Here we will use 2
different annotations to distinguish between service layer, DAO layer (if this
would have been a web application we have user third annotation @Controller). We
will be using annotation @Service for service class and @Component for DAO class. Remember all
these annotations can be used interchangeably.
Also we will create a bean tag
for configuring hibernate session factory and pass connection information to
this session factory by creating another bean called dataSource. How to use
this session factory that we will see in later steps but notice that we need to
use LocalSessionFactoryBean from hibernate4 package and not from hibernate3
package. Here is an example of my configuration file spring-config.xml
<?xml version="1.0"
encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<!-- This
sescion tells Spring context where to look for bean classes with appropriate
annotations -->
<context:component-scan
base-package="com.techcielo.spring4"></context:component-scan>
<!-- Configure JDBC Connection-->
<bean
id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property
name="driverClassName" value="com.mysql.jdbc.Driver"
/>
<property
name="url" value="jdbc:mysql://localhost:3306/northwind"
/>
<property
name="username" value="root" />
<property
name="password" value="" />
</bean>
<!-- Configure Hibernate 4 Session Facotry -->
<bean
id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property
name="dataSource">
<ref
bean="dataSource" />
</property>
<property
name="hibernateProperties">
<props>
<prop
key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop
key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
</beans>
|
So we are ready with basic
configuration and we can now create service class, DAO class and one Main class
to test if this code is working or not. Following is our DAO class in com.techcielo.spring4.dao package (com.techcielo.spring4 is the package
that spring container will check for classes with annotations)
package
com.techcielo.spring4.dao;
import
org.springframework.stereotype.Component;
import
com.techcielo.spring4.bean.Product;
@Component("prodDAO")//This the id by
which it will be auto wired
public class ProductDAO extends BaseDAO{
public Product getProduct(int id){
System.out.println("In DAO
class");
return null;
}
}
|
Notice that we have given
annotation @Component and provided id prodDAO
by which Spring container will wire this class to other classes.
We will use BaseDAO to store
information about Hibernate SessionFactory information configured in our xml
file, but for now we will focus on injecting this class in service class
ProductService as shown below.
package
com.techcielo.spring4.service;
import
org.springframework.beans.factory.annotation.Autowired;
import
org.springframework.stereotype.Service;
import
com.techcielo.spring4.bean.Product;
import
com.techcielo.spring4.dao.ProductDAO;
@Service("prodSvc")
public class ProductService {
@Autowired
private ProductDAO prodDAO;
public void
setProdDAO(ProductDAO prodDAO) {
this.prodDAO = prodDAO;
}
public Product getProduct(int id){
System.out.println("In Service
class...will call DAO");
return prodDAO.getProduct(id);
}
}
|
Here our service class is
identified by annotation @Service and
is given id prodSvc, also bean identified
by prodDAO is attached to it by
annotation @Autowired. Now we will
write a class to test if this code is working or not. So following class will
get an instance of service class and will call method getProduct of this
instance.
package
com.techcielo.spring4.main;
import
org.springframework.context.ApplicationContext;
import
org.springframework.context.support.ClassPathXmlApplicationContext;
import
com.techcielo.spring4.service.ProductService;
public class Main {
public static void main(String[]
args)
{
//Build application context by
reading spring-config.xml
ApplicationContext ctx = new
ClassPathXmlApplicationContext(new String[]{"spring-config.xml"});
//Get an instance of
ProductService class;
ProductService prdSvc =
(ProductService) ctx.getBean("prodSvc");
//Call getProduct method of
ProductService
prdSvc.getProduct(1);
}
}
|
When we run this class
following will be output.
Jan 03, 2014 1:24:51
PM org.springframework.context.support.AbstractApplicationContext
prepareRefresh
INFO: Refreshing
org.springframework.context.support.ClassPathXmlApplicationContext@3caa4b:
startup date [Fri Jan 03 13:24:51 IST 2014]; root of context hierarchy
Jan 03, 2014 1:24:51
PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader
loadBeanDefinitions
INFO: Loading XML
bean definitions from class path resource [spring-config.xml]
Jan 03, 2014 1:24:52
PM org.springframework.jdbc.datasource.DriverManagerDataSource
setDriverClassName
INFO: Loaded JDBC
driver: com.mysql.jdbc.Driver
Jan 03, 2014 1:24:52
PM org.hibernate.annotations.common.Version <clinit>
INFO: HCANN000001:
Hibernate Commons Annotations {4.0.1.Final}
Jan 03, 2014 1:24:52
PM org.hibernate.Version logVersion
INFO: HHH000412:
Hibernate Core {4.1.7.Final}
Jan 03, 2014 1:24:52
PM org.hibernate.cfg.Environment <clinit>
INFO: HHH000206:
hibernate.properties not found
Jan 03, 2014 1:24:52
PM org.hibernate.cfg.Environment buildBytecodeProvider
INFO: HHH000021:
Bytecode provider name : javassist
Jan 03, 2014 1:24:53
PM org.hibernate.dialect.Dialect <init>
INFO: HHH000400:
Using dialect: org.hibernate.dialect.MySQLDialect
Jan 03, 2014 1:24:53
PM org.hibernate.engine.jdbc.internal.LobCreatorBuilder
useContextualLobCreation
INFO: HHH000423:
Disabling contextual LOB creation as JDBC driver reported JDBC version [3]
less than 4
Jan 03, 2014 1:24:53
PM org.hibernate.engine.transaction.internal.TransactionFactoryInitiator
initiateService
INFO: HHH000399:
Using default transaction strategy (direct JDBC transactions)
Jan 03, 2014 1:24:53
PM org.hibernate.hql.internal.ast.ASTQueryTranslatorFactory <init>
INFO: HHH000397:
Using ASTQueryTranslatorFactory
In Service
class...will call DAO
In DAO class
|
Now we will actually hit the
DB and get the details about entiry Product
and will print the same in our Main
class. In order to do this we will use openly available database called
NorthWind. (Going forward to understand different relationships in hibernate we
will be using same database).
Database with more than what is mentioned in above diagram is available
at following location
Step
3
As mentioned in last step now we will use BaseDAO to store information about
Hibernate SessionFactory. We can refer to beans configured in our spring
configuration by using annotation @Resource
so we will use this annotation to get instance of bean identified as
sessionFactory.in spring-config.xml
package
com.techcielo.spring4.dao;
import
javax.annotation.Resource;
import
org.hibernate.Session;
import
org.hibernate.SessionFactory;
public class BaseDAO {
@Resource(name="sessionFactory")
protected SessionFactory sessionFactory;
public void
setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
protected Session
getSession(){
return sessionFactory.openSession();
}
}
|
Now we will create one
entity class (to make it simple we will select an entity which has no
dependency) for Table Products and we identify it as Product. Following is the
table structure.
First we will take only two fields ProductId (as an
identifier) and ProductName. Rest of the fields we will use in consecutive
sections to establish different relationships in hibernate.
package
com.techcielo.spring4.bean;
import
javax.persistence.Column;
import
javax.persistence.Entity;
import
javax.persistence.Id;
import
javax.persistence.Table;
@Entity
@Table(name="products")
public
class Product {
@Id
@Column(name="ProductID")
private int prodID;
@Column(name="ProductName")
private String name;
public int getProdID() {
return prodID;
}
public void setProdID(int prodID)
{
this.prodID = prodID;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
|
Annotation
@Entity tells Hibernate configuration
that this is hibernate entity, @Table
annotation tells which table this entity is attached to @Id tell which instance variable (in this case prodID) will be used as identifier for this class. @Column
annotation tells to which column respective local variable will be attached to.
Now we will add this class information in spring configuration file’s
sessionFactory bean by changing it as follows.
After this step following will be our eclipse project structure.
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property
name="dataSource">
<ref bean="dataSource"
/>
</property>
<property
name="hibernateProperties">
<props>
<prop
key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop
key="hibernate.show_sql">true</prop>
</props>
</property>
<property
name="annotatedClasses">
<list>
<value>com.techcielo.spring4.bean.Product</value>
</list>
</property>
</bean>
|
This
change tells session factory that class Product is hibernate entity with
annotations and need to be interpreted accordingly. Now time to change our DAO
class and get the product from DB for which id is passed. So lets change
getProduct method of this class as follows.
public Product
getProduct(int id){
System.out.println("In DAO
class");
try{
return (Product)
getSession().get(Product.class, id);
}
catch(HibernateException e){
System.out.println("Error
occured while getting data");
}
return null;
}
|
And
in main class we get this instance and print value of this instance.
package
com.techcielo.spring4.main;
import
org.springframework.context.ApplicationContext;
import
org.springframework.context.support.ClassPathXmlApplicationContext;
import
com.techcielo.spring4.bean.Product;
import
com.techcielo.spring4.service.ProductService;
public class Main {
public static void main(String[]
args)
{
//Build application context by
reading spring-config.xml
ApplicationContext ctx = new
ClassPathXmlApplicationContext(new String[]{"spring-config.xml"});
//Get an instance of
ProductService class;
ProductService prdSvc =
(ProductService) ctx.getBean("prodSvc");
//Call getProduct method of
ProductService
Product prod =
prdSvc.getProduct(1);
System.out.println("Got the
product:"+prod.getName());
}
}
|
And
when you run this class following will be output.
Jan 03, 2014 3:07:13
PM org.springframework.context.support.AbstractApplicationContext
prepareRefresh
INFO: Refreshing
org.springframework.context.support.ClassPathXmlApplicationContext@17e845a:
startup date [Fri Jan 03 15:07:13 IST 2014]; root of context hierarchy
Jan 03, 2014 3:07:13
PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML
bean definitions from class path resource [spring-config.xml]
Jan 03, 2014 3:07:14
PM org.springframework.jdbc.datasource.DriverManagerDataSource
setDriverClassName
INFO: Loaded JDBC
driver: com.mysql.jdbc.Driver
Jan 03, 2014 3:07:14
PM org.hibernate.annotations.common.Version <clinit>
INFO: HCANN000001:
Hibernate Commons Annotations {4.0.1.Final}
Jan 03, 2014 3:07:14
PM org.hibernate.Version logVersion
INFO: HHH000412:
Hibernate Core {4.1.7.Final}
Jan 03, 2014 3:07:14
PM org.hibernate.cfg.Environment <clinit>
INFO: HHH000206:
hibernate.properties not found
Jan 03, 2014 3:07:14
PM org.hibernate.cfg.Environment buildBytecodeProvider
INFO: HHH000021:
Bytecode provider name : javassist
Jan 03, 2014 3:07:14
PM org.hibernate.dialect.Dialect <init>
INFO: HHH000400:
Using dialect: org.hibernate.dialect.MySQLDialect
Jan 03, 2014 3:07:14
PM org.hibernate.engine.jdbc.internal.LobCreatorBuilder
useContextualLobCreation
INFO: HHH000423:
Disabling contextual LOB creation as JDBC driver reported JDBC version [3]
less than 4
Jan 03, 2014 3:07:14
PM org.hibernate.engine.transaction.internal.TransactionFactoryInitiator
initiateService
INFO: HHH000399:
Using default transaction strategy (direct JDBC transactions)
Jan 03, 2014 3:07:14
PM org.hibernate.hql.internal.ast.ASTQueryTranslatorFactory <init>
INFO: HHH000397:
Using ASTQueryTranslatorFactory
In Service
class...will call DAO
In DAO class
Hibernate: select
product0_.ProductID as ProductID3_0_, product0_.ProductName as ProductN2_3_0_
from products product0_ where product0_.ProductID=?
Got the
product:Chai
|