Voorbeeld Zelfgemaakte Lente-Hibernate Integratie Tutorial (Lente 4 + Hibernate 3 en Hibernate 4)

Spring is een van de meest gebruikte Java EE Frameworks en Hibernate is het meest populaire ORM-framework. Daarom wordt de combinatie Spring Hibernate veel gebruikt in bedrijfstoepassingen. Onlangs heb ik veel geschreven over Spring Tutorial en Hibernate Tutorial, dus een bericht over spring hibernate-integratie was al lang gepland.

Spring Hibernate

Vandaag zullen we in deze tutorial Spring 4 gebruiken en integreren met Hibernate 3, en vervolgens hetzelfde project bijwerken naar Hibernate 4. Aangezien er veel versies zijn voor zowel Spring als Hibernate, en de Spring ORM-artefacten zowel Hibernate 3 als Hibernate 4 ondersteunen, is het goed dat ik alle afhankelijkheden opsom die ik in mijn project heb gebruikt. Let op dat ik heb opgemerkt dat niet alle versies van Spring en Hibernate compatibel zijn. De onderstaande versies hebben voor mij gewerkt, dus ik denk dat ze compatibel zijn. Als je andere versies gebruikt en een java.lang.NoClassDefFoundError krijgt, betekent dit dat ze niet compatibel zijn. Meestal komt dit doordat Hibernate-klassen van de ene naar de andere package zijn verplaatst, wat deze fout veroorzaakt. Bijvoorbeeld, de klasse org.hibernate.engine.FilterDefinition is verplaatst naar org.hibernate.engine.spi.FilterDefinition in de nieuwste Hibernate-versies.

  • Spring Framework Versie: 4.0.3.RELEASE
  • Hibernate Core en Hibernate EntityManager Versie: 3.6.9.Final en 4.3.5.Final
  • Spring ORM Versie: 4.0.3.RELEASE

Database Setup

I am using MySQL database for my project, so below setup.sql script will create the necessary table for this example.

CREATE TABLE `Person` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(20) NOT NULL DEFAULT '',
  `country` varchar(20) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
commit;

Spring Hibernate Integratie Voorbeeld Projectstructuur

Hieronder zie je de uiteindelijke projectstructuur. We zullen elk van de componenten één voor één doornemen.

Maven-afhankelijkheden

We zullen eerst kijken naar ons pom.xml-bestand voor alle benodigde afhankelijkheden en hun versies.

<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>org.springframework.samples</groupId>
	<artifactId>SpringHibernateExample</artifactId>
	<version>0.0.1-SNAPSHOT</version>

	<properties>

		<!-- Generic properties -->
		<java.version>1.6</java.version>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

		<!-- Spring -->
		<spring-framework.version>4.0.3.RELEASE</spring-framework.version>

		<!-- Hibernate / JPA -->
		<!-- <hibernate.version>4.3.5.Final</hibernate.version> -->
		<hibernate.version>3.6.9.Final</hibernate.version>

		<!-- Logging -->
		<logback.version>1.0.13</logback.version>
		<slf4j.version>1.7.5</slf4j.version>

	</properties>

	<dependencies>
		<!-- Spring and Transactions -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring-framework.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-tx</artifactId>
			<version>${spring-framework.version}</version>
		</dependency>

		<!-- Spring ORM support -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-orm</artifactId>
			<version>${spring-framework.version}</version>
		</dependency>

		<!-- Logging with SLF4J & LogBack -->
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>${slf4j.version}</version>
			<scope>compile</scope>
		</dependency>
		<dependency>
			<groupId>ch.qos.logback</groupId>
			<artifactId>logback-classic</artifactId>
			<version>${logback.version}</version>
			<scope>runtime</scope>
		</dependency>

		<!-- Hibernate -->
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-entitymanager</artifactId>
			<version>${hibernate.version}</version>
		</dependency>
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-core</artifactId>
			<version>${hibernate.version}</version>
		</dependency>

		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.9</version>
		</dependency>
		<dependency>
			<groupId>commons-dbcp</groupId>
			<artifactId>commons-dbcp</artifactId>
			<version>1.4</version>
		</dependency>
	</dependencies>
</project>

Belangrijke afhankelijkheden voor het integratieproject van Spring en Hibernate zijn:

  • spring-context en spring-tx voor kernfunctionaliteiten van Spring. Let op dat ik versie 4.0.3.RELEASE gebruik.
  • spring-orm-afhankelijkheid voor ondersteuning van Spring ORM, dit is vereist voor de integratie van Hibernate in ons Spring-project.
  • hibernate-entitymanager en hibernate-core-afhankelijkheden voor het Hibernate-framework. Let op dat de versie 3.6.9.Final is, om Hibernate 4 te gebruiken hoeven we alleen maar te wijzigen naar 4.3.5.Final zoals hierboven in het pom.xml-bestand is aangegeven.
  • mysql-connector-java voor de MySQL-driver voor databaseverbinding.

Modelklasse of entiteitbean

We kunnen zowel Hibernate XML-gebaseerde mapping als JPA-annotatiegebaseerde mapping gebruiken. Hier gebruik ik JPA-annotaties voor mapping omdat Hibernate JPA-implementatie biedt.

