مثال تعليمي لـ Hibernate Tomcat JNDI DataSource

مرحبًا بك في دليل مثال Hibernate Tomcat JNDI DataSource. لقد رأينا بالفعل كيفية استخدام أداة Hibernate ORM في تطبيق Java مستقل. اليوم، سنتعلم كيفية استخدام Hibernate مع DataSource في حاوية servlet Tomcat. استخدام Hibernate في تطبيق الويب سهل للغاية، كل ما نحتاجه هو تكوين خصائص DataSource في ملف تكوين Hibernate. أولاً وقبل كل شيء، نحتاج إلى إعداد قاعدة بيانات اختبار و JNDI DataSource في حاوية Tomcat.

مثال Hibernate DataSource JNDI إعداد قاعدة البيانات

I am using MySQL for my example, below script is executed to create a simple table and insert some values into it. employee.sql

CREATE TABLE `Employee` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(20) DEFAULT NULL,
  `role` varchar(20) DEFAULT NULL,
  `insert_time` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=26 DEFAULT CHARSET=utf8;

INSERT INTO `Employee` (`id`, `name`, `role`, `insert_time`)
VALUES
	(3, 'Pankaj', 'CEO', now());
INSERT INTO `Employee` (`id`, `name`, `role`, `insert_time`)
VALUES
	(14, 'David', 'Developer', now());

اسم مخطط قاعدة البيانات هو TestDB.

تكوين Tomcat JNDI DataSource

لتكوين حاوية Tomcat لتهيئة DataSource، نحتاج إلى إجراء بعض التغييرات في ملفي server.xml و context.xml لـ Tomcat. server.xml

<Resource name="jdbc/MyLocalDB" 
      global="jdbc/MyLocalDB" 
      auth="Container" 
      type="javax.sql.DataSource" 
      driverClassName="com.mysql.jdbc.Driver" 
      url="jdbc:mysql://localhost:3306/TestDB" 
      username="pankaj" 
      password="pankaj123" 
      
      maxActive="100" 
      maxIdle="20" 
      minIdle="5" 
      maxWait="10000"/>

أضف المورد أعلاه في عنصر GlobalNamingResources في server.xml. context.xml

<ResourceLink name="jdbc/MyLocalDB"
              global="jdbc/MyLocalDB"
              auth="Container"
              type="javax.sql.DataSource" />

أضف السطر التالي أعلاه منطقة ResourceLink في ملف context.xml ، هذا مطلوب حتى يتمكن التطبيق من الوصول إلى المورد JNDI بالاسم jdbc/MyLocalDB. قم بإعادة تشغيل الخادم ، لا يجب أن تظهر أي أخطاء في سجلات خادم تومكات. إذا كانت هناك أي تكوينات غير صحيحة ، مثل كلمة المرور غير صحيحة ، ستحصل على الاستثناء المقابل في سجل الخادم. يجب أيضًا التأكد من أن ملف تعريف برنامج تشغيل MySQL موجود في دليل lib برنامج تومكات ، وإلا فلن يتمكن تومكات من إنشاء اتصال قاعدة البيانات وستحصل على ClassNotFoundException في السجلات. الآن قاعدة البيانات وإعداد JNDI لخادم تومكات جاهزة ، لننتقل إلى إنشاء تطبيق الويب الخاص بنا باستخدام Hibernate.

مثال على مصدر بيانات Hibernate في مشروع الويب الديناميكي

إنشاء مشروع ويب ديناميكي في Eclipse ثم تكوينه كمشروع Maven. ستبدو هيكلية مشروعنا النهائية كما في الصورة أدناه. يرجى ملاحظة أنني استخدم Tomcat-7 لنشر مشروعي ولقد أضفته إلى مسار البناء، بحيث لا نحتاج إلى إضافة تبعيات واجهة برمجة تطبيقات Servlet بشكل منفصل في مشروعنا. يدعم Tomcat-7 مواصفات Servlet 3 وسنستخدم التعليمات البرمجية لإنشاء السيرفلتات الخاصة بنا. إذا كنت غير ملم بتعليمات برمجة سيرفلت 3، يجب عليك التحقق من دليل برمجة سيرفلت للمبتدئين. لنلقي نظرة على كل من العناصر واحدة تلو الأخرى.

تبعيات Maven لـ Hibernate

يبدو ملف 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>HibernateDataSource</groupId>
	<artifactId>HibernateDataSource</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>
	
	<dependencies>
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-core</artifactId>
			<version>4.3.5.Final</version>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.0.5</version>
			<scope>provided</scope>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<artifactId>maven-war-plugin</artifactId>
				<version>2.3</version>
				<configuration>
					<warSourceDirectory>WebContent</warSourceDirectory>
					<failOnMissingWebXml>false</failOnMissingWebXml>
				</configuration>
			</plugin>
			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.1</version>
				<configuration>
					<source>1.7</source>
					<target>1.7</target>
				</configuration>
			</plugin>
		</plugins>
		<finalName>${project.artifactId}</finalName>
	</build>
