SSH整合

SSH整合

1.整合思路

spring容器管理各层需要的对象

2.整合注意点

2.1.整合一个测试一个

2.2.使用框架,尽量复制

3.SSH整合的步骤

3.1.导入jar包

导入hibernate jar包

1)hibernate 框架必须的基础包

路径:E:…\SSH整合\SSH整合jar包\hibernate\hibernate-release-5.0.7.Final\lib\required

required文件夹下的所有jar包

2)补充:hibernate-entitymanager-5.0.7.Final.jar \jpa文件夹下

SUM公司推出的ORM规范 --全部都是借口。 属于数据持久化的规范技术

3)数据库驱动

注意:不管是hibernate 或者mybatis 都没有提供相应的数据库驱动;
需要连接MySQL,MySQL驱动;连接Oracle,Oracle驱动包。

导入struts2 jar包

1)struts2-blank 文件夹所有jar包

磁盘路径:E:…\SSH整合\SSH整合jar包\struts2\struts-2.3.24\apps\struts2-blank\WEB-INF\lib

特别提醒:copy时,去掉重复的jar包。 删除低版本 ,保留高版本。

2)整合Struts2 spring 的jar包

struts2-spring-plugin-2.3.24.jar

磁盘路径:E:\MyVideo\学习\IT互联网\JAVAEE\SSH体系\SSH整合\SSH整合jar包\struts2\struts-2.3.24\lib

特别提醒:如果没有配置spring ,单独启动struts2,就会去寻找spring容器,找不到就抛出异常。

导入spring jar包

1)4+2 基础包

4:spring-core ,spring-bean, spring-context, spring-express(spring的EL,表达式语言)

2:com.springsource.org.apache.commons.logging-1.1.1.jar
【路径:E:\MyVideo\学习\IT互联网\JAVAEE\SSH体系\SSH整合\SSH整合jar包\spring\spring-framework-3.0.2.RELEASE-dependencies\org.apache.commons\com.springsource.org.apache.commons.logging\1.1.1】

com.springsource.org.apache.log4j-1.2.15.jar
【路径:E:\MyVideo\学习\IT互联网\JAVAEE\SSH体系\SSH整合\SSH整合jar包\spring\spring-framework-3.0.2.RELEASE-dependencies\org.apache.log4j\com.springsource.org.apache.log4j\1.2.15】

【copy commons-logging-1.1.1.jar ,log4j-1.2.16.jar 】(最开始以为没有找的替代版本,后来网上下载到了)

  1. spring整合 web包

spring-web-5.1.12.RELEASE.jar

3)spring整合 AOP 4个包

官方两个包 spring-aop, spring-aspects

三方两个包 com.springsource.org.aopallience-1.0.0.jar , com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
【三方两包路径:E:\SSH体系\SSH整合\SSH整合jar包\spring\spring-framework-3.0.2.RELEASE-dependencies】

  1. 整合hibernate 和事务包

三个包:spring-jdbc-5.1.2.RELEASE.jar , spring-orm-5.1.2.RELEASE.jar , spring-tx-5.1.2.RELEASE.jar

5)c3p0连接池包

com.springsource.com.mchange.v2.c3p0-0.9.1.2.jar

  1. Junit4 测试包

spring-test-5.1.2.RELEASE.jar

  1. 标签库包

jstl.jar , standard.jar

总结:

搭架子的jar包总数 42个 – 需要实操,唯手熟尔。

3.2.单独配置spring框架

3.2.1.spring的配置文件

【戏称为 beans文件】可以通过模板生成

spring配置文件先不要做任何的配置,有抬头内容即可【一些约束文件及其实例】

<?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:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/tx
       http://www.springframework.org/schema/tx/spring-tx.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd
        ">
</beans>

3.2.2.web.xml配置spring容器

  <!-- 配置spring容器在项目启动的配置 -->
  <!-- 通过快捷键CTRL+shift+t 打开ContextLoaderListener 复制而来 -->
  <listener>
  	<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <context-param>
  	<param-name>contextConfigLocation</param-name>
  	<param-value>classpath:applicationContext.xml</param-value>
  </context-param>

3.2.3.启动tomcat

测试spring框架已经配置完成,没有报错,就可以了。

3.3单独配置struts2框架

3.3.1.创建XxAction

创建的XxAction 需要继承 ActionSupport 示例:

package com.zl.web;

import com.opensymphony.xwork2.ActionSupport;

