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.
-
Verander de Hibernate-versie naar 4.3.5.Final in het pom.xml-bestand, zoals hierboven in de opmerkingen wordt weergegeven.
-
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.
Source:
https://www.digitalocean.com/community/tutorials/spring-hibernate-integration-example-tutorial