Spring(十)----SSH框架整合

回顾:

1. AOP注解方式
编写切面类(包含通知和切入点)
开启自动代理
2. JDBC模板技术
Spring提供模板技术,数据库的操作
以后编写DAO层,都可以继承JdbcDaoSupport类(JDBC模板)
Spring框架可以整合开源连接池
3. Spring事务管理
Spring框架事务管理需要接口和概述
PlatformTransactionManager接口(平台事务管理器接口),不管使用哪种方式管理事务,这个类必须配置的!!
手动编码(了解)
声明式事务管理方式(重点掌握),默认使用AOP的技术来增强
XML的方式
注解的方式


ssh整合资料

SSH三大框架需要的配置文件

1. Struts2框架

*在web.xml中配置核心的过滤器

<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>
*在src目录下创建struts.xml,用来配置Action
2. Hibernate框架

* 在src目录创建hibernate.cfg.xml配置文件
* 在JavaBean所在的包下映射的配置文件

3. Spring框架

* 在src目录下创建applicationContext.xml

* 在src目录下log4j.proerties

* 在web.xml配置整合WEB的监听器

<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>

一、Spring框架整合Struts2框架

1. 导入CRM项目的UI页面,找到添加客户的页面,修改form表单,访问Action




编写Action类

public class CustomerAction extends ActionSupport {

	private static final long serialVersionUID = -7334305113638651338L;

	public String add() {
		System.out.println("web层:保存客户...");
		return NONE;
	}
}
配置struts.xml
<struts>
	<package name="crm" namespace="/" extends="struts-default">

		<!-- 配置客户的Action -->
		<action name="customer_*" class="com.ken.web.CustomerAction"
			method="{1}"></action>
	</package>

</struts>



action收到了来自前端的请求,接下来就是去调用service层了。

创建service接口和类。

然后,在applicationContext.xml中配置service bean

<!-- 配置客户模块 -->
<bean id="customerService" class="com.ken.service.CustomerServiceImpl">

</bean>
action通过web工厂来调用service


流程:服务器启动,web.xml中的ContextLoaderListener会执行,applicationContext.xml就被加载。applicationContext.xml中的所有的bean配置都会被解析。然后,bean就会被创建,并且默认是单例。然后,通过web工厂从容器中拿。拿到之后,下次使用就不用再次加载配置文件了,只要直接从工厂里面拿。

在Action中获取到service(开发不会使用,因为麻烦)
可以通过 WebApplicationContextUtils.getWebApplicationContext(ServletActionContext.getServletContext()); 来获取,但是这种方式编写代码太麻烦了。

Spring整合Struts2框架的第一种方式(Action由Struts2框架来创建)

在Action中添加:

private CustomerService customerService;

public void setCustomerService(CustomerService customerService) {
	this.customerService = customerService;
}
就可以直接用了。因为,struts2-spring-plugin-2.3.24.jar帮我们自动注入了。




如此一来,action中只要提供一个变量的set方法,struts框架就会帮我们从spring工厂中按名称去拿bean。

Action的类是在struts.xml中配置的,那么action的对象就是由struts2框架来创建的,并且是多例的,有一次请求就创建一个action对象。

Spring整合Struts2框架的第二种方式(Action由Spring框架来创建)

(推荐大家来使用的)

上面那种方法中,action对象是由struts2框架来创建的。而我们的spring的核心ioc就是负责对象的创建以及依赖的管理。那么,action也可以由spring来创建嘛。然后,我们就可以直接注入service了。这样的好处是,action,service,dao,所有对象都由spring来管理。

做法是:

首先,在applicationContext.xml中配置这个action。


那么问题来了,我们在struts.xml中也配置了这个action,也会创建这个action的对象


怎么办呢?


要注意,action是多例的,要在applicationContext.xml中配置。


action交给了spring来管理,那么自动注入就失效了。我们要手动注入service。


二、Spring框架整合Hibernate框架

1. 编写CustomerDaoImpl的代码,加入配置并且在CustomerServiceImpl中完成注入



