Hibernate Tomcat JNDI数据源示例教程
欢迎使用Hibernate Tomcat JNDI DataSource示例教程。
我们已经了解了如何在独立的Java应用程序中使用Hibernate ORM工具,今天我们将学习如何在Tomcat Servlet容器中将Hibernate与DataSource一起使用。
在Web应用程序中使用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, 'hyman', 'CEO', now()); INSERT INTO `Employee` (`id`, `name`, `role`, `insert_time`) VALUES (14, 'David', 'Developer', now());
数据库架构名称为TestDB。
Tomcat JNDI数据源配置
为了配置tomcat容器以初始化DataSource,我们需要对tomcat server.xml和context.xml文件进行一些更改。
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="hyman" password="hyman123" maxActive="100" maxIdle="20" minIdle="5" maxWait="10000"
在server.xmlGlobalNamingResources
元素中添加以上资源。
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 模式创建我们的Web应用程序。
Hibernate DataSource示例动态Web项目
在Eclipse中创建一个动态Web项目,然后将其配置为Maven项目。
我们的最终项目结构将如下图所示。
请注意,我正在使用Tomcat-7进行项目部署,并且已将其添加到构建路径中,因此我们无需在项目中单独添加Servlet API依赖项。
Tomcat-7支持Servlet 3规范,我们将使用批注来创建Servlet。
如果您不熟悉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>
我正在使用Hibernate最新版本4.3.5.Final,为Hibernate添加了hibernate-core
依赖项。
添加了" mysql-connector-java"依赖项,因为我们正在使用MySQL数据库,尽管提供了范围是因为它已经是tomcat容器库的一部分。
即使我们不添加MySQL驱动程序依赖项,我们的项目也可以编译并正常运行。
但是,最好包含它,这样,如果有人研究项目依赖项,很明显我们正在使用MySQL数据库。
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.theitroad.servlet.hibernate.model.Employee" </session-factory> </hibernate-configuration>
hibernate.connection.datasource属性用于提供将被Hibernate用于数据库操作的数据源名称。
Hibernate DataSource示例模型类
如您在Hibernate 配置文件中看到的,我们在模型类Employee中使用注释。
我们的模型bean如下所示。
Employee.java
package com.theitroad.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; } }
模型bean与Hibernate Beginners Tutorial中使用的模型bean相同,您应该检查一下是否与使用的任何注释有关。
Hibernate数据源Tomcat JNDI Servlet侦听器
由于我们必须初始化HibernateSessionFactory
,因为我们可以在应用程序中以及在Web应用程序被销毁时使用它,因此我们需要销毁SessionFactory。
因此,最好在ServletContextListener实现中进行此操作。
HibernateSessionFactoryListener.java
package com.theitroad.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侦听器教程。
Hibernate Tomcat JNDI示例Servlet实现
让我们编写一个简单的servlet,其中我们将员工ID作为请求参数传递,它将从数据库中打印出员工信息,显然,我们将使用Hibernate查询数据库并获取员工信息。
GetEmployeeByID.java
package com.theitroad.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.theitroad.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>"); } } }
这是一个非常简单的servlet类,我使用的是@WebServlet注解,以为其提供URI模式。
测试Hibernate DataSource Tomcat JNDI示例应用程序
我们的应用程序现已准备就绪,只需将其导出为war文件并将其部署在tomcat容器中即可。
下面是调用应用程序servlet时的一些屏幕截图。
请注意,我在请求URL查询字符串中传递了empId请求参数。
您还将在服务器日志中看到我们的应用程序生成的日志。
Jan 08, 2014 8:14:16 PM org.hibernate.cfg.Configuration configure INFO: HHH000043: Configuring from resource: hibernate.cfg.xml Jan 08, 2014 8:14:16 PM org.hibernate.cfg.Configuration getConfigurationInputStream INFO: HHH000040: Configuration resource: hibernate.cfg.xml Jan 08, 2014 8:14:16 PM org.hibernate.cfg.Configuration doConfigure INFO: HHH000041: Configured SessionFactory: null Jan 08, 2014 8:14:16 PM com.theitroad.servlet.hibernate.listener.HibernateSessionFactoryListener contextInitialized INFO: Hibernate Configuration created successfully Jan 08, 2014 8:14:16 PM com.theitroad.servlet.hibernate.listener.HibernateSessionFactoryListener contextInitialized INFO: ServiceRegistry created successfully Jan 08, 2014 8:14:16 PM org.hibernate.dialect.Dialect <init> INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQLDialect Jan 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 Jan 08, 2014 8:14:17 PM org.hibernate.engine.transaction.internal.TransactionFactoryInitiator initiateService INFO: HHH000399: Using default transaction strategy (direct JDBC transactions) Jan 08, 2014 8:14:17 PM org.hibernate.hql.internal.ast.ASTQueryTranslatorFactory <init> INFO: HHH000397: Using ASTQueryTranslatorFactory Jan 08, 2014 8:14:17 PM com.theitroad.servlet.hibernate.listener.HibernateSessionFactoryListener contextInitialized INFO: SessionFactory created successfully Jan 08, 2014 8:14:17 PM com.theitroad.servlet.hibernate.listener.HibernateSessionFactoryListener contextInitialized INFO: Hibernate SessionFactory Configured successfully Jan 08, 2014 8:14:32 PM com.theitroad.servlet.hibernate.GetEmployeeByID doGet INFO: Request Param empId=3 Jan 08, 2014 8:15:22 PM com.theitroad.servlet.hibernate.GetEmployeeByID doGet INFO: Request Param empId=3
如果您将取消部署应用程序或者停止服务器,则将看到用于销毁SessionFactory的服务器日志。
Jan 08, 2014 11:31:16 PM com.theitroad.servlet.hibernate.listener.HibernateSessionFactoryListener contextDestroyed INFO: Closing sessionFactory Jan 08, 2014 11:31:16 PM com.theitroad.servlet.hibernate.listener.HibernateSessionFactoryListener contextDestroyed INFO: Released Hibernate sessionFactory resource
以上就是关于tomcat容器的Hibernate DataSource示例,我希望它易于理解和实现。