package com.journaldev.model;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

/**
 * Entity bean with JPA annotations
 * Hibernate provides JPA implementation
 * @author pankaj
 *
 */
@Entity
@Table(name="Person")
public class Person {

	@Id
	@Column(name="id")
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	private int id;
	
	private String name;
	
	private String country;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getCountry() {
		return country;
	}

	public void setCountry(String country) {
		this.country = country;
	}
	
	@Override
	public String toString(){
		return "id="+id+", name="+name+", country="+country;
	}
}

DAO-klassen

We zullen twee methoden implementeren in onze DAO-klassen, de eerste om het Person-object in de tabel op te slaan en de tweede om alle records uit de tabel op te halen en de lijst met Personen terug te geven.

package com.journaldev.dao;

import java.util.List;

import com.journaldev.model.Person;

public interface PersonDAO {

	public void save(Person p);
	
	public List<Person> list();
	
}

De implementatie van bovenstaande DAO-klasse zou er als volgt uitzien.

package com.journaldev.dao;

import java.util.List;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;

import com.journaldev.model.Person;

public class PersonDAOImpl implements PersonDAO {

	private SessionFactory sessionFactory;

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }
    
	@Override
	public void save(Person p) {
		Session session = this.sessionFactory.openSession();
		Transaction tx = session.beginTransaction();
		session.persist(p);
		tx.commit();
		session.close();
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<Person> list() {
		Session session = this.sessionFactory.openSession();
		List<Person> personList = session.createQuery("from Person").list();
		session.close();
		return personList;
	}

}

Let op dat dit de enige plaats is waar we Hibernate-gerelateerde klassen gebruiken. Deze aanpak maakt onze implementatie flexibel en gemakkelijk te migreren van de ene technologie naar de andere. Als we bijvoorbeeld het iBatis ORM-framework willen gebruiken, hoeven we alleen maar een DAO-implementatie voor iBatis te verstrekken en vervolgens het configuratiebestand voor de Spring-bean te wijzigen. In het bovenstaande voorbeeld gebruik ik Hibernate-sessiontransactiebeheer. Maar we kunnen ook Spring-declaratief transactiebeheer gebruiken met de @Transactional-annotatie, lees meer op Spring Transaction Management.

Spring Bean Configuration-bestand voor Hibernate 3-integratie

Laten we eerst kijken naar de Spring Bean-configuraties die we nodig hebben voor de integratie met Hibernate 3. We zullen later gedetailleerder ingaan.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://www.springframework.org/schema/beans"
	xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns:aop="https://www.springframework.org/schema/aop"
	xmlns:tx="https://www.springframework.org/schema/tx"
	xsi:schemaLocation="https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
		https://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop-4.0.xsd
		https://www.springframework.org/schema/tx https://www.springframework.org/schema/tx/spring-tx-4.0.xsd">

	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
		destroy-method="close">
		<property name="driverClassName" value="com.mysql.jdbc.Driver" />
		<property name="url" value="jdbc:mysql://localhost:3306/TestDB" />
		<property name="username" value="pankaj" />
		<property name="password" value="pankaj123" />
	</bean>

<!-- Hibernate 3 XML SessionFactory Bean definition-->
<!-- 	<bean id="hibernate3SessionFactory"
		class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
		<property name="dataSource" ref="dataSource" />
		<property name="mappingResources">
			<list>
				<value>person.hbm.xml</value>
			</list>
		</property>
		<property name="hibernateProperties">
			<value>
				hibernate.dialect=org.hibernate.dialect.MySQLDialect
			</value>
		</property>
	</bean> -->

<!-- Hibernate 3 Annotation SessionFactory Bean definition-->
	<bean id="hibernate3AnnotatedSessionFactory"
		class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
		<property name="dataSource" ref="dataSource" />
		<property name="annotatedClasses">
			<list>
				<value>com.journaldev.model.Person</value>
			</list>
		</property>
		<property name="hibernateProperties">
			<props>
				<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
				<prop key="hibernate.current_session_context_class">thread</prop>
				<prop key="hibernate.show_sql">false</prop>
			</props>
		</property>
	</bean>
	
	<bean id="personDAO" class="com.journaldev.dao.PersonDAOImpl">
		<property name="sessionFactory" ref="hibernate3AnnotatedSessionFactory" />
	</bean>
</beans>