接下来就是考虑,dao层如何操作数据库了。

我们使用HibernateTemplate,它需要一个session。最终的操作数据库,就是使用session.get(), session.save()等方法。

我们可以在dao层的方法中new一个HibernateTemplate对象,来使用。如下图:


但是,我们用spring来做整合。那么,我们把模板对象也交给spring来管理。



我们要使用模板类的话,还要在它这里注入一些东西。


我们的dao实现类可以继承HibernateDaoSupport,它帮我们提供了hibernateTemplate成员变量和set方法。






2.1 带有hibernate.cfg.xml的配置文件

2. 编写映射的配置文件,并且在hibernate.cfg.xml的配置文件中引入映射的配置文件

3. 在applicationContext.xml的配置文件,配置加载hibernate.cfg.xml的配置

<!-- 编写bean,名称都是固定,加载hibernate.cfg.xml的配置文件 -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
	<property name="configLocation" value="classpath:hibernate.cfg.xml" />
</bean>
LocalSessionFactoryBean用来加载hibernate的核心配置文件,并且,顺便帮我们构建sessionFactory对象。所以,我们一般把它的id值设为sessionFactory。
流程:当我们启动服务器,刚刚配置的这个对象会被创建。它一创建,就会加载hibernate的核心配置文件。然后,根据配置文件的信息,去生成一个SessionFactory对象。SessionFactory对象可以创建session。 SessionFactory是重量级的,不要轻易创建和销毁。那么,我们这个配置就正好,我们启动服务器,创建SessionFactory对象,这个对象就在内存中了。只要服务器不关,它就一直活着。

我们把SessionFactory对象注入到dao的实现类中。dao的实现类中,只需要使用hibernateTemplate即可。因为hibernateTemplate对session进行了封装。底层,还是session在做。

4. 在CustomerDaoImpl中想完成数据的添加,Spring框架提供了一个HibernateDaoSupport的工具类,以后DAO都可以继承该类

5. 开启事务的配置


先配置事务管理器,注意现在使用的是Hibernate框架,所以需要使用Hibernate框架的事务管理器。事务是又session来管理的。SessionFactory可以生产session。所以,我们把SessionFactory注入给事务管理器。

<!-- 先配置平台事务管理器 -->
<bean id=""
	class="org.springframework.orm.hibernate5.HibernateTransactionManager">
	<property name="sessionFactory" ref="sessionFactory" />
</bean>
开启注解事务
<tx:annotation-driven transaction-manager="transactionManager" />
在Service类中添加事务注解
@Transactional
ssh整合带hibernate配置文件代码

2.2 不带有hibernate.cfg.xml的配置文件

不带有hibernate.cfg.xml配置文件,那么这个配置文件里的内容就要转移到applicationContext.xml文件中。

hibernate核心配置文件里面有:数据库的4大参数c3p0连接池。我们的spring可以整合c3p0连接池。那么,这两个参数就完事了。还有,数据库方言可选配置(show_sql, format_sql, hbm2ddl.auto)、映射文件

1.先配置连接池相关的信息

<!-- 先配置c3p0连接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
	<property name="driverClass" value="com.mysql.jdbc.Driver" />
	<property name="jdbcUrl" value="jdbc:mysql:///ssh_inte1" />
	<property name="user" value="root" />
	<property name="password" value="123456" />
</bean>
我们的hibernate核心配置文件的作用就是为了创建SessionFactory。我们在spring里面也可以创建 SessionFactory,通过LocalSessionFactoryBean。

2.修改 LocalSessionFactoryBean 的属性配置,因为已经没有了hibernate.cfg.xml的配置文件,所以需要修改该配置,注入连接池

3.在 LocalSessionFactoryBean 中配置,使用hibernateProperties属性继续来配置其他的属性,注意值是properties属性文件


