مثال تكامل Spring Hibernate (Spring 4 + Hibernate 3 و Hibernate 4)

الربيع هو واحد من أكثر الإطارات استخدامًا في جافا إي إي، و هيبرنيت هو الإطار الأكثر شعبية لرسم الخرائط الكائنية. ولهذا السبب، يتم استخدام مزيج الربيع هيبرنيت كثيرًا في تطبيقات الشركات. مؤخرًا، كتبت الكثير عن برنامج تعليمي للربيع و برنامج تعليمي لهيبرنيت، لذلك كان من المفترض أن يتم نشر مقال حول تكامل الربيع وهيبرنيت منذ وقت طويل.

الربيع هيبرنيت

اليوم في هذا البرنامج التعليمي، سنستخدم الربيع 4 وندمجه مع هيبرنيت 3، ثم نقوم بتحديث نفس المشروع لاستخدام هيبرنيت 4. نظرًا لوجود العديد من الإصدارات لكل من الربيع وهيبرنيت، ويدعم تحفيز الربيع للمشروعين هيبرنيت 3 وهيبرنيت 4، من الجيد أن أقوم بتوضيح جميع التبعيات التي استخدمتها في مشروعي. لاحظ أنني لاحظت أن جميع إصدارات الربيع وهيبرنيت ليست متوافقة، وأن الإصدارات أدناه قد عملت بالنسبة لي لذا أعتقد أنها متوافقة. إذا كنت تستخدم إصدارات أخرى وتحصل على خطأ java.lang.NoClassDefFoundError، فهذا يعني أنها غير متوافقة. في الغالب لأن فئات هيبرنيت تم نقلها من حزمة إلى أخرى مما يتسبب في هذا الخطأ. على سبيل المثال، فئة org.hibernate.engine.FilterDefinition تم نقلها إلى org.hibernate.engine.spi.FilterDefinition في أحدث إصدارات هيبرنيت.

  • إصدار إطار الربيع: 4.0.3.RELEASE

  • إصدار نواة هيبرنيت وهيبرنيت إنتيتي ماناجر: 3.6.9.Final و 4.3.5.Final

  • إصدار تحفيز الربيع: 4.0.3.RELEASE

إعداد قاعدة البيانات

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;

هيكل مشروع مثال تكامل الربيع وهيبرنيت

الصورة أدناه توضح هيكل المشروع النهائي، وسنستعرض كل من المكونات واحد تلو الآخر.

تبعيات Maven

سنبدأ بالنظر في ملف pom.xml لجميع التبعيات المطلوبة وإصداراتها.

<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>

التبعيات المهمة لمشروع تكامل Spring و Hibernate هي:

  • spring-context و spring-tx لوظائف Spring الأساسية. لاحظ أنني أستخدم الإصدار 4.0.3.RELEASE.
  • تبعية spring-orm لدعم Spring ORM، وهي مطلوبة لتكامل Hibernate في مشروع Spring الخاص بنا.
  • تبعيتي hibernate-entitymanager و hibernate-core لإطار العمل Hibernate. لاحظ أن الإصدار هو 3.6.9.Final، ولاستخدام Hibernate 4، كل ما نحتاج إليه هو تغييره إلى 4.3.5.Final كما هو معلق في ملف pom.xml أعلاه.
  • mysql-connector-java لسائق MySQL لاتصال قاعدة البيانات.

فئة النموذج أو كائن الكيان

يمكننا استخدام تعيين الخريطة القائم على XML في Hibernate بالإضافة إلى تعيين الخريطة القائم على تعليقات JPA. هنا أستخدم تعليقات JPA للتعيين لأن Hibernate يوفر تنفيذ JPA.

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

سنقوم بتنفيذ طريقتين في فئات DAO لدينا، الأولى لحفظ كائن Person في الجدول والثانية التي ستقوم بجلب جميع السجلات من الجدول وتعيد قائمة من الأشخاص.

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();
	
}

سيكون تنفيذ الفئة DAO أعلاه كما يلي.

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;
	}

}

لاحظ أن هذا هو المكان الوحيد الذي نستخدم فيه فئات ذات صلة بـ Hibernate. هذا النمط يجعل تنفيذنا مرنًا وسهل الترحيل من تقنية إلى أخرى. على سبيل المثال، إذا أردنا استخدام إطار عمل iBatis ORM، كل ما نحتاج إليه هو توفير تنفيذ DAO لـ iBatis ثم تغيير ملف تكوين الفاصلة الربيعية. في المثال أعلاه، أستخدم إدارة المعاملات Hibernate session. ولكن يمكننا أيضًا استخدام إدارة المعاملات الوصفية للربيع باستخدام @Transactional التعليق، اقرأ المزيد على إدارة المعاملات الربيعية .

