웹사이트 검색

Hibernate Tomcat JNDI DataSource 예제 튜토리얼


Hibernate Tomcat JNDI DataSource 예제 자습서에 오신 것을 환영합니다. 우리는 이미 독립형 Java 애플리케이션에서 Hibernate ORM 도구를 사용하는 방법을 살펴보았습니다. 오늘은 Tomcat 서블릿 컨테이너에서 DataSource와 함께 Hibernate를 사용하는 방법을 배우겠습니다. 웹 애플리케이션에서 Hibernate를 사용하는 것은 매우 쉽습니다. Hibernate 구성 파일에서 DataSource 속성을 구성하기만 하면 됩니다. 먼저 Tomcat 컨테이너에 테스트 데이터베이스와 JNDI DataSource를 설정해야 합니다.

Hibernate DataSource JNDI 예제 데이터베이스 설정

예를 들어 MySQL을 사용하고 있습니다. 아래 스크립트가 실행되어 간단한 테이블을 만들고 일부 값을 삽입합니다. 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 컨테이너를 구성하려면 tomcat server.xml 및 context.xml 파일을 일부 변경해야 합니다. <코드>서버.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"/>

server.xml GlobalNamingResources 요소에 위 리소스를 추가합니다. context.xml

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

context.xml 파일에서 위의 ResourceLink를 추가합니다. 애플리케이션이 이름이 jdbc/MyLocalDB인 JNDI 리소스에 액세스할 수 있도록 필요합니다. 서버를 다시 시작하면 Tomcat 서버 로그에 오류가 표시되지 않습니다. 암호가 잘못된 것과 같은 잘못된 구성이 있으면 서버 로그에 해당 예외가 표시됩니다. 또한 MySQL 드라이버 jar 파일이 tomcat lib 디렉토리 안에 있는지 확인해야 합니다. 그렇지 않으면 tomcat이 데이터베이스 연결을 생성할 수 없으며 로그에 ClassNotFoundException이 표시됩니다. 이제 데이터베이스와 Tomcat 서버 JNDI 설정이 준비되었습니다. 이제 최대 절전 모드를 사용하여 웹 애플리케이션을 생성해 보겠습니다.

Hibernate DataSource 예제 동적 웹 프로젝트

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>

Hibernate 최신 버전 4.3.5를 사용하고 있습니다. 최종적으로 Hibernate에 대한 hibernate-core 종속성이 추가되었습니다. mysql-connector-java 종속성은 MySQL 데이터베이스를 사용하기 때문에 추가되지만 이미 Tomcat 컨테이너 라이브러리의 일부이기 때문에 범위가 제공됩니다. MySQL 드라이버 종속성을 추가하지 않더라도 프로젝트가 잘 컴파일되고 실행됩니다. 그러나 누군가가 프로젝트 종속성을 조사할 경우 MySQL 데이터베이스를 사용하고 있음을 분명히 할 수 있도록 포함하는 것이 좋습니다.

최대 절전 모드 데이터 소스 구성

데이터 소스가 포함된 최대 절전 모드 구성 파일은 다음과 같습니다. 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가 사용할 DataSource 이름을 제공하는 데 사용됩니다.

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;
	}
}

Model bean은 우리가 Hibernate Beginners Tutorial에서 사용한 것과 동일합니다. 사용된 주석과 관련된 혼동이 있으면 확인해야 합니다.

Hibernate DataSource Tomcat JNDI 서블릿 리스너

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 예제 서블릿 구현

직원 ID를 요청 매개변수로 전달하고 데이터베이스에서 직원 정보를 출력하는 간단한 서블릿을 작성해 보겠습니다. 분명히 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 예제 애플리케이션 테스트

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

Tomcat 컨테이너에 대한 Hibernate DataSource 예제의 전부입니다. 이해하고 구현하기 쉽기를 바랍니다. 아래 링크에서 샘플 프로젝트를 다운로드하고 이를 가지고 놀면서 자세히 알아보세요.

Hibernate DataSource 프로젝트 다운로드