public class SupplierAction extends ActionSupport {
	public String supplier() throws Exception {
		//first 重写execute方法 super.execute();
		System.out.println("SupplierAction对象创建成功");
		return SUCCESS;
	}

}

3.3.2.struts.xml

创建struts2的核心配置文件 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的dtd,不要记忆,靠复制 -->
<struts>
	<package name="zl" namespace="/" extends="struts-default">
		<action name="supplierAction" class="com.zl.web.SupplierAction"
			method="supplier">
			<result name="success">/supplier.jsp</result>
		</action>
	</package>
</struts>	

3.3.3.web.xml配置struts核心过滤器

3.3…4.启动tomcat测试

配置struts2的debug

代码没有问题,前端页面报找不到XxAction类的异常;

考虑编译环境的问题:

struts2 需要tomcat8.0以上,jdk8的环境。

3.4 spring-struts2整合

spring配置XxAction

将原来由Struts2负责创建的XxAction交给Spring容器。

<!-- 让struts2种的action交给spring容器来管理 -->
	<bean name="supplierAction" class="com.zl.web.SupplierAction">
		<property name="supplierService" ref="supplierService"></property>
	</bean>

修改struts.xml

<struts>
	<package name="zl" namespace="/" extends="struts-default">
        <!-- class类属性修改为spring里面的beanName,完成引用 -->
        <!-- class属性可以是创建实例的类,又或者是spring容器里面的beanName -->
		<action name="supplierAction" class="supplierAction"
			method="supplier">
			<result name="success">/supplier.jsp</result>
		</action>
	</package>
</struts>

3.4.3.启动tomcat

特别注意:

	struts2的设计理念是【多例】,spring默认【单例】,因此整合时需要更改<scope>为prototype

整合过程的debug:

解决:

先把Tomcat停掉 , 然后选Eclipse导航栏的Project > Clean , clean会删除项目WebRoot下的classes文件 , 然后自动重新编译再生成class文件。

最优解决:

先把Tomcat停掉 , 然后选Eclipse导航栏的 Project->Build Aotumatically ,打上勾可以了,完成自动重建。

3.5单配hibernate框架

1)导入jar包

相关jar包,第一步已做。

2)添加配置文件

hibernate核心配置文件

