ברוכים הבאים למדריך הדוגמה של 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 עבור תוך-קנייה, אני מקווה שזה קל להבין ולהטמיע. להוריד את הפרויקט הדוגמא מהקישור למטה ולשחק איתו כדי ללמוד עוד.
Source:
https://www.digitalocean.com/community/tutorials/hibernate-tomcat-jndi-datasource-example-tutorial