דוגמת הדרכה למשאבי מידע של JNDI DataSource של Tomcat Hibernate

ברוכים הבאים למדריך הדוגמה של Hibernate Tomcat JNDI DataSource. כבר ראינו איך להשתמש בכלי Hibernate ORM באפליקציה סטנדלון של ג'אווה, היום נלמד איך להשתמש ב-Hibernate עם DataSource בסביבת ה-Servlet של Tomcat. שימוש ב-Hibernate באפליקציה אינטרנטית הוא קל מאוד, הכל שאנחנו צריכים לעשות הוא להגדיר את תכונות ה-DataSource בקובץ התצורה של Hibernate. תחילה, אנחנו צריכים להגדיר את מסד הנתונים לבדיקה ואת ה-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

כדי להגדיר את ה-DataSource של Tomcat כדי לאתחלו, אנחנו צריכים לבצע מספר שינויים בקבצי התצורה של השרת והקונטקסט של 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. אתה צריך לאתחל את השרת, לא תראה שום שגיאות ביומן של שרת Tomcat. אם יש הגדרות שגויות, כמו שגיאה בסיסמה, תקבל את החריגה המתאימה ביומן של השרת. עליך גם לוודא שקובץ המנהל של MySQL נמצא בתיקיית lib של Tomcat, אחרת Tomcat לא יוכל ליצור חיבור לבסיס הנתונים ותקבל שגיאת ClassNotFoundException ביומנים. כעת התקנו את התקנת JNDI של בסיס הנתונים ושרת Tomcat, בואו נמשיך ליצירת היישום האינטרנטי שלנו באמצעות Hibernate.

צור פרויקט רשת דינמי ב-Eclipse ואז הגדר אותו כפרויקט Maven. מבנה הפרויקט הסופי שלנו יראה כמו בתמונה הבאה. שים לב שאני משתמש ב-Tomcat-7 עבור התקנת הפרויקט שלי וכבר הוספתי אותו לנתיב הבנייה, כך שאין צורך להוסיף בנפרד תלות ב- Servlet API בפרויקט שלנו. Tomcat-7 תומך ב-Servlet 3 specs ונשתמש בהערות כדי ליצור את ה-servlets שלנו. אם אינך מכיר את ההערות של Servlet 3, אתה צריך לבדוק את מדריך ה-Servlet עבור מתחילים. בוא נסתכל על כל אחד מהרכיבים אחד ליד השני.

התלות של 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>

נכונות.dataSource משמשת לספק את שם מקור הנתונים (DataSource) שישמש על ידי Hibernate לצורך פעולות מסד נתונים.

דוגמה למודל עם Hibernate DataSource

כפי שניתן לראות בקובץ התצורה של 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, כדאי לבדוק אותו אם יש לך סבלנות לגבי כל אחת מהאנוטציות שמשתמשים בהן.

שמעת שמקור הנתונים של Hibernate משתמש ב-Tomcat JNDI Servlet Listener?

מכיוון שעלינו לאתחל את SessionFactory של Hibernate כדי שנוכל להשתמש בו באפליקציה וכן כאשר האפליקציה נסגרת, עלינו להשמיד את ה-SessionFactory. לכן, המקום הטוב ביותר לעשות זאת הוא במימוש של 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");
    }
	
}

אם אינך מכיר באזניים של servlet, אנא קרא את המדריך של טוטוריאל של Servlet Listener.

מימוש של דוגמת Hibernate Tomcat JNDI בסרבלט

בואו נכתוב סרבלט פשוט שבו נעביר את מזהה העובד כפרמטר בקשה והוא ידפיס את מידע העובד ממסד הנתונים, ברור שנשתמש בהיברנייט כדי לשאול את מסד הנתונים ולקבל את מידע העובד. 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 Tomcat JNDI

היישום שלנו מוכן כעת, פשוט ייצא כקובץ WAR והפעיל אותו בתוך התכנית Tomcat. למטה יש כמה תמונות מסך בעת שאנו קוראים לשרvlet של היישום שלנו. שימו לב שאני מעביר 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 עבור תוך-קנייה, אני מקווה שזה קל להבין ולהטמיע. להוריד את הפרויקט הדוגמא מהקישור למטה ולשחק איתו כדי ללמוד עוד.

להוריד את פרויקט מקור הנתונים של Hibernate

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