提供示例模板:hibernate.cfg.xml 只能叫这个名字,hibernate框架才会自动读取

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <!--数据库驱动-->
        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
        <!--连接数据库URL--><!--通过URL解决hibernate向MySQL插入中文乱码问题-->
        <property name="connection.url">
            <![CDATA[jdbc:mysql://192.168.200.150:3306/zl_orm?useUnicode=true&characterEncoding=utf8]]></property>
        <!--连接数据库的用户名-->
        <property name="connection.username">root</property>
        <!--数据库用户密码-->
        <property name="connection.password">root</property>
        <!--选择数据库使用的方言-->
        <!-- hibernate dialect org.hibernate.dialect.MySQLDialect 对应 MySQL5.0之前 -->
        <!--<property name="dialect">org.hibernate.dialect.MySQLDialect</property>-->
        <!-- dialect org.hibernate.dialect.MySQL5InnoDBDialect 对应MySQL5.0版本之后-->
        <property name="dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>

        <!-- 连接池的配置 -->
        <!--JDBC连接池最大连接数-->
        <property name="hibernate.c3p0.max_size">20</property>
        <!--JDBC连接池最小连接数-->
        <property name="hibernate.c3p0.min_size">1</property>
        <!--连接池连接的超时时间-->
        <property name="hibernate.c3p0.timeout">5000</property>
        <!--连接池最大缓存多少个statement对象-->
        <property name="hibernate.c3p0.max_statements">100</property>
        <!--每隔3000秒检查连接池里的空闲连接-->
        <property name="hibernate.c3p0.idle_test_period">3000</property>
        <!--连接池里面的连接用完的时候,指定c3p0可以获取2个新的连接数-->
        <property name="hibernate.c3p0.acquire_increment">2</property>
        <!--每次验证连接池的连接是否可用-->
        <property name="hibernate.c3p0.validate">true</property>
        <!--JDBC连接池(使用内置的连接池)-->
        <property name="connection.pool_size">1</property>

        <!--根据需要自动创建数据表--> <!--在启动时删除并重新创建数据库-->
        <property name="hbm2ddl.auto">update</property>
        <!--显示执行的SQL语句-->
        <property name="show_sql">true</property>
        <!--将sql脚本进行格式化后输出-->
        <property name="hibernate.format_sql">true</property>
        <!--设置Hibernate自动管理上下文的策略-->
        <!--<property name="current_session_context_class">thread</property>-->
        <!--下面罗列出持久化类的类名--><!--类的全限定名-->
        <mapping class="com.zl.hibernate.po.User"/>
    </session-factory>
</hibernate-configuration>
  1. pojo

    package com.zl.domain;

    import java.util.Date;

    public class User {

     private Integer id;
     private String username;
     private Date birthday; //java.util.Date;
     private String sex;
     private String address;
     
     public Integer getId() {
     	return id;
     }
     public void setId(Integer id) {
     	this.id = id;
     }
     public String getUsername() {
     	return username;
     }
     public void setUsername(String username) {
     	this.username = username;
     }
     
     public Date getBirthday() {
     	return birthday;
     }
     public void setBirthday(Date birthday) {
     	this.birthday = birthday;
     }
     public String getSex() {
     	return sex;
     }
     public void setSex(String sex) {
     	this.sex = sex;
     }
     public String getAddress() {
     	return address;
     }
     public void setAddress(String address) {
     	this.address = address;
     }
     @Override
     public String toString() {
     	return "User [id=" + id + ", username=" + username + ", date=" + birthday + ", sex=" + sex + ", address=" + address
     			+ "]";
     }
    

    }

细节

实体类的date,与数据库的date数据交互。

因为,数据库的date是“yyyy-MM-dd”的形式,因此实体类的date,也需要借助简单日期转换器转换为“yyyy-MM-dd”

	再hibernate的配置文件中五大参数可以省略前缀【hibernate】,但是如果是在spring文件中五大参数必须有【hibernate】;并且,spring文件中的hibernate配置,去五大参数的【key】应该是固定

示例:

//Java Date 对应jdbc的date类型  StringDate -> Date
		String pattern = "yyyy-MM-dd";
		String sDate = "1997-10-01";
		SimpleDateFormat sdf = new SimpleDateFormat(pattern);
		Date date = sdf.parse(sDate);

hibernate的debug

我最大的错误就是不去找错误日志;借助错误日志,完成排查,成功测试。

bug1:
	log4j缺少log4j2.xml配置文件,error报错	~~网上找个模板,解决

bug2:
	太自信了,不信息自己配置文件有错误,有了第一步,再加上调试,得到无效的hibernate配置文件
排查后得到是,注释时 【 --> 】不合法

bug3:
	类表之间的“数据交换”都是通过类属性的getter/setter方法完成,一定一定一定要确保 get/set后面跟属性名。

hibernate-orm映射文件

提供示例: 映射文件名【EntityName+hbm.xml】, 实体类名字+.hbm.xml

提醒:hibernate-orm映射文件最好与实体类放到一块【并非强制】

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!--
    Mapping file autogenerated by MyEclipse Persistence Tools
    hibernate的映射文件名称 命名规则为      “类名.hbm.xml”
-->
<hibernate-mapping>
        <!--实体类的类全名-->
        <class name="com.zl.hibernate.po.User">
                <!--属性/成员变量 与 表的主键映射-->
                <id name="id" column="id">
                        <generator class="increment"></generator>
                </id>
                <!--其他属性/成员变量 与 表的字段映射-->
                <property name="username" column="username" type="java.lang.String" length="20"></property>
                <property name="birthday" column="birthday" type="java.util.Date" length="20"></property>
                <property name="sex" column="sex" type="java.lang.String" length="20"></property>
                <property name="address" column="address" type="java.lang.String" length="20"></property>
        </class>
</hibernate-mapping>

3)测试hibernate框架

测试使用的表 user

测试使用的entity:

@Data
public class User {
    //成员变量

    private Integer id;
    private String username;
    private Date birthday;//java.util.Date;
    private String sex;
    private String address;
}

3.6 spring-hibernate整合

1)spring引入hibernate

spring的核心文件引入hibernate文件

<!-- sessionFactory交给spring容器管理 【事实上是其实现子类LocalSessionFactory交给spring容器】 -->
<!-- 
		整合hiberna框架,将LocalSessionFactoryBean交给spring容器管理
		sessionfactory 的实现子类 
-->
	<!-- 配置方式1 直接加载hibernate的配置文件 -->
	 <bean name="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
	 	<!-- 需要告诉LocalSessionFactoryBean 去哪里读取hibernate文件 ,靠下面的属性 -->
	 	<property name="configLocation" value="classpath:hibernate.cfg.xml"></property>
	 </bean>

	<!-- 配置方式2 hibernate文件的所有配置都写在spring的配置文件中 -->
