Hibernate Tomcat JNDI DataSource Voorbeeld Zelfstudie

Welkom bij de Hibernate Tomcat JNDI DataSource voorbeeldhandleiding. We hebben al gezien hoe we Hibernate ORM-tool kunnen gebruiken in een op zichzelf staande Java-toepassing, vandaag zullen we leren hoe we Hibernate met DataSource kunnen gebruiken in de Tomcat-servletcontainer. Het gebruik van Hibernate in een webtoepassing is zeer eenvoudig, het enige wat we nodig hebben is het configureren van DataSource-eigenschappen in het hibernate-configuratiebestand. Allereerst moeten we een testdatabase en JNDI DataSource opzetten in de Tomcat-container.

Hibernate DataSource JNDI Voorbeeld Database Setup

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

De databaseschemanaam is TestDB.

Tomcat JNDI DataSource-configuratie

Om de Tomcat-container te configureren om DataSource te initialiseren, moeten we enkele wijzigingen aanbrengen in de server.xml- en context.xml-bestanden van 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"/>

Voeg de bovenstaande bron toe in het GlobalNamingResources-element van server.xml. context.xml

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

Voeg bovenstaande ResourceLink toe in het context.xml-bestand, het is vereist zodat applicaties toegang hebben tot de JNDI-bron met de naam jdbc/MyLocalDB. Start gewoon de server opnieuw op, je zou geen fouten moeten zien in de serverlogs van Tomcat. Als er verkeerde configuraties zijn, zoals een verkeerd wachtwoord, krijg je de overeenkomstige uitzondering in het serverlogboek. Zorg er ook voor dat het MySQL-driver-JAR-bestand zich in de tomcat lib-map bevindt, anders kan Tomcat geen databaseverbinding maken en krijg je een ClassNotFoundException in de logs. Nu is onze database- en Tomcat-server-JNDI-setup klaar, laten we doorgaan met het maken van onze webapplicatie met behulp van Hibernate.

Hibernate DataSource Voorbeeld Dynamisch Webproject

Maak een dynamisch webproject in Eclipse en configureer het vervolgens als een Maven-project. Onze uiteindelijke projectstructuur zal eruit zien als de onderstaande afbeelding. Let op dat ik Tomcat-7 gebruik voor het implementeren van mijn project en ik heb het aan het build-pad toegevoegd, zodat we niet apart Servlet API-afhankelijkheden aan ons project hoeven toe te voegen. Tomcat-7 ondersteunt Servlet 3-specificaties en we zullen annotaties gebruiken om onze servlets te maken. Als je niet bekend bent met Servlet 3-annotaties, moet je de Servlet Tutorial voor Beginners bekijken. Laten we elk van de componenten één voor één bekijken.

Hibernate Maven-afhankelijkheden

Ons uiteindelijke pom.xml-bestand ziet er als volgt uit.

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

Ons Hibernate-configuratiebestand met datasource ziet er als volgt uit. 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-eigenschap wordt gebruikt om de naam van de DataSource op te geven die door Hibernate zal worden gebruikt voor databasebewerkingen.

Modelklasse voor Hibernate DataSource-voorbeeld

Zoals u kunt zien in het hibernate-configuratiebestand, gebruiken we annotaties in onze modelklasse Employee. Onze model bean ziet er als volgt uit. 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;
	}
}

Model bean is hetzelfde als we gebruikten in Hibernate Beginners Tutorial, je zou het moeten bekijken als je verward bent over een van de gebruikte annotaties.

Hibernate DataSource Tomcat JNDI Servlet Listener

Aangezien we Hibernate SessionFactory moeten initialiseren omdat we het kunnen gebruiken in de applicatie en ook wanneer de webapplicatie wordt vernietigd, moeten we SessionFactory vernietigen. De beste plaats om dit te doen is in een implementatie van 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");
    }
	
}

Als u niet bekend bent met servlet listeners, lees dan Servlet Listener Tutorial.

Hibernate Tomcat JNDI Example Servlet Implementation

Latenn we een eenvoudige servlet schrijven waarbij we het werknemer-ID als verzoekparameter doorgeven en het zal de werknemersinformatie uit de database afdrukken, uiteraard zullen we Hibernate gebruiken om de database te bevragen en werknemersinformatie op te halen. 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>");
        }
	}

}

Het is een zeer eenvoudige servletklasse, ik gebruik de @WebServlet-annotatie om het URI-patroon ervoor op te geven.

Testen van Hibernate DataSource Tomcat JNDI Example Application

Onze toepassing is nu klaar, exporteer gewoon als een war-bestand en implementeer het in de tomcat-container. Hieronder staan enkele screenshots wanneer we onze toepassingsservlet aanroepen. Let op dat ik de empId verzoekparameter doorgeef in de queryreeks van de request-URL. U zult ook onze toepassingslogs zien in de serverlogs.

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

Als u de toepassing ontkoppelt of de server stopt, zult u serverlogs zien voor het vernietigen van de 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

Dat is alles voor het Hibernate DataSource-voorbeeld voor de tomcat-container, ik hoop dat het gemakkelijk te begrijpen en te implementeren is. Download het voorbeeldproject van onderstaande link en probeer ermee te spelen om meer te leren.

Download Hibernate DataSource-project

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