In my previous spring tutorial, i’ve given simple example how to integrating Spring Framework with Hibernate through JPA. Now i’ll show you how to engaging Spring with Hibernate using Hibernate template on Spring. It’s easier than you connect using JPA. Because spring already build hibernate support.
First of all, we need to create entity class. Lets give it User class, this will be located on org.adit.spring.hibernate.entity package. Following is the content of User.java
package org.adit.spring.hibernate.entity; import java.io.Serializable; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Table; import org.hibernate.annotations.GenericGenerator; @Entity @Table(name = "user") public class User implements Serializable { /** * */ private static final long serialVersionUID = 8496087166198616020L; private String userId; private String userName; private Integer age; private Boolean registered; @Id @GeneratedValue(generator = "system-uuid") @GenericGenerator(name = "system-uuid", strategy = "uuid") @Column(name = "userId") public String getUserId() { return userId; } public void setUserId(String userId) { this.userId = userId; } @Column(name = "userName", nullable=false) public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } @Column(name = "age") public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Column(name = "registered", nullable=false) public Boolean getRegistered() { return registered; } public void setRegistered(Boolean registered) { this.registered = registered; } }
As you can see, i’m using generator approach, so Id of this record on database will automatically created , so you don’t need to set this entity Id or make this field auto generated when you create the table.
Second, we created DAO class, because just like i told you before it gonna be simple example. So we just only create 4 basic method. Create, Retrtieve, Update and Delete (CRUD). Below is the interface of UserDao.java
package org.adit.spring.hibernate.dao; import java.util.List; import org.adit.spring.hibernate.entity.User; public interface UserDao { public void saveUser(User user); public List<User> getAllUser(User user); public User selectUserById(String userId); public void deleteUser(User user); }
And, we have to implement this interface with this class
package org.adit.spring.hibernate.dao; import java.util.List; import org.adit.spring.hibernate.entity.User; import org.hibernate.SessionFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.orm.hibernate3.HibernateTemplate; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; //This will make easier to autowired @Repository("userDao") // Default is read only @Transactional public class UserDaoImpl implements UserDao { private HibernateTemplate hibernateTemplate; @Autowired public void setSessionFactory(SessionFactory sessionFactory) { hibernateTemplate = new HibernateTemplate(sessionFactory); } @Transactional(readOnly = false) public void saveUser(User user) { hibernateTemplate.saveOrUpdate(user); } @Transactional(readOnly = false) public void deleteUser(User user) { hibernateTemplate.delete(user); } @SuppressWarnings("unchecked") public List<User> getAllUser(User user) { return (List<User>) hibernateTemplate.find("from " + User.class.getName()); } public User selectUserById(String userId) { return hibernateTemplate.get(User.class, userId); } }
Class UserDaoImpl have added @Repository annotation, so we don’n need to write this dao into Spring beans configuration. This class already auto scanned.
Ok now, we created Spring configuration file. I deliberately separated configuration into small pieces, so it’s will easier for us, when maintenance or change our code in the future. Main configuration is app-config.xml. Contains general configuration for application.
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <list> <value>/configuration.properties</value> </list> </property> </bean> <context:component-scan base-package="org.adit.spring" /> <import resource="db-config.xml" /> </beans>
Second configuration is db-config.xml. This file purposes for saving configuration of datasource and ORM settings.
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd "> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <property name="driverClass"> <value>${jdbc.driver.className}</value> </property> <property name="jdbcUrl"> <value>${jdbc.url}</value> </property> <property name="user"> <value>${jdbc.username}</value> </property> <property name="password"> <value>${jdbc.password}</value> </property> </bean> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> <property name="dataSource"> <ref bean="dataSource" /> </property> <property name="packagesToScan" value="org.adit.spring.hibernate.entity" /> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">${jdbc.hibernate.dialect}</prop> <prop key="hibernate.hbm2ddl.auto">create</prop> <!-- uncomment this for first time run--> <prop key="hibernate.hbm2ddl.auto">create</prop> <prop key="hibernate.show_sql">false</prop> </props> </property> </bean> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory"> <ref bean="sessionFactory" /> </property> </bean> <tx:annotation-driven /> </beans>
I suggest to separate editable property into different file. So when we have to edit or change some property only this configuration.properties is changed.
jdbc.driver.className=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/springhibernate jdbc.username=yourusername jdbc.password=yourpassword jdbc.hibernate.dialect=org.hibernate.dialect.MySQLDialect
For the last, write an unit testing class, Spring has good support for JUnit, it makes us testing painless. This is our unit testing class
package test.adit.spring.hibernate; import java.util.List; import junit.framework.Assert; import org.adit.spring.hibernate.dao.UserDao; import org.adit.spring.hibernate.entity.User; 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; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration( { "/app-config.xml" }) public class UserTest { private UserDao dao; @Autowired public void setDao(UserDao dao) { this.dao = dao; } @Test public void testCreateData() { int expectedResult = 1; User user = new User(); user.setAge(23); user.setUserName("Adit"); user.setRegistered(true); dao.saveUser(user); Assert.assertEquals(expectedResult, dao.getAllUser(new User()).size()); } @Test public void testRetrieveData() { List<User> userList = dao.getAllUser(new User()); Assert.assertEquals(1, userList.size()); User userExpected = userList.get(0); User userResult = dao.selectUserById(userExpected.getUserId()); Assert.assertEquals(userExpected.getUserId(), userResult.getUserId()); } @Test public void testUpdateData() { List<User> userList = dao.getAllUser(new User()); Assert.assertEquals(1, userList.size()); User userExpected = userList.get(0); userExpected.setUserName("Singgih"); dao.saveUser(userExpected); User userResult = dao.selectUserById(userExpected.getUserId()); Assert.assertEquals(userExpected.getUserName(), userResult .getUserName()); } @Test public void testDeleteData() { List<User> userList = dao.getAllUser(new User()); Assert.assertEquals(1, userList.size()); User userExpected = userList.get(0); dao.deleteUser(userExpected); User userResult = dao.selectUserById(userExpected.getUserId()); Assert.assertEquals(userResult, null); } }
You can browse mavenize source code of this tutorial here. Or check out directly using subversion using :
svn checkout http://the-nest.googlecode.com/svn/trunk/java/spring-hibernate1 spring-hibernate1
Next part i’ll show how to build relations between tables in database
A good tutorial indeed. A minor point – the test you’ve written using JUnit is strictly an “integration test” rather than a unit test. It is testing multiple tiers of your application.
Still a good test, but it is important to distinguish unit from integration.
Thanks for the tutorial!
Thanks for your reviews
You’re right, it’s better to call those test integration test rather than unit testing, i was testing group unit in per test.
Very nice tutorial.
Have been having trouble using info in UserTest.java to develop a way to simply store a line in the database.
Would like a simple load program to store a line.
Always have had trouble with DAO.
Thank you,
Anton
Have resolved my mistakes after some researching.
After creating context,ctx from ClassPathXmlApplicationContext:
UserDao dao = (UserDao)ctx.getBean(UserDao.class);
With a dao; the rest came easy.
Thanks for the tutorial,
Anton
Pingback: Eric Blue’s Blog » Weekly Lifestream for July 18th
Hey!
Very nice tutorial.
I am a newbie in this stuff.
The tutorial is very helpful
However it is not working on,
i am researching in order to correct the errors.
Maybe Anton could share with the mistakes he was refering to.
Yours
Simple, neat and very good one. can follow easily. Just follow the steps above to set up Hibernate connection, saves so much of anyone’s time.
Thanks for the tutorial.
Hi, thanks for posting this example. I cannot seem to resolve this problem, even after moving app-config.xml to various places. Do you know what is causing this:
Caused by: org.springframework.beans.factory.BeanDefinitionStoreException: Unexpected exception parsing XML document from class path resource [app-config.xml]; nested exception is java.lang.NoClassDefFoundError: org/springframework/transaction/interceptor/TransactionInterceptor
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:412)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:334)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:302)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:143)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:178)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:149)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:212)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:81)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:1)
at org.springframework.test.context.TestContext.loadApplicationContext(TestContext.java:280)
at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:304)
[RETO] — PLEASE NOTE: I can see the “java.lang.NoClassDefFoundError: org/springframework/transaction/interceptor/TransactionInterceptor” fine. It is like Spring cannot figure stuff out from the location of the app-config-xml file, per it’s indication:
Unexpected exception parsing XML document from class path resource [app-config.xml]
Thanks a million
Hi — I resolved the problem. Strangely enough, it was due to a missing jar: aopalliance.jar. Quite the strange error.
Hi Guys!
I’ve troubles runing maven project in:
http://the-nest.googlecode.com/svn/trunk/java/spring-hibernate1
When I run mvn test I get four errors Messages:
[INFO] Copying 1 resource
[WARNING] POM for ‘javax.mail:mail:pom:1.4:compile’ is invalid.
Its dependencies (if any) will NOT be available to the current build.
[WARNING] POM for ‘javax.jms:jms:pom:1.1:compile’ is invalid.
Its dependencies (if any) will NOT be available to the current build.
[WARNING] POM for ‘com.sun.jdmk:jmxtools:pom:1.2.1:compile’ is invalid.
Its dependencies (if any) will NOT be available to the current build.
[WARNING] POM for ‘com.sun.jmx:jmxri:pom:1.2.1:compile’ is invalid.
Its dependencies (if any) will NOT be available to the current build.
[INFO] [compiler:compile {execution: default-compile}]
[INFO] Compiling 3 source files to /home/humberto/java/Dao/spring-hibernate1/target/classes
[INFO] ————————————————————————
[ERROR] BUILD FAILURE
[INFO] ————————————————————————
[INFO] Compilation failure
error: error reading /home/humberto/.m2/repository/javax/mail/mail/1.4/mail-1.4.jar; error in opening zip file
error: error reading /home/humberto/.m2/repository/javax/jms/jms/1.1/jms-1.1.jar; error in opening zip file
error: error reading /home/humberto/.m2/repository/com/sun/jdmk/jmxtools/1.2.1/jmxtools-1.2.1.jar; error in opening zip file
error: error reading /home/humberto/.m2/repository/com/sun/jmx/jmxri/1.2.1/jmxri-1.2.1.jar; error in opening zip file
can anybody tell me how to correct pom.xml file or where download it?
great post. i wanna share also a spoon-feed tutorial on Spring MVC
http://www.adobocode.com/spring/a-spring-web-mvc-tutorial
and add step-by-step Hibernate JPA capabilities tutorial to it:
http://www.adobocode.com/spring/adding-crud-capability-to-spring-mvc
hope it will help people!