<!-- 方法二,重点掌握 目标hibernate的所有配置都写进spring配置文件beans中 -->
	 <!-- 先来五个必选参数压压惊  -->
	 <!-- 接收复杂参数的固定形式,这里接受Map类型的多个 “key-value对” -->
	  
	 <bean name="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
	 	<property name="hibernateProperties">
	 		<!-- 5个必选参数 -->
	 		<!-- 2个可选参数 -->
	 		<props>
	 			<prop key="hibernate.connection.driver_class">com.mysql.jdbc.Driver</prop>
	 			<prop key="hibernate.connection.url"><![CDATA[jdbc:mysql://192.168.200.150:3306/zl_orm?useUnicode=true&characterEncoding=utf8]]></prop>
	 			<prop key="hibernate.connection.username">root</prop>
	 			<prop key="hibernate.connection.password">root</prop>
	 		
	 			<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
	 			<prop key="hibernate.show_sql">true</prop>
	 			<prop key="hibernate.format_sql">true</prop>
	 		</props>	 		
	 	</property>
	 	
	 	<!-- 让spring去哪里加载ORM映射文件 -->											 
	    <!-- 包扫描 ,可以读取到包下的所有配置文件-->
	 	<property name="mappingDirectoryLocations" value="classpath:com/zl/domain"></property>
	 </bean>

spring-hibernate整合debug

版本不一致:
	spring版本 与  hibernate版本不一致
	org.springframework.orm.hibernate5.LocalSessionFactoryBean 对应 hibernate5

配置文件错误:
	spring文件引入hibernate部分的 bean 属性配置错误;
	configLocation 误写为 [configLocations] 或者 不是LocalSessionFactoryBean的属性(就没有get/set方法);
	"classpath:hibernate.cfg.xml" 少写了 前面的[classpath:] ;
	错误提示信息:		
		Caused by: org.springframework.beans.NotWritablePropertyException: Invalid property 'configLoca' of bean class [org.springframework.orm.hibernate5.LocalSessionFactoryBean]: Bean property 'configLoca' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?
		明确告诉我们,configLoca这个属性在LocalSessionFactoryBean没有找到,就不能找到setter方法注入。
	
	方式二 包扫描【路径分隔符号】错误:
		com.zl.domain 
		<property name="mappingDirectoryLocations" value="classpath:com.zl.domain"></property>
	错误提示信息:
			Caused by: java.io.FileNotFoundException: class path resource [com.zl.domain] cannot be resolved to 
		com.zl.domain --->  改为:com/zl/domain 解决。

3.7 spring-其他

3.7.1.c3p0

1)数据源 bean 交付spring创建

数据源可以是c3p0 也可以是德鲁伊连接池。 此处选择c3p0

<!-- c3p0交付spring创建 -->
    <!-- 注意键是ComboPooledDataSource属性名字 -->
<!-- springDTDT约束文件规定 URL多参数之间需要使用【&amp;】分隔 -->
    <bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    	<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
    	<property name="jdbcUrl" value="jdbc:mysql://192.168.200.150:3306/zl_orm?useUnicode=true&amp;characterEncoding=utf8"></property>
    	<property name="user" value="root"></property>
    	<property name="password" value="root"></property>
    </bean>
  1. spring创建c3p0 debug

    配置文件xml:
    转义字符问题:
    提示信息:
    对实体 “characterEncoding” 的引用必须以 ‘;’ 分隔符结尾
    解决:URL拼接参数时,使用 【&】
    jdbc:mysql://192.168.200.150:3306/zl_orm?useUnicode=true;characterEncoding=utf8 替换为
    jdbc:mysql://192.168.200.150:3306/zl_orm?useUnicode=true&characterEncoding=utf8

  2. 创建c3p0优化

开发中,数据源一般有三个;线上,本地开发以及测试

属于变化比较频繁,因此可以将其提取到配置文件,后面要换数据源只需要修改配置文件。

创建 db.properties

driverClass=com.mysql.jdbc.DriverjdbcUrl=jdbc:mysql://192.168.200.150:3306/zl_orm?useUnicode=true&characterEncoding=utf8user=rootpassword=root

读取外部文件db,properties ,再使用spring的取值表达式,取值

<!-- 注意键是ComboPooledDataSource属性名字 -->
    <bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    	<property name="driverClass" value="${driverClass}"></property>
    	<property name="jdbcUrl" value="${jdbcUrl}"></property>
    	<property name="user" value="${user}"></property>
    	<property name="password" value="${password}"></property>
    </bean>
  1. c3p0优化bug

    优化时:遇到中文乱码的问题,有对编码设置 utf-8,未生效;
    查看,原来properties文件,&characterEncoding的引用,前面只需要加 【&】 。

3.7.2.事务

1)spring创建【事务】