</project>

I am using Hibernate latest version 4.3.5.Final, hibernate-core dependency is added for Hibernate. mysql-connector-java dependency is added because we are using MySQL database, although scope is provided because it’s already part of the tomcat container libraries. Even if we don’t add MySQL driver dependencies, our project will compile and run fine. However it’s better to include it so that if someone will look into the project dependencies, it will be clear that we are using MySQL database.

تكوين مصدر بيانات Hibernate

يبدو ملف تكوين Hibernate الخاص بنا مع مصدر البيانات كما يلي. hibernate.cfg.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
		"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
		"https://hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
        <property name="hibernate.connection.datasource">java:comp/env/jdbc/MyLocalDB</property>
        <property name="hibernate.current_session_context_class">thread</property>
        
        <!-- Mapping with model class containing annotations -->
	<mapping class="com.journaldev.servlet.hibernate.model.Employee"/>
    </session-factory>
</hibernate-configuration>

خاصية hibernate.connection.datasource تُستخدم لتوفير اسم مصدر البيانات الذي سيتم استخدامه بواسطة Hibernate لعمليات قاعدة البيانات.

مثال نموذج مصدر البيانات في Hibernate

كما يمكنك رؤية في ملف تكوين Hibernate، نستخدم التعليقات في فئة نموذجنا Employee. يبدو نموذجنا كما يلي. Employee.java

package com.journaldev.servlet.hibernate.model;

import java.util.Date;

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

@Entity
@Table(name="Employee", 
	   uniqueConstraints={@UniqueConstraint(columnNames={"ID"})})
public class Employee {

	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	@Column(name="ID", nullable=false, unique=true, length=11)
	private int id;
	
	@Column(name="NAME", length=20, nullable=true)
	private String name;
	
	@Column(name="ROLE", length=20, nullable=true)
	private String role;
	
	@Column(name="insert_time", nullable=true)
	private Date insertTime;
	
	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 getRole() {
		return role;
	}
	public void setRole(String role) {
		this.role = role;
	}
	public Date getInsertTime() {
		return insertTime;
	}
	public void setInsertTime(Date insertTime) {
		this.insertTime = insertTime;
	}
}

النموذج هو نفسه الذي استخدمناه في دورة تعلم Hibernate للمبتدئين، يجب عليك التحقق منها إذا كان هناك أي ارتباك يتعلق بأي من التعليقات المستخدمة.

مستمع Servlet لـ Hibernate DataSource Tomcat JNDI

نظرًا لأنه يجب علينا تهيئة SessionFactory في Hibernate لاستخدامها في التطبيق وأيضًا عند تدمير تطبيق الويب، فإن أفضل مكان لفعل ذلك هو في تنفيذ ServletContextListener. HibernateSessionFactoryListener.java

package com.journaldev.servlet.hibernate.listener;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.jboss.logging.Logger;

@WebListener
public class HibernateSessionFactoryListener implements ServletContextListener {

	public final Logger logger = Logger.getLogger(HibernateSessionFactoryListener.class);
	
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
    	SessionFactory sessionFactory = (SessionFactory) servletContextEvent.getServletContext().getAttribute("SessionFactory");
    	if(sessionFactory != null && !sessionFactory.isClosed()){
    		logger.info("Closing sessionFactory");
    		sessionFactory.close();
    	}
    	logger.info("Released Hibernate sessionFactory resource");
    }

    public void contextInitialized(ServletContextEvent servletContextEvent) {
    	Configuration configuration = new Configuration();
    	configuration.configure("hibernate.cfg.xml");
    	logger.info("Hibernate Configuration created successfully");
    	
    	ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();
    	logger.info("ServiceRegistry created successfully");
    	SessionFactory sessionFactory = configuration
				.buildSessionFactory(serviceRegistry);
    	logger.info("SessionFactory created successfully");
    	
    	servletContextEvent.getServletContext().setAttribute("SessionFactory", sessionFactory);
    	logger.info("Hibernate SessionFactory Configured successfully");
    }
	
}

إذا لم تكن على دراية بمستمعات سيرفلت، يرجى قراءة دليل مستمع سيرفلت.

مثال تطبيق Hibernate Tomcat JNDI Servlet Implementation

لنكتب سيرفلت بسيط حيث سنمرر معرف الموظف كمعلمة طلب وسيتم طباعة معلومات الموظف من قاعدة البيانات، وبالطبع سنستخدم Hibernate للاستعلام عن قاعدة البيانات والحصول على معلومات الموظف. GetEmployeeByID.java

package com.journaldev.servlet.hibernate;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.jboss.logging.Logger;

import com.journaldev.servlet.hibernate.model.Employee;

@WebServlet("/GetEmployeeByID")
public class GetEmployeeByID extends HttpServlet {
	private static final long serialVersionUID = 1L;
	
	public final Logger logger = Logger.getLogger(GetEmployeeByID.class);
       
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		int empId = Integer.parseInt(request.getParameter("empId"));
		logger.info("Request Param empId="+empId);
		