<!-- 编写bean,名称都是固定,加载hibernate.cfg.xml的配置文件 -->
<!-- 之前是加载hibernate.cfg.xml。现在,我们取消hibernate核心配置文件,如下方这样配置 -->
<bean id="sessionFactory"
	class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
	<!-- 先加载连接池 -->
	<property name="dataSource" ref="dataSource" />
	<!-- 加载方言,加载可选项 -->
	<property name="hibernateProperties">
		<props>
			<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
			<prop key="hibernate.show_sql">true</prop>
			<prop key="hibernate.format_sql">true</prop>
			<prop key="hibernate.hbm2ddl.auto">update</prop>
		</props>
	</property>
	<!-- 引入映射的配置文件 -->
	<property name="mappingResources">
		<list>
			<value>com/ken/domain/Customer.hbm.xml</value>
		</list>
	</property>
</bean>
ssh整合,不带hibernate.cfg.xml
目前的代码没有绑定到当前线程的代码。如果有,就报错了。因为,我们现在用LocalSessionFactoryBean,它由spring提供的。它来帮我们生产session,会负责管理session,而且生成的是session的一个代理对象。所以,现在session不是由hibernate来维护了。现在的session是由spring来创建的。所以,不能配置绑定到当前线程的操作。

三、Hibernate的模板的常用的方法

1. 增删改的操作

  • 添加:save(Object obj);
  • 修改:update(Object obj);
  • 删除:delete(Object obj);
2. 查询的操作
查询一条记录:
  • Object get(Class c,Serializable id);
  • Object load(Class c,Serializable id);
3. 查询多条记录:List find(String hql,Object... args);


4.QBC方式查询所有

findByCriteria(DetachedCriteria criteria, ...)

离线条件查询。我们可以提前把条件准备好,然后,当做参数传进来。

看上面的,参数列表里面有 int firstRresult, int maxResults, 很适合做分页查询。

/**
 * QBC, 查询所有
 */
@Override
public List<Customer> findAllByQBC() {
	DetachedCriteria criteria = DetachedCriteria.forClass(Customer.class);
	// 设置条件查询
	List<Customer> list = (List<Customer>) this.getHibernateTemplate().findByCriteria(criteria);
	return list;
}
离线条件,为什么称为离线?因为这个对象不是由session来创建的,是我们自己new的,所以,它放在任何一层都可以。

四、延迟加载问题


在action中创建loadById方法,并在service和dao层分别创建,dao层的代码如下:


访问这个接口:



这是包冲突了:


包删除后,再访问,有另一个异常:


load方法是延迟加载。延迟加载,当你用到它属性的时候才会去发送sql语句。


原因在于,system.out.println(c)的时候,才发sql语句。然而,这个时候session已经销毁了,session销毁了,就没法发sql。


web层调用service层。请求到了service层之后,service就帮我们创建session,管理事务。service接着调用dao层。在dao层,load方法,延迟加载,并没有去数据库面查数据,返回给service层的对象(代理对象)里面只有一个id。service把对象返回给web层,并且关闭了session。web层拿到对象(代理对象)之后,进行打印操作,这时用到了客户的属性,就发sql,可是session已经关闭了。就报这个错:

org.hibernate.LazyInitializationException: could not initialize proxy - no Session
解决方案1:不使用延迟加载,那么第一次查询的时候就把所有的属性查出来了。


加了lazy="false"就不延迟加载了。我们延迟加载是为了提高程序的性能。那我们怎么样做更好呢?

解决方案2:Spring框架提供了一个过滤器,让session对象在WEB层就创建,在WEB层销毁。只需要配置该过滤器即可。但是,要注意需要在struts2的核心过滤器之前进行配置

<!-- 解决延迟加载的问题 -->
<filter>
	<filter-name>OpenSessionInViewFilter</filter-name>
	<filter-class>org.springframework.orm.hibernate5.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
	<filter-name>OpenSessionInViewFilter</filter-name>
	<url-pattern>/*</url-pattern>
</filter-mapping>
看名字:open session in view,在视图层打开session。也就是在web层开启session。

ssh_inte2模板常用方法&延迟加载问题


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值