<!-- 配置事务通知 -->
	 <tx:advice id="txadvice" transaction-manager="transactionManager">
	 	<tx:attributes>
	 		<tx:method name="find*" isolation="READ_COMMITTED" propagation="REQUIRED" read-only="true"/>
	 		<tx:method name="add*" isolation="READ_COMMITTED" propagation="REQUIRED" read-only="false"/>
	 	</tx:attributes>
	 </tx:advice>
	 <!-- 配置AOP织入 -->
	 <aop:config>
	 	<!-- 切点表达式 -->
	 	<aop:pointcut expression="execution(* com.zl.service.*Service.*(..))" id="pc"/>
	 	<aop:advisor advice-ref="txadvice" pointcut-ref="pc"/>
	 </aop:config>
  1. 创建事务过程 debug

    给service层创建事务,却忘记注入dao层到service层;
    报错提示信息:
    java.lang.NullPointerException
    at com.zl.service.UserService.addUser(UserService.java:48)
    调用addUser()方法时,报空指针,因为 真正执行的UserDao 没有注入到service,因此未默认值null;

超级坑点,再事务配置无误的情况下

报错提示信息:
	org.springframework.transaction.CannotCreateTransactionException: ![Could not open Hibernate Session for transaction; nested exception is java.lang.BootstrapMethodError:]! java.lang.NoClassDefFoundError: org/hibernate/engine/spi/SharedSessionContractImplementor
两种解决方案:
1)修改事务通知范围 propagation属性	[REQUIRED]
<tx:method name="find*" isolation="READ_COMMITTED" propagation="REQUIRED" read-only="true"/><tx:method name="add*" isolation="READ_COMMITTED" propagation="REQUIRED" read-only="false"/>	
更改为:	[SUPPORTS]
<tx:method name="find*" isolation="READ_COMMITTED" propagation="SUPPORTS" read-only="true"/>
<tx:method name="add*" isolation="READ_COMMITTED" propagation="SUPPORTS" read-only="false"/>
	
2) 更换spring的jar包  spring-aspects-5.1.2.RELEASE.jar
更换为: 4.2.4.RELEASE	说明开发还是以稳定为主,学习可以尝试新版。

4.SH结合操作数据库

SH指的是:spring整合hibernate之后,操作数据库

4.1核心类

使用的核心类是 hibernatetemplate 与 hibernateDaoSupport

两者的不同点:	hibernatetemplate需要在使用类,创建变量ht来注入;	hibernateDaoSupport则并不需要,只需要XXDao实用类继承。	举例子:		public class UserDao 【extends】 HibernateDaoSupport

-查询(查询返回当个对象,查询返回list)

-添加

4.2 XXdao由spring创建

如果我们采用XXDao 继承 HibernateDaoSupport的方式,就必须要在创建XXDao bean,给bean属性注入sessionfactory当然是 HibernateDaoSupport 需要依赖 sessionfactory 。通过子类继承的属性注入值,传递给父类。

<!-- 示例 -->
<!-- spring容器管理dao层 -->
	 <bean name="userDao" class="com.zl.dao.UserDao">
	 	<!-- 子类userDao给继承来的属性sessionFactory,注入bean,传递给父类HibernateDaoSupport,这是父类必			须要有的依赖" -->
	 	<property name="sessionFactory" ref="sessionFactory"></property>
	 </bean>

4.3 debug

规范问题:
	定义的方法,如果不是给属性赋值/取值,尽量避开 getXx/setXx方法命令方式。
XxDao bean配置:
	缺少sessionfactory
	提示信息:
			Caused by: java.lang.IllegalArgumentException: 'sessionFactory' or 'hibernateTemplate' 							is required;
	java.lang.IllegalArgumentException,这类异常,一般是属性赋值错误或者缺少必要属性;
	
	解决:加上sessionFactory属性
	<property name="sessionFactory" ref="sessionFactory"></property>

4.4 操作方法

