zoukankan      html  css  js  c++  java
  • Spring(五):Spring&Struts2&Hibernate整合后,实现查询Employee信息

    • 背景:

      基于之前两篇文章《Spring(三):Spring整合Hibernate》、《Spring(四):Spring整合Hibernate,之后整合Struts2》,了解了如何整合SSH的过程,但还不知道整合后在项目中该怎么开发使用,本文主要讲解的是基于SSH实现Employee信息查询功能的使用。

    • 新建Employee,Department实体类,并添加对应类的hibernate实体配置文件

      新建包com.dx.ssh.entities,在该包下创建Employee、Department实体类,并添加对应的hibernate实体配置文件Employee.hbm.xml、Department.hbm.xml

    Employee.java

     1 package com.dx.ssh.entities;
     2 
     3 public class Department {
     4     private Integer id;
     5     private String deparmentName;
     6 
     7     public Integer getId() {
     8         return id;
     9     }
    10 
    11     public void setId(Integer id) {
    12         this.id = id;
    13     }
    14 
    15     public String getDeparmentName() {
    16         return deparmentName;
    17     }
    18 
    19     public void setDeparmentName(String deparmentName) {
    20         this.deparmentName = deparmentName;
    21     }
    22 }
    View Code

    Employee.hbm.xml

     1 <?xml version="1.0"?>
     2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
     3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
     4 <!-- Generated 2017-5-9 16:33:32 by Hibernate Tools 3.5.0.Final -->
     5 <hibernate-mapping>
     6     <class name="com.dx.ssh.entities.Department" table="SSH_DEPARTMENT">
     7         <id name="id" type="java.lang.Integer">
     8             <column name="ID" />
     9             <generator class="native" />
    10         </id>
    11         <property name="deparmentName" type="java.lang.String">
    12             <column name="DEPARMENTNAME" />
    13         </property>
    14     </class>
    15 </hibernate-mapping>
    View Code

    Department.java

     1 package com.dx.ssh.entities;
     2 
     3 import java.util.Date;
     4 
     5 public class Employee {
     6     private Integer id;
     7     private String lastName;
     8     private String email;
     9     private Date birth;
    10     // 不能被修改
    11     private Date createTime;
    12     // n:1的关系
    13     private Department department;
    14 
    15     public Integer getId() {
    16         return id;
    17     }
    18 
    19     public void setId(Integer id) {
    20         this.id = id;
    21     }
    22 
    23     public String getLastName() {
    24         return lastName;
    25     }
    26 
    27     public void setLastName(String lastName) {
    28         this.lastName = lastName;
    29     }
    30 
    31     public String getEmail() {
    32         return email;
    33     }
    34 
    35     public void setEmail(String email) {
    36         this.email = email;
    37     }
    38 
    39     public Date getBirth() {
    40         return birth;
    41     }
    42 
    43     public void setBirth(Date birth) {
    44         this.birth = birth;
    45     }
    46 
    47     public Date getCreateTime() {
    48         return createTime;
    49     }
    50 
    51     public void setCreateTime(Date createTime) {
    52         this.createTime = createTime;
    53     }
    54 
    55     public Department getDepartment() {
    56         return department;
    57     }
    58 
    59     public void setDepartment(Department department) {
    60         this.department = department;
    61     }
    62 }
    View Code

    Department.hbm.xml

     1 <?xml version="1.0"?>
     2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
     3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
     4 <!-- Generated 2017-5-9 16:33:32 by Hibernate Tools 3.5.0.Final -->
     5 <hibernate-mapping>
     6     <class name="com.dx.ssh.entities.Employee" table="SSH_EMPLOYEE">
     7         <id name="id" type="java.lang.Integer">
     8             <column name="ID" />
     9             <generator class="native" />
    10         </id>
    11         <property name="lastName" type="java.lang.String">
    12             <column name="LASTNAME" />
    13         </property>
    14         <property name="email" type="java.lang.String">
    15             <column name="EMAIL" />
    16         </property>
    17         <property name="birth" type="java.util.Date">
    18             <column name="BIRTH" />
    19         </property>
    20         <property name="createTime" type="java.util.Date">
    21             <column name="CREATETIME" />
    22         </property>
    23         <!-- 单项N:1关联关系 -->
    24         <many-to-one name="department" class="com.dx.ssh.entities.Department">
    25             <column name="DEPARTMENT_ID" />
    26         </many-to-one>
    27     </class>
    28 </hibernate-mapping>
    View Code
    • 添加Dao、Service、Action,并配置相关配置文件

    添加包com.dx.ssh.dao,并新建EmployeeDao.java

    package com.dx.ssh.dao;
    
    import java.util.List;
    
    import org.hibernate.Session;
    import org.hibernate.SessionFactory;
    
    import com.dx.ssh.entities.Employee;
    
    public class EmployeeDao {
        private SessionFactory sessionFactory;
    
        public void setSessionFactory(SessionFactory sessionFactory) {
            this.sessionFactory = sessionFactory;
        }
    
        private Session getSession() {
            return this.sessionFactory.getCurrentSession();
        }
    
        public List<Employee> getAll() {
            String hql = "From Employee e LEFT OUTER JOIN FETCH e.department";
            return getSession().createQuery(hql).list();
        }
    }

    在com.dx.ssh.service包下,新建EmployeeService.java

    package com.dx.ssh.service;
    
    import java.util.List;
    
    import com.dx.ssh.dao.EmployeeDao;
    import com.dx.ssh.entities.Employee;
    
    public class EmployeeService {
        private EmployeeDao employeeDao;
    
        public void setEmployeeDao(EmployeeDao employeeDao) {
            this.employeeDao = employeeDao;
        }
    
        public List<Employee> getAll() {
            List<Employee> items = employeeDao.getAll();
    
            return items;
        }
    }

    在com.dx.ssh.actions下,新建Action类EmployeeAction.java

    package com.dx.ssh.service;
    
    import java.util.List;
    
    import com.dx.ssh.dao.EmployeeDao;
    import com.dx.ssh.entities.Employee;
    
    public class EmployeeService {
        private EmployeeDao employeeDao;
    
        public void setEmployeeDao(EmployeeDao employeeDao) {
            this.employeeDao = employeeDao;
        }
    
        public List<Employee> getAll() {
            List<Employee> items = employeeDao.getAll();
    
            return items;
        }
    }

    配置applicationContext-beans.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
        <bean id="employeeDao" class="com.dx.ssh.dao.EmployeeDao">
            <property name="sessionFactory" ref="sessionFactory"></property>
        </bean>
    
        <bean id="employeeService" class="com.dx.ssh.service.EmployeeService">
            <property name="employeeDao" ref="employeeDao"></property>
        </bean>
    
        <bean id="employeeAction" class="com.dx.ssh.actions.EmployeeAction" scope="prototype">
            <property name="employeeService" ref="employeeService"></property>
        </bean>
    </beans>

    配置struts.xml

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
        "http://struts.apache.org/dtds/struts-2.3.dtd">
    <struts>
        <constant name="struts.enable.DynamicMethodInvocation" value="false" />
        <constant name="struts.devMode" value="true" />
    
        <package name="default" namespace="/" extends="struts-default">
            <action name="emp-*" class="employeeAction" method="{1}">
                <result name="list">/WEB-INF/views/emp-list.jsp</result>
            </action>
        </package>
    </struts>

    applicationContext.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
        xmlns:tx="http://www.springframework.org/schema/tx"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
    
        <!-- 加载配置文件 -->
        <context:property-placeholder location="classpath:jdbc.properties" file-encoding="utf-8" ignore-unresolvable="true" />
    
        <!-- 配置数据源 -->
        <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
            <property name="driverClass" value="${jdbc.driverClassName}"></property>
            <property name="jdbcUrl" value="${jdbc.url}"></property>
            <property name="user" value="${jdbc.username}"></property>
            <property name="password" value="${jdbc.password}"></property>
            <property name="testConnectionOnCheckout" value="${jdbc.c3p0.testConnectionOnCheckout}"></property>
            <property name="testConnectionOnCheckin" value="${jdbc.c3p0.testConnectionOnCheckin}"></property>
            <property name="idleConnectionTestPeriod" value="${jdbc.c3p0.idleConnectionTestPeriod}"></property>
            <property name="initialPoolSize" value="${jdbc.c3p0.initialPoolSize}"></property>
            <property name="minPoolSize" value="${jdbc.c3p0.minPoolSize}"></property>
            <property name="maxPoolSize" value="${jdbc.c3p0.maxPoolSize}"></property>
            <property name="maxIdleTime" value="${jdbc.c3p0.maxIdleTime}"></property>
        </bean>
    
        <bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
            <!-- 数据源dataSource -->
            <property name="dataSource" ref="dataSource" />
    
            <!-- hibernate的配置方案一  -->
            <property name="configLocation" value="classpath:hibernate.cfg.xml"></property>
            <!-- hibernate的配置方案二  -->
            <!-- 
            <property name="hibernateProperties"> 
                <props> 
                    <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop> 
                    <prop key="hibernate.dialect">${hibernate.dialect}</prop> 
                    <prop key="hibernate.show_sql">${hibernate.show_sql}</prop> 
                    <prop key="hibernate.format_sql">${hibernate.format_sql}</prop> 
                    <prop key="hibernate.temp.use_jdbc_metadata_defaults">false</prop> 
                </props> 
            </property>
             -->
    
            <!-- 持久化类的位置方案一,通过包进行扫描 -->
            <property name="mappingLocations" value="classpath:com/dx/ssh/entities/*.hbm.xml"></property>
            <!-- spring的spring.jar的jar包内,在org.springframework.orm.hibernate3.annotation下, 
                有一个AnnotationSessionFactoryBean类,其中有一个属性叫做"packagesToScan", 有个方法叫setpackagesToScan(),
            也就是说我可以再spring里面将这个属性给设定上。 
                packagesToScan是"包扫描"的意思,哪些包spring可以给我们扫描一下,看看有哪些实体类,
            这一项在我们在配置文件中配置hibernate的实体类的时候可以这么配,只要给出具体的扫描范围就可以了, 
            不需要将实体类一个一个的写出来 
            -->
            <!-- 持久化类的位置方案二,通过包进行扫描 -->
            <!-- 
            <property name="packagesToScan"> 
                <list> 
                    <value>com.dx.ssh.entities</value> 
                </list> 
            </property> 
            -->
            <!-- 持久化类的位置方案三,通过类进行扫描 -->
            <!-- 
            <property name="annotatedClasses"> 
                <list> 
                    <value>com.dx.ssh.entities.Member</value> 
                    <value>com.dx.ssh.entities.Log</value> 
                </list> 
            </property> 
            -->
        </bean>
        <!-- 配置Hibernate事务管理器 -->
        <bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
            <property name="sessionFactory" ref="sessionFactory" />
        </bean>
    
        <!-- 配置事务异常封装
        <bean id="persistenceExceptionTranslationPostProcessor" class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
         -->
        <!-- 基于数据源的事务管理器 -->
        <!-- 
        <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource"></property>
        </bean> 
         -->
        <!-- 启用注解来管理事务 -->  
        
        <!-- 配合<tx:advice>和<aop:advisor>完成了事务切面的定义 -->
        <!-- 使用强大的切点表达式是语言轻松定义目标方法 -->
        <aop:config proxy-target-class="true">
            <!-- 通过aop定义事务增强切面 -->
            <aop:pointcut expression=" execution(* com.dx.ssh.service..*(..))" id="serviceMethod" />
            <!-- 引用事务增强 -->
            <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethod" />
        </aop:config>
        <!-- 事务增强 -->
        <tx:advice id="txAdvice" transaction-manager="transactionManager">
            <!-- 事务属性定义 -->
            <tx:attributes>
                <tx:method name="*" />
            </tx:attributes>
        </tx:advice>
        
        <!-- 第一种方式: 注解方式配置事物 
        <tx:annotation-driven transaction-manager="transactionManager" />
        -->
    </beans>
    View Code

    hibernate.cfg.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE hibernate-configuration PUBLIC
            "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
            "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
    <hibernate-configuration>
        <session-factory>
            <!--
            把一下配置信息转移到jdbc.properties中。
            <property name="hibernate.connection.username">root</property>
            <property name="hibernate.connection.password">123456</property>
            <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
            <property name="hibernate.connection.url">jdbc:mysql://localhost/my_ssh</property>
            -->
    
            <property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
            <property name="hibernate.show_sql">true</property>
            <property name="hibernate.format_sql">true</property>
            <property name="hibernate.hbm2ddl.auto">update</property>
            <!-- <property name="hibernate.current_session_context_class">thread</property> -->
        </session-factory>
    </hibernate-configuration>
    View Code

    jdbc.properties

    #-----------------------------------------------------
    # u6570u636Eu5E93u914Du7F6E
    #-----------------------------------------------------
    #u670Du52A1u5668u5730u5740
    host=127.0.0.1
    dbName=my_ssh
    jdbc.driverClassName=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql://${host}:3306/${dbName}
    jdbc.username=root
    jdbc.password=123456
    
    #-----------------------------------------------------
    # u9002u7528u4E8Ec3p0u7684u914Du7F6E
    #-----------------------------------------------------
    #-----------------------------------------------------
    # c3p0u53CDu7A7Au95F2u8BBEu7F6EuFF0Cu9632u6B628u5C0Fu65F6u5931u6548u95EEu989828800
    #-----------------------------------------------------
    #idleConnectionTestPeriodu8981u5C0Fu4E8EMySQLu7684wait_timeout
    jdbc.c3p0.testConnectionOnCheckout=false
    jdbc.c3p0.testConnectionOnCheckin=true
    jdbc.c3p0.idleConnectionTestPeriod=3600
    #-----------------------------------------------------
    # c3p0u8FDEu63A5u6C60u914Du7F6E
    #-----------------------------------------------------
    #initialPoolSize, minPoolSize, maxPoolSize define the number of Connections that will be pooled.
    #Please ensure that minPoolSize <= maxPoolSize.
    #Unreasonable values of initialPoolSize will be ignored, and minPoolSize will be used instead.
    jdbc.c3p0.initialPoolSize=10
    jdbc.c3p0.minPoolSize=10
    jdbc.c3p0.maxPoolSize=100
    #maxIdleTime defines how many seconds a Connection should be permitted to go unused before being culled from the pool.
    jdbc.c3p0.maxIdleTime=3600
    #-----------------------------------------------------
    # hibernateu8FDEu63A5u6C60u914Du7F6E
    #-----------------------------------------------------
    hibernate.connection.driverClass=com.mysql.jdbc.Driver
    hibernate.connection.url=jdbc:mysql://${host}:3306/${dbName}
    hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
    hibernate.show_sql=true
    hibernate.format_sql=true
    hibernate.hbm2ddl.auto=update
    View Code

    在WebContent下创建index.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
    <a href="emp-list">Employee List</a>
    </body>
    </html>
    View Code

    在WEB-INF下创建views文件夹,在views下创建emp-list.jsp页面

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <%@taglib prefix="s" uri="/struts-tags"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
        <s:if test="#request.employees==null || #request.employees.size()==0">
            暂无记录!
        </s:if>
        <s:else>
            <table border="1" cellpadding="10" cellspacing="0">
                <tr>
                    <td>ID</td>
                    <td>LastName</td>
                    <td>Email</td>
                    <td>BirthDay</td>
                    <td>CreateTime</td>
                    <td>Department Name</td>
                <tr>
                    <s:iterator value="#request.employees">
                        <tr>
                            <td>${id }</td>
                            <td>${lastName }</td>
                            <td>${email }</td>
                            <td>${birth }</td>
                            <td>${createTime }</td>
                            <td>${department.deparmentName }</td>
                        <tr>
                    </s:iterator>
            </table>
        </s:else>
    </body>
    </html>
    View Code

    web.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID"
        version="3.0">
        <display-name>My-SSH</display-name>
    
        <welcome-file-list>
            <welcome-file>index.jsp</welcome-file>
            <welcome-file>index</welcome-file>
        </welcome-file-list>
    
          <!-- 配置启动IOC容器的Listener -->
        <!-- needed for ContextLoaderListener -->
        <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:applicationContext*.xml</param-value>
        </context-param>
    
        <!-- Bootstraps the root web application context before servlet initialization -->
        <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>
        
        <!-- Struts2 filter -->
        <filter>
            <filter-name>struts2</filter-name>
            <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
        </filter>
    
        <filter-mapping>
            <filter-name>struts2</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
    
    </web-app>

    项目结构如下:

    • 测试结果:

    • 常见抛出异常情况:

    1、nested exception is java.lang.NoClassDefFoundError: org/aspectj/weaver/reflect/ReflectionWorld$ReflectionWorldException

    错误原因:缺少aspectjweaver-1.8.9.jar包导致的错误。

    从地址http://repo1.maven.org/maven2/org/aspectj/aspectjweaver/,下载包aspectjweaver-1.8.9.jar。

    2、Action class [userAction] not found - action

    在做一个 ssh三个框架集成的时候,经常遇到上诉问题。如果已经正确定义了action,仍报错,其实是缺少包struts2-sping-plugin 2.0.1.jar

     解决方案一: 

    上诉问题说的 在struts.xml 没用找到 sping配置文件里的一个bean啊;也就是说:struts.xml 这个文件没有和sping配置文件关联起来;

    在此 另一种解决方案是 在 lib 目录下加入一个jar包struts2-sping-plugin 2.0.1.jar问题就解决了.

    解决方案二:

    在struts.xml中还要加入这么一个bean 

    <bean type="com.opensymphony.xwork2.ObjectFactory" name="spring
             class="org.apache.struts2.spring.StrutsSpringObjectFactory" />

    这个bean要放在package的外面

    3、Struts Problem Report

    Struts has detected an unhandled exception:

    Messages:
    • createQuery is not valid without active transaction
    File: org/hibernate/context/internal/ThreadLocalSessionContext.java
    Line number: 351

    解决方案:

    包hibernate.cfg.xml中的配置项注意掉:

    <!-- <property name="hibernate.current_session_context_class">thread</property> -->

    4、hibernate中采用了lazy加载,在查询hql=“From Employee e”,执行过程中dao被service调用,当action调用employeeService结束后,就立即关闭了session,导致页面没有版本加载数据导致的错误。

     Struts Problem Report

    Struts has detected an unhandled exception:

    Messages:
    1. could not initialize proxy - no Session
    2. Error reading 'deparmentName' on type com.dx.ssh.entities.Department_$$_jvst9ef_0
    3. javax.el.ELException: Error reading 'deparmentName' on type com.dx.ssh.entities.Department_$$_jvst9ef_0
    File: org/hibernate/proxy/AbstractLazyInitializer.java
    Line number: 146

    解决该错误有三种解决方案:

    解决方案一:修改Employee.hbm.xml man-to-one节点添加上属性 lazy="false",比较笨的方法。因为这是在用效率作为代价。

            <!-- 单项N:1关联关系 -->
            <many-to-one name="department" class="com.dx.ssh.entities.Department" lazy="false">
                <column name="DEPARTMENT_ID" />
            </many-to-one>

    解决方案二:使用OpenSessionInViewFilter。这种方法是将session交给servlet filter来管理,每当一个请求来之后就会开

    启一个session,只有当响应结束后才会关闭。如下:

    <filter-name>hibernateFilter</filter-name>   
         <filter-class>  org.springframework.orm.hibernate3.support.OpenSessionInViewFilter </filter-class>   
    </filter   
    <filter-mapping>   
         <filter-name>hibernateFilter</filter-name>   
         <url-pattern>/*</url-pattern>   
    </filter-mapping>   

    解决方案三:修改hql

        public List<Employee> getAll() {
            String hql = "From Employee e LEFT OUTER JOIN FETCH e.department";
            return getSession().createQuery(hql).list();
        }

    My-SSH项目源代码下载地址:http://pan.baidu.com/s/1o87Ezge

  • 相关阅读:
    MoSQL
    Open Search Server 1.4 Beta3 发布
    NxWidgets 1.5 发布,NuttX的GUI开发包
    segatex 7.900 发布,SELinux 策略编辑器
    MySQL Connector/ODBC 5.2.4 发布
    Phing 2.5 发布,PHP 项目构建工具
    SwingX 1.6.5 发布,GUI 工具包
    XWiki 4.4.1 发布,Java 的 Wiki 引擎
    流言终结者——C语言内存管理
    Hudson 3.0 正式版发布,持续集成引擎
  • 原文地址:https://www.cnblogs.com/yy3b2007com/p/6831902.html
Copyright © 2011-2022 走看看