Er zijn twee manieren om databaseverbinding details aan Hibernate te verstrekken: ten eerste door alles door te geven in hibernateProperties, en ten tweede door een DataSource te maken en deze vervolgens door te geven aan Hibernate. Ik geef de voorkeur aan de tweede benadering, daarom hebben we de Apache Commons DBCP-afhankelijkheid om een BasicDataSource te maken door databaseverbindingseigenschappen in te stellen. Voor de integratie van Spring en Hibernate 3 biedt Spring ORM twee klassen: org.springframework.orm.hibernate3.LocalSessionFactoryBean wanneer hibernate-mappings XML-gebaseerd zijn, en org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean voor op annotaties gebaseerde mapping. Ik heb een eenvoudige bean-configuratie van LocalSessionFactoryBean in opmerkingen gegeven als je XML-gebaseerde mappings gebruikt. AnnotationSessionFactoryBean breidt de klasse LocalSessionFactoryBean uit, dus het heeft alle basiskenmerken voor hibernate-integratie. De eigenschappen zijn zelfverklarend en voornamelijk gerelateerd aan Hibernate, dus ik zal er niet te diep op ingaan. Maar als je je afvraagt waar hibernateProperties, annotatedClasses vandaan komen, moet je naar de broncode van de bean-klasse kijken. Let op de bean-definitie van personDAO. Zoals ik eerder zei, als we moeten overschakelen naar een ander ORM-framework, moeten we de implementatieklasse hier veranderen en eventuele andere benodigde eigenschappen instellen.

Lente 4 Hibernate 3 Testprogramma

Onze opstelling is nu gereed, laten we een eenvoudig programma schrijven om onze toepassing te testen.

package com.journaldev.main;

import java.util.List;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.journaldev.dao.PersonDAO;
import com.journaldev.model.Person;

public class SpringHibernateMain {

	public static void main(String[] args) {

		ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
		
		PersonDAO personDAO = context.getBean(PersonDAO.class);
		
		Person person = new Person();
		person.setName("Pankaj"); person.setCountry("India");
		
		personDAO.save(person);
		
		System.out.println("Person::"+person);
		
		List list = personDAO.list();
		
		for(Person p : list){
			System.out.println("Person List::"+p);
		}
		// bronnen sluiten
		context.close();	
	}
}

Wanneer we het bovenstaande programma uitvoeren, krijgen we veel output gerelateerd aan Hibernate omdat ik de logging niet goed heb ingesteld, maar dat valt buiten de scope van deze tutorial. We krijgen echter de volgende output gegenereerd door ons programma.

Person::id=3, name=Pankaj, country=India
Person List::id=1, name=Pankaj, country=India
Person List::id=2, name=Pankaj, country=India
Person List::id=3, name=Pankaj, country=India

Lente 4 Hibernate 4 integratiewijzigingen

Nu gaan we onze toepassing wijzigen om Hibernate 4 in plaats van Hibernate 3 te gebruiken. Voor deze migratie moeten we slechts de volgende configuratiewijzigingen aanbrengen.

  1. Verander de Hibernate-versie naar 4.3.5.Final in het pom.xml-bestand, zoals hierboven in de opmerkingen wordt weergegeven.

  2. Wijzig het configuratiebestand van de Spring bean, tot nu toe moet je hebben uitgevonden dat het configuratiebestand van de Spring bean de sleutel is voor de integratie van Spring en het Hibernate-framework. Het onderstaande configuratiebestand van de Spring bean zal werken voor Spring 4 en Hibernate 4 versies.

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="https://www.springframework.org/schema/beans"
    	xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns:aop="https://www.springframework.org/schema/aop"
    	xmlns:tx="https://www.springframework.org/schema/tx"
    	xsi:schemaLocation="https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
    		https://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop-4.0.xsd
    		https://www.springframework.org/schema/tx https://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
    
    	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
    		destroy-method="close">
    		<property name="driverClassName" value="com.mysql.jdbc.Driver" />
    		<property name="url" value="jdbc:mysql://localhost:3306/TestDB" />
    		<property name="username" value="pankaj" />
    		<property name="password" value="pankaj123" />
    	</bean>
    
    
    <!-- Definitie van Hibernate 4 SessionFactory Bean -->
    <bean id="hibernate4AnnotatedSessionFactory"
    		class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    		<property name="dataSource" ref="dataSource" />
    		<property name="annotatedClasses">
    			<list>
    				<value>com.journaldev.model.Person</value>
    			</list>
    		</property>
    		<property name="hibernateProperties">
    			<props>
    				<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
    				<prop key="hibernate.current_session_context_class">thread</prop>
    				<prop key="hibernate.show_sql">false</prop>
    			</props>
    		</property>
    	</bean>
    
    	
    	<bean id="personDAO" class="com.journaldev.dao.PersonDAOImpl">
    		<property name="sessionFactory" ref="hibernate4AnnotatedSessionFactory" />
    	</bean>
    </beans>
    

    Voor Hibernate 4 moeten we org.springframework.orm.hibernate4.LocalSessionFactoryBean gebruiken voor de SessionFactory bean. Spring ORM heeft beide klassen voor Hibernate 3 samengevoegd en er is nu een enkele klasse, dit is goed om verwarring te voorkomen. Alle andere configuraties zijn hetzelfde als voorheen.

Dat is het, ons project is succesvol gemigreerd naar Hibernate 4, netjes toch. Verander gewoon de klasse SpringHibernateMain om spring4.xml te gebruiken voor de bean-configuratie, en het zal prima werken. Je krijgt hetzelfde resultaat als voorheen. Je kunt het eindproject downloaden via de onderstaande link en spelen met meer configuraties om meer te leren.

Download Spring Hibernate Integratieproject

Source:
https://www.digitalocean.com/community/tutorials/spring-hibernate-integration-example-tutorial