有四种查询方式:
	方式1 session
	方式2 HQL
	方式3 SQL
	方式4 criteria 面向对象
本示例展示方式2 & 方式4

/**
	 * 根据用户ID获取用户
	 */
	public User findUser(final Integer id) {//语法要求,匿名内部类,拿到外部的参数,必须加上final修饰
		//方式2 QHL
		User user=getHibernateTemplate().execute(new HibernateCallback<User>() {//链式编程.execute方法,接受匿名内部类
			@Override
			public User doInHibernate(Session session) throws HibernateException {
				//1.编写hql语句
				String hql = "from com.zl.domain.User where id=?";
				Query query = session.createQuery(hql);
				query.setParameter(0, id);
				User user = (User) query.uniqueResult();
				return user;
			}
		});		
		return user;
	}

/**
	 * 根据用户IDS获取用户的list集合
	 * 使用方式4 criteria 标准entity方式
	 * @return
	 */
	public List<User> findUsers(){//规范,只有属性/变量才使用get/set方法,其它方法不要使用
        // 方式4 criteria
		DetachedCriteria dcriteria = DetachedCriteria.forClass(User.class);
		//有getHibernateTemplate,必然有setHibernateTemplate(),并且注入hibernateTemolate必须有sessionfactory;
		List<User> list = (List<User>) getHibernateTemplate().findByCriteria(dcriteria);
		//只要是查询必须判断是否为空 ,规范
		if (list!=null&&list.size()>0) {
			//list.forEach(e->{System.out.println(e);});
			return list;	
		}else {
			return null;
		}		
	}
}

4.5 更多操作方法

增加entity

