Добро пожаловать в руководство по примеру использования Hibernate Tomcat JNDI DataSource. Мы уже видели, как использовать инструмент Hibernate ORM в автономном приложении на Java, сегодня мы научимся использовать Hibernate с DataSource в контейнере сервлетов 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
. Просто перезапустите сервер, вы не должны увидеть никаких ошибок в журналах сервера tomcat. Если есть какие-либо неправильные конфигурации, например, неправильный пароль, вы получите соответствующее исключение в журнале сервера. Также убедитесь, что файл драйвера MySQL находится в каталоге lib tomcat, в противном случае tomcat не сможет создать соединение с базой данных, и вы получите ClassNotFoundException
в журналах. Теперь наша настройка базы данных и сервера tomcat JNDI готова, перейдем к созданию нашего веб-приложения с использованием hibernate.
Hibernate Пример источника данных Динамический веб-проект
Создайте динамический веб-проект в Eclipse, а затем настройте его как проект Maven. Структура нашего конечного проекта будет выглядеть как на изображении ниже. Обратите внимание, что я использую Tomcat-7 для развертывания моего проекта, и добавил его в путь сборки, чтобы нам не нужно было отдельно добавлять зависимости Servlet API в наш проект. Tomcat-7 поддерживает спецификации Servlet 3, и мы будем использовать аннотации для создания наших сервлетов. Если вы не знакомы с аннотациями Servlet 3, вам следует ознакомиться с Руководством по Servlet для начинающих. Давайте рассмотрим каждый из компонентов по очереди.
Зависимости Hibernate 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>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, вам следует посмотреть его, если у вас есть какие-либо затруднения с использованием аннотаций.
Слушатель сервлета Tomcat JNDI для источника данных Hibernate
Поскольку нам нужно инициализировать фабрику сеансов Hibernate SessionFactory
, чтобы мы могли использовать ее в приложении, а также при уничтожении веб-приложения, нам нужно уничтожить 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");
}
}
Если вы не знакомы с слушателями сервлетов, прочтите Руководство по слушателям сервлетов.
Пример реализации сервлета Hibernate Tomcat JNDI
Давайте напишем простой сервлет, где мы передадим идентификатор сотрудника в качестве параметра запроса, и он выведет информацию о сотруднике из базы данных. Очевидно, мы будем использовать 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
Наше приложение готово, просто экспортируйте его как war-файл и разверните в контейнере Tomcat. Ниже приведены некоторые снимки экрана при вызове сервлета нашего приложения.
Обратите внимание, что я передаю параметр запроса 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 в контейнере Tomcat. Надеюсь, это легко понять и реализовать. Скачайте образец проекта по следующей ссылке и поиграйтесь с ним, чтобы узнать больше.
Source:
https://www.digitalocean.com/community/tutorials/hibernate-tomcat-jndi-datasource-example-tutorial