Primefaces Spring和Hibernate集成示例教程
欢迎使用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>