		SessionFactory sessionFactory = (SessionFactory) request.getServletContext().getAttribute("SessionFactory");
		
		Session session = sessionFactory.getCurrentSession();
		Transaction tx = session.beginTransaction();
		Employee emp = (Employee) session.get(Employee.class, empId);
		tx.commit();
		PrintWriter out = response.getWriter();
        response.setContentType("text/html");
        if(emp != null){
        out.print("<html><body><h2>Employee Details</h2>");
        out.print("<table border=\"1\" cellspacing=10 cellpadding=5>");
        out.print("<th>Employee ID</th>");
        out.print("<th>Employee Name</th>");
        out.print("<th>Employee Role</th>");
        
            out.print("<tr>");
            out.print("<td>" + empId + "</td>");
            out.print("<td>" + emp.getName() + "</td>");
            out.print("<td>" + emp.getRole() + "</td>");
            out.print("</tr>");
        out.print("</table></body><br/>");
        
        out.print("</html>");
        }else{
        	out.print("<html><body><h2>No Employee Found with ID="+empId+"</h2></body></html>");
        }
	}

}

إنها فئة سيرفلت بسيطة جدًا، أستخدم تعليق @WebServlet لتوفير نمط URI لها.

تطبيق اختبار Hibernate DataSource Tomcat JNDI

تطبيقنا جاهز الآن، فقط قم بتصديره كملف حرب ونشره في حاوية تومكات. أدناه بعض لقطات الشاشة عند استدعاء سيرفليت التطبيق الخاص بنا. لاحظ أنني أمرر معلمة طلب empId في سلسلة الاستعلام لعنوان URL الخاص بالطلب. سترى أيضًا سجلات تطبيقنا المولدة في سجلات الخادم.

May 08, 2014 8:14:16 PM org.hibernate.cfg.Configuration configure
INFO: HHH000043: Configuring from resource: hibernate.cfg.xml
May 08, 2014 8:14:16 PM org.hibernate.cfg.Configuration getConfigurationInputStream
INFO: HHH000040: Configuration resource: hibernate.cfg.xml
May 08, 2014 8:14:16 PM org.hibernate.cfg.Configuration doConfigure
INFO: HHH000041: Configured SessionFactory: null
May 08, 2014 8:14:16 PM com.journaldev.servlet.hibernate.listener.HibernateSessionFactoryListener contextInitialized
INFO: Hibernate Configuration created successfully
May 08, 2014 8:14:16 PM com.journaldev.servlet.hibernate.listener.HibernateSessionFactoryListener contextInitialized
INFO: ServiceRegistry created successfully
May 08, 2014 8:14:16 PM org.hibernate.dialect.Dialect <init>
INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQLDialect
May 08, 2014 8:14:17 PM org.hibernate.engine.jdbc.internal.LobCreatorBuilder useContextualLobCreation
INFO: HHH000423: Disabling contextual LOB creation as JDBC driver reported JDBC version [3] less than 4
May 08, 2014 8:14:17 PM org.hibernate.engine.transaction.internal.TransactionFactoryInitiator initiateService
INFO: HHH000399: Using default transaction strategy (direct JDBC transactions)
May 08, 2014 8:14:17 PM org.hibernate.hql.internal.ast.ASTQueryTranslatorFactory <init>
INFO: HHH000397: Using ASTQueryTranslatorFactory
May 08, 2014 8:14:17 PM com.journaldev.servlet.hibernate.listener.HibernateSessionFactoryListener contextInitialized
INFO: SessionFactory created successfully
May 08, 2014 8:14:17 PM com.journaldev.servlet.hibernate.listener.HibernateSessionFactoryListener contextInitialized
INFO: Hibernate SessionFactory Configured successfully
May 08, 2014 8:14:32 PM com.journaldev.servlet.hibernate.GetEmployeeByID doGet
INFO: Request Param empId=3
May 08, 2014 8:15:22 PM com.journaldev.servlet.hibernate.GetEmployeeByID doGet
INFO: Request Param empId=3

إذا كنت ستقوم بإلغاء نشر التطبيق أو إيقاف الخادم، فسترى سجلات الخادم لتدمير SessionFactory.

May 08, 2014 11:31:16 PM com.journaldev.servlet.hibernate.listener.HibernateSessionFactoryListener contextDestroyed
INFO: Closing sessionFactory
May 08, 2014 11:31:16 PM com.journaldev.servlet.hibernate.listener.HibernateSessionFactoryListener contextDestroyed
INFO: Released Hibernate sessionFactory resource

هذا كل شيء بالنسبة لمثال Hibernate DataSource لحاوية تومكات، آمل أن يكون من السهل فهمه وتنفيذه. قم بتنزيل المشروع العيني من الرابط أدناه وتفاعل معه لتتعلم المزيد.

تنزيل مشروع Hibernate DataSource

Source:
https://www.digitalocean.com/community/tutorials/hibernate-tomcat-jndi-datasource-example-tutorial