Primefaces Spring和Hibernate集成示例教程

时间:2020-02-23 14:41:40  来源:igfitidea点击:

欢迎使用Spring Primefaces和Hibernate集成示例。
框架之间的集成是一项复杂的任务,并且通常需要很多时间才能实现。
我们已经在单独的教程中讨论了Primeme,Spring和Hibernate框架,但是这次我们将向您展示如何集成所有框架以创建分层(分层)应用程序。

SpringPrimefaces休眠

分层(分层)应用程序是一种流行的设计,大多数企业应用程序都与该设计保持一致。
其中:

  • Primefaces框架将用于处理所有UI问题并验证客户的输入。

  • Hibernate框架将用于传达您自己的持久性存储,该存储可能是MySQL数据库。

  • Spring框架将用于在所有这些框架之间粘合。

本教程旨在使用所有列出的框架来实现分层的应用程序。

Spring Primefaces Hibernate所需工具

在开始深入研究之前,让我们看一下所需的必需工具:

  • Eclipse开普勒4.3。

  • 休眠3.x。

  • Spring4.x.

  • Primefaces5.x。

  • JDK 1.6以上版本。

  • MySQL5.x。

Primefaces Spring Hibernate项目结构

我们的最终项目结构将如下图所示,我们将逐一介绍每个组件。

创建数据库员工表

MySQL数据库将用于保留所有员工实例/记录。
已用员工表如下所示:

另外,在其SQL创建脚本下方找到:

CREATE TABLE `employee` (
`EMP_ID` int(11) NOT NULL AUTO_INCREMENT,
`EMP_NAME` varchar(45) DEFAULT NULL,
`EMP_HIRE_DATE` datetime DEFAULT NULL,
`EMP_SALARY` decimal(11,4) DEFAULT NULL,
PRIMARY KEY (`EMP_ID`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

创建员工模型Bean

创建Employee表后,现在是时候看看Employee类的样子了:

package com.theitroad.hibernate.data;

import java.util.Date;

public class Employee {
	private long employeeId;
	private String employeeName;
	private Date employeeHireDate;
	private double employeeSalary;

	public long getEmployeeId() {
		return employeeId;
	}

	public void setEmployeeId(long employeeId) {
		this.employeeId = employeeId;
	}

	public String getEmployeeName() {
		return employeeName;
	}

	public void setEmployeeName(String employeeName) {
		this.employeeName = employeeName;
	}

	public Date getEmployeeHireDate() {
		return employeeHireDate;
	}

	public void setEmployeeHireDate(Date employeeHireDate) {
		this.employeeHireDate = employeeHireDate;
	}

	public double getEmployeeSalary() {
		return employeeSalary;
	}

	public void setEmployeeSalary(double employeeSalary) {
		this.employeeSalary = employeeSalary;
	}
}

Spring Primefaces休眠Maven依赖关系

Maven是一个构建工具,主要用于管理项目依赖项。
因此,无需像通常那样下载JAR并将其附加到项目中。
MySQL JDBC驱动程序,休眠核心,Spring核心框架,Primefaces以及我们进行Spring Hibernate Primefaces集成所需的许多库。
我们最终的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/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.theitroad</groupId>
	<artifactId>Primefaces-Hibernate-Spring-Integration-Sample</artifactId>
	<packaging>war</packaging>
	<version>0.0.1-SNAPSHOT</version>
	<name>Primefaces-Hibernate-Spring-Integration-Sample Maven Webapp</name>
	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<configuration>
					<source>1.6</source>
					<target>1.6</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
	<url>https://maven.apache.org</url>
	<repositories>
		<repository>
			<id>prime-repo</id>
			<name>PrimeFaces Maven Repository</name>
			<url>https://repository.primefaces.org</url>
			<layout>default</layout>
		</repository>
	</repositories>
	<dependencies>
		<!-- Servlet -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>servlet-api</artifactId>
			<version>2.5</version>
			<scope>provided</scope>
		</dependency>
		<!-- Faces Implementation -->
		<dependency>
			<groupId>com.sun.faces</groupId>
			<artifactId>jsf-impl</artifactId>
			<version>2.2.4</version>
		</dependency>
		<!-- Faces Library -->
		<dependency>
			<groupId>com.sun.faces</groupId>
			<artifactId>jsf-api</artifactId>
			<version>2.2.4</version>
		</dependency>
		<!-- Primefaces Version 5 -->
		<dependency>
			<groupId>org.primefaces</groupId>
			<artifactId>primefaces</artifactId>
			<version>5.0</version>
		</dependency>
		<!-- JSP Library -->
		<dependency>
			<groupId>javax.servlet.jsp</groupId>
			<artifactId>javax.servlet.jsp-api</artifactId>
			<version>2.3.1</version>
		</dependency>
		<!-- JSTL Library -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
			<version>1.1.2</version>
		</dependency>
		<!-- Primefaces Theme Library -->
		<dependency>
			<groupId>org.primefaces.themes</groupId>
			<artifactId>blitzer</artifactId>
			<version>1.0.10</version>
		</dependency>
		<!-- Hibernate library -->
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-core</artifactId>
			<version>3.6.10.Final</version>
		</dependency>
		<!-- MySQL driver connector library -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.31</version>
		</dependency>
		<!-- Spring ORM -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-orm</artifactId>
			<version>4.0.3.RELEASE</version>
		</dependency>
		<!-- Spring Web -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>4.0.3.RELEASE</version>
		</dependency>
		<!-- Required By Hibernate -->
		<dependency>
			<groupId>commons-dbcp</groupId>
			<artifactId>commons-dbcp</artifactId>
			<version>1.4</version>
		</dependency>
		<dependency>
			<groupId>javassist</groupId>
			<artifactId>javassist</artifactId>
			<version>3.12.1.GA</version>
		</dependency>
	</dependencies>
</project>

Spring Primefaces –休眠配置

Hibernate是一种标准的对象关系映射(ORM)解决方案,用于将您的对象域映射到关系表格公式中。
休眠配置过程需要执行以下步骤:

  • 主要在hibernate配置文件中指定所有相关的数据库信息,例如驱动程序,JDBC URL,hibernate方言和hibernate会话上下文,主要使用hibernate.cfg.xml。
    休眠实现本身将使用方言来确保映射过程的执行有效完成。
    该文件应位于项目的src/main/resources文件夹下。

  • 指定休眠的映射文件。
    映射文件将包含所有映射信息,例如对象表,属性列和关联关系,domain-classes.hbm.xml文件主要用于此目的。
    该文件应位于项目的src/main/resources文件夹下,以便位于应用程序的类路径中。

  • 重要的是要说,当我们要使用Spring时,需要进行一些修改。

hibernate.cfg.xml

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
      "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
      "https://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>

  <session-factory>

      <!-- Database connection settings -->
      <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
      <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/theitroad</property>
      <property name="hibernate.connection.username">root</property>
      <property name="hibernate.connection.password">root</property>

      <!-- SQL dialect -->
      <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
      <!-- Specify session context -->
      <property name="hibernate.current_session_context_class">org.hibernate.context.internal.ThreadLocalSessionContext</property>
      <!-- Show SQL -->
      <property name="hibernate.show_sql">true</property>
      <!-- Referring Mapping File -->
      <mapping resource="domain-classes.hbm.xml"
  </session-factory>

</hibernate-configuration>

domain-classes.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping
PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
"https://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
	<class name="com.theitroad.hibernate.data.Employee" table="employee">
		<id name="employeeId" column="EMP_ID" type="long">
			<generator class="native" 
		</id>
		<property name="employeeName" column="EMP_NAME" type="string"
		<property name="employeeHireDate" column="EMP_HIRE_DATE" type="date"
		<property name="employeeSalary" column="EMP_SALARY" type="double"
	</class>
</hibernate-mapping>

测试我们的Hibernate应用程序

到目前为止,我们已经创建了一个配置有必需依赖项的Eclipse Web项目,创建了数据库Employee Table,并创建了休眠框架。

在进一步进行Spring集成和开发Primefaces UI表单之前,让我们看看如何使用简单的Java应用程序将Employee实例保存到我们自己的数据库中。
有了Java应用程序,它将帮助我们确定我们将获得的好处,特别是稍后使用Spring框架时。

package com.theitroad;

import java.util.Date;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import com.theitroad.hibernate.data.Employee;

public class Main {
	public static void main(String [] args){
		//Create a configuration instance
		Configuration configuration = new Configuration();
		//Provide configuration file
		configuration.configure("hibernate.cfg.xml");
		//Build a SessionFactory
		SessionFactory factory = configuration.buildSessionFactory(new StandardServiceRegistryBuilder().configure().build());
		//Get current session, current session is already associated with Thread
		Session session = factory.getCurrentSession();
		//Begin transaction, if you would like save your instances, your calling of save must be associated with a transaction
		session.getTransaction().begin();
		//Create employee
		Employee emp = new Employee();
		emp.setEmployeeName("Peter Jousha");
		emp.setEmployeeSalary(2000);
		emp.setEmployeeHireDate(new Date());
		//Save
		session.save(emp);
		//Commit, calling of commit will cause save an instance of employee
		session.getTransaction().commit();
	}
}

以下是上述代码的详细说明:

  • Hibernate需要定义的上下文,以使您获得的会话受到影响。
    通过提供hibernate的属性hibernate.current_session_context_class可以实现标准Java应用程序上下文。
    org.hibernate.context.internal.ThreadLocalSessionContext的值将把上下文绑定到当前执行的线程。
    这意味着,如果您对活动事务中的会话对象调用了任何类型的CRUD操作,则一旦事务提交,它们将在您自己的数据库中执行。
    在我们的例子中,新的员工实例已保存。
    如果您使用的是休眠3,则此属性应为thread,而不是ThreadLocalSessionContext。

  • Hibernate 4用于测试目的,此版本的hibernate在与Spring 4集成时不适用。
    要与Spring 4集成,您已请求使用Hibernate 3。

  • 使用最新版本的休眠状态要求您使用" StandardServiceRegistryBuilder"来构建SessionFactory。

设置弹簧

Spring是一个全面的框架,主要用于控制反转(IoC),它考虑了众所周知的概念Dependency Injection的更一般的类别。

但是,提供的简单Java应用程序使您能够将Employee实例保存到自己的数据库中,但是通常,这不是大多数应用程序用来配置其自己的休眠持久层的方式。

使用Spring将帮助您避免所有创建和关联对象的东西。
创建所需的对象,关联其他对象主要是Spring的工作。
接下来是Spring上下文配置文件,更新的休眠配置,更新的Maven pom.xml和我们的部署描述符文件。
让我们看看如何配置所有这些以正确使用Spring。

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="https://www.springframework.org/schema/beans"
	xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns:tx="https://www.springframework.org/schema/tx"
	xmlns:context="https://www.springframework.org/schema/context"
	xmlns:aop="https://www.springframework.org/schema/aop" xmlns:util="https://www.springframework.org/schema/util"
	xsi:schemaLocation="https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd https://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd https://www.springframework.org/schema/context  https://www.springframework.org/schema/context/spring-context-3.2.xsd https://www.springframework.org/schema/tx https://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
	<!-- Enable Spring Annotation Configuration -->
	<context:annotation-config 
	<!-- Scan for all of Spring components such as Spring Service -->
	<context:component-scan base-package="com.theitroad.spring.service"></context:component-scan>
	<!-- Create Data Source bean -->
	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
		destroy-method="close">
		<property name="driverClassName" value="com.mysql.jdbc.Driver" 
		<property name="url" value="jdbc:mysql://localhost:3306/theitroad" 
		<property name="username" value="root" 
		<property name="password" value="root" 
	</bean>
	<!-- Define SessionFactory bean -->
	<bean id="sessionFactory"
		class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
		<property name="dataSource" ref="dataSource" 
		<property name="mappingResources">
			<list>
				<value>domain-classes.hbm.xml</value>
			</list>
		</property>
		<property name="configLocation">
          <value>classpath:hibernate.cfg.xml</value>
      </property>
	</bean>
	<!-- Transaction Manager -->
	<bean id="transactionManager"
		class="org.springframework.orm.hibernate3.HibernateTransactionManager">
		<property name="sessionFactory" ref="sessionFactory" 
	</bean>
	<!-- Detect @Transactional Annotation -->
	<tx:annotation-driven transaction-manager="transactionManager" 
</beans>

hibernate.cfg.xml

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
      "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
      "https://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
  <session-factory>
      <!-- SQL dialect -->
      <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
  </session-factory>
</hibernate-configuration>

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
	xmlns="https://java.sun.com/xml/ns/javaee" xmlns:web="https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	xsi:schemaLocation="https://java.sun.com/xml/ns/javaee
	https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	id="WebApp_ID" version="2.5" metadata-complete="true">
	<servlet>
		<servlet-name>Faces Servlet</servlet-name>
		<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>Faces Servlet</servlet-name>
		<url-pattern>/faces/*</url-pattern>
	</servlet-mapping>
	<servlet-mapping>
		<servlet-name>Faces Servlet</servlet-name>
		<url-pattern>*.xhtml</url-pattern>
	</servlet-mapping>
	<context-param>
		<description>State saving method: 'client' or 'server' (=default). See JSF Specification 2.5.2</description>
		<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
		<param-value>client</param-value>
	</context-param>
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
	<listener>
		<listener-class>com.sun.faces.config.ConfigureListener</listener-class>
	</listener>
</web-app>

以下是上面给出的代码的详细说明:

  • 我们通过实例化名为sessionFactory的Spring Bean创建了SessionFactory。
    实例化SessionFactory确实需要传递数据源实例的实例,传递映射文件(按原样提供domain-classes.hbm.xml),通过使用hibernate.cfg.xml传递所有必需的Hibernate属性。
    您已经注意到,hibernate.cfg.xml不包含数据库信息,因为它是立即定义的-Data Source Bean-不需要休眠会话上下文,因此可以通过Apache Tomcat进行丰富。
    甚至Apache Tomact都不是托管服务器,但它包含有助于创建上下文会话的功能。

  • 交易管理器将帮助您消除使用诸如session.getTransaction()。
    begin()和commit()之类的代码片段。
    @Transactional注释将替代使用。
    这就是说,任何以@Transactional注释的Spring Service方法的执行都将以跨国方式完成。
    如果您在诸如session.save()之类的跨国范围内针对会话调用了CRUD操作,它将在被调用方法结束时直接在您自己的数据库中执行。
    这就是所谓的交易分界。

  • 您可以使用@Component定义自己的Spring Services。
    那将被自动扫描。

  • 新的库已添加到我们的pom.xml maven依赖文件中,common-dbcp和javassist是hibernate 3所必需的。
    如果您已经注意到,Hibernate 4不需要这些库。

  • 必须为您的web.xml文件添加Spring上下文加载器监听器。
    该侦听器需要在WEB-INF /文件夹下定义一个applicationContext.xml。
    这是Spring配置上下文文件的默认位置和名称。
    如果您要更改其位置和名称,则必须在以下带有所需路径的代码段中添加。

配置非默认的Spring上下文位置:

<context-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>/WEB-INF/spring/SpringContext.xml</param-value>
  </context-param>

注意:如果您正在寻找Spring 4和Hibernate 4的集成,我们需要在Spring Bean配置文件中进行一些小的更改,您可以在Spring Hibernate Integration Example中获得有关此配置的更多信息。

Spring员工服务

在像我们在此所做的分层应用程序中,所有业务操作都必须通过服务来实现。
Spring提供了定义包含业务规则的服务的能力。
EmployeeService将包含创建Employee所需的业务。

package com.theitroad.spring.service;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.theitroad.hibernate.data.Employee;

@Component
public class EmployeeService {
	@Autowired
	private SessionFactory sessionFactory;

	public SessionFactory getSessionFactory() {
		return sessionFactory;
	}

	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}

	@Transactional
	public void register(Employee emp){
		//Acquire session
		Session session = sessionFactory.getCurrentSession();
		//Save employee, saving behavior get done in a transactional manner
		session.save(emp);
	}
}

以下是上述代码的详细说明:

  • EmployeeService是一个Spring服务,@ Component批注用于定义Spring Service。
    默认情况下,Spring将根据上下文:component-scan标签扫描您提到的软件包以找到您的服务。

  • @Autowired将帮助您注入所需的实例。
    那就是依赖注入或者IoC(控制反转)概念。
    这是一个重要的概念,它意味着不允许开发人员控制创建实例和进行所需关联的过程。
    它使所有这些创建和关联都在后面可见。
    这是Spring不可思议的力量。
    @Autowired用于注入SessionFactory的一个实例,如果您担心性能问题,可以将SessionFactory bean定义为单例作用域。
    有关自动装配的完整信息,请阅读Spring自动装配示例。

  • @Transactional批注用于事务划分目的。
    事务划分用于将上下文会话与活动事务相关联。
    这将导致针对您自己的数据库执行CRUD操作。
    您应该阅读Spring声明式事务管理示例。

Primefaces托管Bean – RegisterEmployee

Managed Bean是一种JSF功能,用于处理所有必需的用户界面验证。
在分层应用程序中,托管Bean用于调用业务服务。
当您知道将EmployeeService Spring bean注入自己的Managed Bean中时,您可能会想知道。
如果您使用@ManagedProperty批注,那将成为事实。

faces-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<faces-config xmlns="https://xmlns.jcp.org/xml/ns/javaee"
	xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="https://xmlns.jcp.org/xml/ns/javaee https://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd"
	version="2.2">
<application>
	<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
</application>
</faces-config>
package com.theitroad.prime.faces.beans;

import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;

import com.theitroad.hibernate.data.Employee;
import com.theitroad.spring.service.EmployeeService;

@ManagedBean
@SessionScoped
public class RegisterEmployee {

	@ManagedProperty("#{employeeService}")
	private EmployeeService employeeService;

	private Employee employee = new Employee();

	public EmployeeService getEmployeeService() {
		return employeeService;
	}

	public void setEmployeeService(EmployeeService employeeService) {
		this.employeeService = employeeService;
	}

	public Employee getEmployee() {
		return employee;
	}

	public void setEmployee(Employee employee) {
		this.employee = employee;
	}

	public String register() {
		//Calling Business Service
		employeeService.register(employee);
		//Add message
		FacesContext.getCurrentInstance().addMessage(null, 
				new FacesMessage("The Employee "+this.employee.getEmployeeName()+" Is Registered Successfully"));
		return "";
	}
}

以下是上述代码的详细说明:

  • RegisterEmployee托管Bean是使用@ManagedProperty批注开发的,它将帮助您获得Spring EmployeeService实例的注入。
    如果您未提供包含新添加的Spring el-resolver的特殊faces-config.xml文件,则该关联将不适用。

  • Primefaces UI表单将帮助您收集有关注册员工的所有必需信息。

  • 注册操作将要求EmployeeService保存给定的雇员实例。

Primefaces –注册表

index.xhtml

<html xmlns="https://www.w3.org/1999/xhtml"
	xmlns:ui="https://java.sun.com/jsf/facelets"
	xmlns:h="https://java.sun.com/jsf/html"
	xmlns:f="https://java.sun.com/jsf/core"
	xmlns:p="https://primefaces.org/ui">
<h:head>
	<script name="jquery/jquery.js" library="primefaces"></script>
	<title>Register Employee</title>
</h:head>
<h:form>
	<p:growl id="messages"></p:growl>
	<p:panelGrid columns="2">
		<p:outputLabel value="Enter Employee Name:"></p:outputLabel>
		<p:inputText value="#{registerEmployee.employee.employeeName}"></p:inputText>
		<p:outputLabel value="Enter Employee Hire Date:"></p:outputLabel>
		<p:calendar value="#{registerEmployee.employee.employeeHireDate}"></p:calendar>
		<p:outputLabel value="Enter Employee Salary:"></p:outputLabel>
		<p:inputText value="#{registerEmployee.employee.employeeSalary}"></p:inputText>						
	</p:panelGrid>
	<p:commandButton value="Register" action="#{registerEmployee.register}" update="messages"></p:commandButton>
</h:form>
</html>