A few months ago, i’ve read a tutorial about spring 2.5 writen by Endy Muhardin (one of JUG Indonesia Hall Of Fame), that tutorial explained bout newest features of Spring 2.5, this version now supports Annotation. Configuration is no longer always in xml file. this made our effort to build program pragmatically more easier to configure, faster and efficient.
But due to my bustle, and a regulation in place i work now. i have to leave Spring Frameworks. My project prefer choosing EJB3 and Struts2 as main developtment stack. the main reason is our client need a distributable application (even i know that spring support those too). Besides, developt a ORM for handling database using JPA is more interesting for me than other approach. One question is, how bout people who doesnt need EJB feature which needed heavy container like Glassfish or JBOSS to running their application?.
Fortunately, Spring support JPA for connecting to database, we can choose Hibernate or Toplink for JPA implementations. and it’s still can run in light web server like tomcat or jetty. i’ll give you very simple example using JPA+Hibernate in Spring 2.5.
I’m using apache-maven2 for build this program, you can download it here and read this tutorial for installation.
Let me assume you have using maven2 before. Because we using Hibernate-Annotation, we need create a POJO class references from our table in database. All entity class must be registered with @Entity annotation. in Person class below i have added named query. it can be used if we want create costum query beside delete, update or persist (create) data.
package org.thenest.simplespring.models; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.NamedQueries; import javax.persistence.NamedQuery; import javax.persistence.Table; @Entity @Table(name = "PERSON") @NamedQueries( { @NamedQuery(name = "Person.findAll", query = "SELECT p FROM Person p") }) public class Person { private int id; private String name; private int age; public void setId(int id) { this.id = id; } @Id public int getId() { return id; } public void setName(String name) { this.name = name; } public String getName() { return name; } public void setAge(int age) { this.age = age; } public int getAge() { return age; } }
And this is DDL file for create table PERSON (i’m using mysql), and insert data into thus table.
CREATE TABLE PERSON( ID INT(5) PRIMARY KEY NOT NULL AUTO_INCREMENT, NAME VARCHAR(50) NOT NULL, AGE INT(3) NOT NULL); INSERT INTO PERSON values(NULL,'Michael','22'); INSERT INTO PERSON values(NULL,'Alex','23'); INSERT INTO PERSON values(NULL,'Kevin','19');
One DAO class interface and it’s implementations. we can notice that PersonServiceJpa class have @Repository annotation. it’s mean we doesn’t needed to register this DAO class in Spring’s application context. We gonna make all DAO auto scanned.
package org.thenest.simplespring.services; import java.util.List; import org.thenest.simplespring.models.Person; public interface IPersonService { public boolean save(Person person); public List<Person> getAll(); public Person getById(int id); public boolean delete(Person person); public boolean update(Person person); }
package org.thenest.simplespring.services.jpa; import java.util.List; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import javax.persistence.Query; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; import org.thenest.simplespring.models.Person; import org.thenest.simplespring.services.IPersonService; @Repository("iPersonService") @Transactional(readOnly = true) public class PersonServiceJpa implements IPersonService { private EntityManager entityManager; @PersistenceContext public void setEntityManager(EntityManager entityManager) { this.entityManager = entityManager; } public EntityManager getEntityManager() { return entityManager; } @Override public Person getById(int id) { // TODO Auto-generated method stub return entityManager.find(Person.class, id); } public List<Person> getAll() { Query query = entityManager.createNamedQuery("Person.findAll"); List&lt;Person&gt; persons = null; persons = query.getResultList(); return persons; } @Override public boolean save(Person person) { entityManager.persist(person); entityManager.flush(); return true; } @Override public boolean update(Person person) { entityManager.merge(person); entityManager.flush(); return true; } @Override public boolean delete(Person person) { person = entityManager.getReference(Person.class, person.getId()); if (person == null) return false; entityManager.remove(person); entityManager.flush(); return true; } }
And persistence.xml file :
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0"> <persistence-unit name="testa" transaction-type="RESOURCE_LOCAL"> <class>org.thenest.simplespring.models.Person</class> </persistence-unit> </persistence>
Here they are application context, you need to change dataSource setting with your locat variable.
<?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:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation=" http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"> <context:annotation-config /> <context:component-scan base-package="org.thenest.simplespring.services" /> <tx:annotation-driven /> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" p:driverClassName="com.mysql.jdbc.Driver" p:url="jdbc:mysql://localhost/iseng" p:username="root" p:password="rahasia" /> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" p:dataSource-ref="dataSource" p:jpaVendorAdapter-ref="jpaAdapter"> <property name="loadTimeWeaver"> <bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" /> </property> </bean> <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager" p:entityManagerFactory-ref="entityManagerFactory" /> <bean id="jpaAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" p:database="MYSQL" p:showSql="true" /> </beans>
Cause i’m using JUnit too for unit testing, this is unit testing class. i assume you have using JUnit too before.
package test.org.thenest.simplespring; import org.apache.log4j.BasicConfigurator; import org.apache.log4j.Logger; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.thenest.simplespring.models.Person; import org.thenest.simplespring.services.IPersonService; public class PersonDaoSpringJpaTest { private ApplicationContext ctx; private IPersonService personService; private Logger log = Logger.getLogger(this.getClass()); public PersonDaoSpringJpaTest() { BasicConfigurator.configure(); // TODO Auto-generated constructor stub ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); personService = (IPersonService) ctx.getBean("iPersonService"); log.info("Application Context Loaded"); } @Test public void testGetAll() { log.info("Test get all ================================="); for (Person p : personService.getAll()) { log.info("Name : " + p.getName() + " Age " + p.getAge()); } } @Test public void testSave() { log.info("Test Save Data ================================="); Person person = new Person(); person.setName("Raven"); person.setAge(23); personService.save(person); } @Test public void testGetDataById() { log.info("Test get data by id =========================="); Person p = personService.getById(1); log.info("Name : " + p.getName() + " Age " + p.getAge()); } @Test public void testUpdateData() { log.info("Test update data ============================="); Person p = personService.getById(1); log.info("Name : " + p.getName() + " Age " + p.getAge()); p.setAge(30); personService.update(p); } @Test public void testDeleteData() { log.info("Test delete all =============================="); Person p = personService.getById(1); personService.delete(p); } }
And last, Maven 2 build file, pom.xml.
<?xml version="1.0" encoding="UTF-8"?> <project> <modelVersion>4.0.0</modelVersion> <groupId>SimpleSpringJpaHibernateApp</groupId> <artifactId>SimpleSpringJpaHibernateApp</artifactId> <packaging>jar</packaging> <version>0.0.1-SNAPSHOT</version> <description></description> <build> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <configuration> <executable>${JAVA_HOME}/bin/javac </executable> <compilerVersion>1.6</compilerVersion> <source>1.6</source> <target>1.6</target> <debug>true</debug> <fork>true</fork> <showWarnings>true</showWarnings> <showDeprecation>true</showDeprecation> </configuration> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.9</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring</artifactId> <version>2.5.4</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>2.5.5</version> <scope>test</scope> </dependency> <dependency> <groupId>javax.persistence</groupId> <artifactId>persistence-api</artifactId> <version>1.0</version> </dependency> <dependency> <groupId>hsqldb</groupId> <artifactId>hsqldb</artifactId> <version>1.8.0.7</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager </artifactId> <version>3.3.2.GA</version> </dependency> <dependency> <groupId>commons-lang</groupId> <artifactId>commons-lang</artifactId> <version>2.4</version> </dependency> <dependency> <groupId>commons-collections</groupId> <artifactId>commons-collections</artifactId> <version>3.2</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.6</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.2</version> </dependency> </dependencies> </project>
You can download all complete code here . If you wan’t to integrating Spring without JPA bridge, I’ve already short tutorial about Spring 3.0 and Hibernate here
That’s really what I want!
Thank you very much for your kindly sharing!
By the way, I suggest you can use dbunit and hibernate3 hbm3ddl to create datebase schema and inject data into the database using maven.
Hi Kasim
Thanks for your suggestion, glad to help you
The code above bombed on me at:
personService = (IPersonService) ctx.getBean(“iPersonService”);
It seems there is no such bean declared in the above spring config file.
Ahh… it was a typo causing issue. Your code works fine…
Pingback: Spring 3.0 and Hibernate tutorial (part 1) « Me and my chaotic life