/**	 * 添加用户信息	 * @throws ParseException 	 */	public void addUser() throws ParseException {		User user = new User();		user.setUsername("牛魔王");		user.setSex("男");		//Java Date 对应jdbc的date类型  StringDate -> Date		String pattern = "yyyy-MM-dd";		String sDate = "1997-10-01";		SimpleDateFormat sdf = new SimpleDateFormat(pattern);		Date date = sdf.parse(sDate);		user.setBirthday(date);		user.setAddress("莫锡国");				getHibernateTemplate().save(user);	}

报错了

报错提示信息:
	org.springframework.dao.InvalidDataAccessApiUsageException: Write operations are not allowed in 【read-only mode】 (FlushMode.MANUAL): Turn your Session into FlushMode.COMMIT/AUTO or remove 'readOnly' marker from transaction definition.

这是告诉我们,这是只读模式,查询没问题,增删改就需要修改为可读可写,增加事务。	

SSH整合最终版配置

spring.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:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/tx
       http://www.springframework.org/schema/tx/spring-tx.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd
        ">
        
    <!-- 读取外部配置文件 -->
    <context:property-placeholder location="classpath:db.properties"/>
    <!-- c3p0交付spring创建 -->
    <!-- 注意键是ComboPooledDataSource属性名字 -->
    <bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    	<property name="driverClass" value="${driverClass}"></property>
    	<property name="jdbcUrl" value="${jdbcUrl}"></property>
    	<property name="user" value="${user}"></property>
    	<property name="password" value="${password}"></property>
    </bean> 
	<!-- 让struts2种的action交给spring容器来管理 -->
	<bean name="supplierAction" class="com.zl.web.SupplierAction" scope="prototype">
		<property name="supplierService" ref="supplierService"></property>
	</bean>
	<!-- 让service层交给spring容器管理 -->
	<bean name="supplierService" class="com.zl.service.SupplierService"></bean>
	<bean name="userService" class="com.zl.service.UserService">
		<!-- 将XxDao注入到service层 -->
		<property name="userDao" ref="userDao"></property>
	</bean>
	
	<!-- 
		整合hiberna框架的东西:
			核心配置文件
			orm映射文件
		将LocalSessionFactoryBean交给spring容器管理 (LocalSessionFactoryBean) sessionfactory 的实现子类
		创建 sessionfactory的过程中,会主动与数据库链接。如果没有开启数据库,找不到会报错。
	 -->	 
	 <!-- 方法一,但是不推荐 -->
	 	<!-- 需要告诉LocalSessionFactoryBean 去哪里读取hibernate文件 ,靠下面的属性 -->
	 <!--   
	 <bean name="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
	 	<property name="configLocation" value="classpath:hibernate.cfg.xml"></property>
	 </bean>
	 --> 
	 <!-- 方法二,重点掌握 目标hibernate的所有配置都写进spring配置文件beans中 -->
	 <!-- 先来五个必选参数压压惊  -->
	 <!-- 接收复杂参数的固定形式,这里接受Map类型的多个 “key-value对” -->
	 <bean name="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
	 	<!-- c3p0 注入到hibernate框架 -->
	 	<property name="dataSource" ref="dataSource"></property>
	 	<property name="hibernateProperties">
	 		<!-- 5个必选参数 -->
	 		<!-- 2个可选参数 -->
	 		<props>
	 			<!-- c3p0连接池就能提供了 
	 			<prop key="hibernate.connection.driver_class">com.mysql.jdbc.Driver</prop>
	 			<prop key="hibernate.connection.url"><![CDATA[jdbc:mysql://192.168.200.150:3306/zl_orm?useUnicode=true&characterEncoding=utf8]]></prop>
	 			<prop key="hibernate.connection.username">root</prop>
	 			<prop key="hibernate.connection.password">root</prop>
	 			-->
	 			<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
	 			<prop key="hibernate.show_sql">true</prop>
	 			<prop key="hibernate.format_sql">true</prop>
	 		</props>	 		
	 	</property>
	 	<!-- 让spring去哪里加载ORM映射文件 -->											 
	 													<!-- 包扫描 ,可以读取到包下的所有配置文件-->
	 	<property name="mappingDirectoryLocations" value="classpath:com/zl/domain"></property>
	 </bean>
	 <!-- spring容器管理dao层 -->
	 <bean name="userDao" class="com.zl.dao.UserDao">
	 	<!-- 子类userDao给继承来的属性sessionFactory,注入bean,传递给父类HibernateDaoSupport,这是父类必须要有的依赖" -->
	 	<property name="sessionFactory" ref="sessionFactory"></property>
	 </bean>
	 <!-- spring容器管理事务 -->
	 <!-- 打开 Ctrl + shift + T 搜索HibernateTransactionManager -->
	 <bean name="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
	 	<!-- 依赖sessionfactory 属性注入 -->
	 	<property name="sessionFactory" ref="sessionFactory"></property>
	 </bean>
	 <!-- 开启事务扫描 【可选】 -->
	 <tx:annotation-driven transaction-manager="transactionManager"/>
	 <!-- 配置事务通知 -->
	 <tx:advice id="txadvice" transaction-manager="transactionManager">
	 	<tx:attributes>
	 		<tx:method name="find*" isolation="READ_COMMITTED" propagation="SUPPORTS" read-only="true"/>
	 		<tx:method name="add*" isolation="READ_COMMITTED" propagation="SUPPORTS" read-only="false"/>
	 	</tx:attributes>
	 </tx:advice>
	 <!-- 配置AOP织入 -->
	 <aop:config>
	 	<!-- 切点表达式 -->
	 	<aop:pointcut expression="execution(* com.zl.service.*Service.*(..))" id="pc"/>
	 	<aop:advisor advice-ref="txadvice" pointcut-ref="pc"/>
	 </aop:config>
</beans>

spring扩展

spring实体类复杂属性注入

<?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:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/tx
       http://www.springframework.org/schema/tx/spring-tx.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd
        ">
    
    	<!-- 以下内容,与SSH整合项目无关 借助搭好的架子做测试用的bean -->
		<!-- 测试给实体类复杂属性复制 -->
        <bean name="beanComplexTypeDI" class="com.zl.test.BeanComplexTypeDI">
            <property name="myString" value="这是我的测试">	</property>
            <property name="myPojo" ref="myPojo"></property>
            <!-- 复杂类型之数组 -->
            <property name="myArray">
                <array>
                    <value>这是数组数据注入</value>
                </array>
            </property>
            <property name="myList">
                <list>
                    <ref bean="myPojo"/>
                </list>
            </property>
            <property name="mySet">
                <set>
                    <ref bean="myPojo"/>
                </set>
            </property>
            <property name="myMap">
                <map>
                    <entry key="map001" value-ref="myPojo"></entry>
                </map>	
            </property>
            <property name="myProperties">
                <props>
                    <prop key="prop">复杂类型属性数据注入</prop>
                </props>	
            </property>
        </bean>
        <bean name="myPojo" class="com.zl.test.MyPojo">
            <property name="name" value="这是我测试用的pojo"></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>
	<package name="zl" namespace="/" extends="struts-default">
		<action name="supplierAction" class="supplierAction"
			method="supplier">
			<result name="success">/supplier.jsp</result>
		</action>
	</package>
</struts>	

hibernate.cfg.xml

这里面的配置已经全部放到spring bean。做参考

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <!--数据库驱动-->
        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
        <!--连接数据库URL--><!--通过URL解决hibernate向MySQL插入中文乱码问题-->
        <property name="connection.url">
            <![CDATA[jdbc:mysql://192.168.200.150:3306/zl_orm?useUnicode=true&characterEncoding=utf8]]></property>
        <!--连接数据库的用户名-->
        <property name="connection.username">root</property>
        <!--数据库用户密码-->
        <property name="connection.password">root</property>
        <!--选择数据库使用的方言-->
        <!-- hibernate dialect org.hibernate.dialect.MySQLDialect 对应 MySQL5.0之前 -->
        <!-- <property name="dialect">org.hibernate.dialect.MySQLDialect</property> -->
        <!-- dialect org.hibernate.dialect.MySQL5InnoDBDialect 对应MySQL5.0版本之后-->
        <property name="dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
        
        <!-- 连接池的配置 -->
        <!--JDBC连接池最大连接数-->
        <property name="hibernate.c3p0.max_size">20</property>
        <!--JDBC连接池最小连接数-->
        <property name="hibernate.c3p0.min_size">1</property>
        <!--连接池连接的超时时间-->
        <property name="hibernate.c3p0.timeout">5000</property>
        <!--连接池最大缓存多少个statement对象-->
        <property name="hibernate.c3p0.max_statements">100</property>
        <!--每隔3000秒检查连接池里的空闲连接-->
        <property name="hibernate.c3p0.idle_test_period">3000</property>
        <!--连接池里面的连接用完的时候,指定c3p0可以获取2个新的连接数-->
        <property name="hibernate.c3p0.acquire_increment">2</property>
        <!--每次验证连接池的连接是否可用-->
        <property name="hibernate.c3p0.validate">true</property>
        <!--JDBC连接池(使用内置的连接池)-->
        <property name="connection.pool_size">1</property>

        <!--根据需要自动创建数据表--> <!--在启动时删除并重新创建数据库-->
        <!-- <property name="hbm2ddl.auto">update</property> -->
        <!--显示执行的SQL语句-->
        <property name="hibernate.show_sql">true</property>
        <!--将sql脚本进行格式化后输出-->
        <property name="hibernate.format_sql">true</property>
        <!--设置Hibernate自动管理上下文的策略-->
        <!--<property name="current_session_context_class">thread</property>-->
        <!--下面罗列出持久化类的类名--><!--类的全限定名-->
        <!-- <mapping class="com.zl.domain.User"/> -->
        <!-- 把mapping映射文件引入到hibernate核心配置文件 -->
        <mapping resource="com/zl/domain/User.hbm.xml"></mapping>
    </session-factory>
</hibernate-configuration>

db.properties

driverClass=com.mysql.jdbc.Driver
jdbcUrl=jdbc:mysql://192.168.200.150:3306/zl_orm?useUnicode=true&characterEncoding=utf8
user=root
password=root

记录一下db.properties的小bug

当对文件做了修改后(比如同文件切换到Oracle链接参数),表面看没问题,但是通过el ${} 读取就是不能连接到数据库。

解决方法:
	1)亲自测试有效,原文件复制一份数据,删掉文件,新建文件。spring.xml读取db新文件。

log4j2.xml

日志也是必不可少;bug常用,日志提供很大帮助

<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
    <Appenders>
        <Console name="STDOUT" target="SYSTEM_OUT">
            <PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/>
        </Console>
        <RollingFile name="RollingFile" fileName="logs/strutslog1.log"
                     filePattern="logs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz">
            <PatternLayout>
                <Pattern>%d{MM-dd-yyyy} %p %c{1.} [%t] -%M-%L- %m%n</Pattern>
            </PatternLayout>
            <Policies>
                <TimeBasedTriggeringPolicy />
                <SizeBasedTriggeringPolicy size="1 KB"/>
            </Policies>
            <DefaultRolloverStrategy fileIndex="max" max="2"/>
        </RollingFile>
    </Appenders>
    <Loggers>
        <Logger name="com.opensymphony.xwork2" level="WAN"/>
        <Logger name="org.apache.struts2" level="WAN"/>
        <Root level="warn">
            <AppenderRef ref="STDOUT"/>
        </Root>
    </Loggers>
 
</Configuration>
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值