ملف تكوين فاصلة الربيع لتكامل Hibernate 3

لنلق نظرة أولاً على تكوينات الفاصلة الربيعية التي نحتاجها لدمج Hibernate 3، سننظر في التفاصيل لاحقًا.

<?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>

هناك طريقتان يمكننا استخدامهما لتوفير تفاصيل اتصال قاعدة البيانات إلى Hibernate، الأولى عن طريق تمرير كل شيء في hibernateProperties والثانية عن طريق إنشاء مصدر بيانات ومن ثم تمريره إلى Hibernate. أفضل الطريقة هي الثانية، وهذا هو السبب في وجود تبعية Apache Commons DBCP لإنشاء BasicDataSource عن طريق تعيين خصائص اتصال قاعدة البيانات. بالنسبة لدمج Spring و Hibernate 3، Spring ORM يوفر فصيلتين – org.springframework.orm.hibernate3.LocalSessionFactoryBean عندما تكون التعيينات هي على أساس XML و org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean للتعيينات على أساس التعليقات. لقد قدمت تكوينًا بسيطًا لفاصلة الجلسة المحلية LocalSessionFactoryBean في التعليقات، إذا كنت تستخدم تعيينات على أساس XML. AnnotationSessionFactoryBean يمتد من الفئة LocalSessionFactoryBean ، لذا يحتوي على جميع الخصائص الأساسية لدمج Hibernate. الخصائص مفهومة ذاتياً وتتعلق في الغالب بـ Hibernate، لذا لن أدخل في تفاصيل كثيرة بشأنها. ولكن إذا كنت تتساءل من أين تأتي hibernateProperties ، annotatedClasses ، فيجب عليك النظر إلى كود مصدر فئة الفاصلة. لاحظ تعريف فاصلة personDAO ، كما قلت سابقاً إذا كان علينا التبديل إلى إطار عمل ORM آخر، يجب علينا تغيير فئة التنفيذ هنا وتعيين أي خصائص أخرى نحتاجها.

برنامج اختبار Spring 4 Hibernate 3

إعدادنا جاهز الآن، دعونا نكتب برنامجًا بسيطًا لاختبار تطبيقنا.

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);
		}
		// أغلق الموارد
		context.close();	
	}
}

عند تنفيذ البرنامج أعلاه، نحصل على الكثير من الإخراج المتعلق بـ Hibernate لأنني لم أقم بإعداد تسجيل بشكل صحيح، ولكن هذا خارج نطاق هذا البرنامج التعليمي. ومع ذلك، نحصل على الإخراج التالي الذي تم إنشاؤه بواسطة برنامجنا.

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

تغييرات تكامل Spring 4 Hibernate 4

الآن دعونا نغير تطبيقنا لاستخدام Hibernate 4 بدلاً من Hibernate 3. لهذه الهجرة، نحتاج إلى إجراء التغييرات التكوينية التالية فقط.

  1. قم بتغيير إصدار Hibernate إلى 4.3.5.Final في ملف pom.xml، كما هو موضح في التعليقات أعلاه.

  2. تغيير ملف تكوين الفاصلة الربيعية، حتى الآن يجب أن تكون قد فهمت أن ملف تكوين فاصلة الربيع هو المفتاح لتكامل إطار الربيع والهايبرنيت. سيعمل ملف تكوين فاصلة الربيع أدناه لإصدارات الربيع 4 والهايبرنيت 4.

    <?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 4 -->
    <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>
    

    بالنسبة للهايبرنيت 4، نحتاج إلى استخدام org.springframework.orm.hibernate4.LocalSessionFactoryBean لجلسة SessionFactory، دمجت فئتي Hibernate 3 في إطار Spring ORM وهناك فئة واحدة الآن، وهذا جيد لتجنب الارتباك. جميع التكوينات الأخرى هي كما كانت من قبل.

هذا كل شيء، تم ترحيل مشروعنا بنجاح إلى هيبرنيت 4، جيد أليس كذلك؟ فقط قم بتغيير فئة SpringHibernateMain لاستخدام spring4.xml لتكوين الفولاذة وسيعمل بشكل جيد، ستحصل على نفس النتيجة كما كانت من قبل. يمكنك تنزيل المشروع النهائي من الرابط أدناه واللعب مع المزيد من التكوينات لتعلم المزيد.

تحميل مشروع تكامل الربيع وهيبرنيت

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