SSH整合(Spring整合Hibernate、Struts2整合Spring、延遲加載問題)xml方式

目標:體現spring的特性:粘合劑的作用(整合Hibernate,整合Struts2)。能讓spring管理的都讓其管理。

1.SSH jar包和配置文件的導入

1.1 struts2框架(15個)

第一步:導入Jar包
在這裏插入圖片描述
第二步:web.xml配置文件
web.xml 配置核心Filter

<!-- struts2的前端控制器,這是struts2運行的核心 -->
<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

<?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.devMode" value="true" />
	<!-- 主題樣式 -->
	<constant name="struts.ui.theme" value="simple"/>

    <package name="default" namespace="/" extends="struts-default">
	 
    </package>

</struts> 

第四步:在src下,創建log4j.properties

### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### direct messages to file mylog.log ###
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=c\:mylog.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### set log levels - for more verbose logging change 'info' to 'debug' ###

log4j.rootLogger=info, stdout

1.2 Spring4框架(13個)

第一步:導入Jar包
Spring4.2 開發最基本jar包

  • spring-beans-4.2.4.RELEASE.jar
  • spring-context-4.2.4.RELEASE.jar
  • spring-core-4.2.4.RELEASE.jar
  • spring-expression-4.2.4.RELEASE.jar

AOP開發

  • spring-aop-4.2.4.RELEASE.jar
  • spring-aspects-4.2.4.RELEASE.jar
  • com.springsource.org.aopalliance-1.0.0.jar
  • com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar

Spring Jdbc開發

  • spring-jdbc-4.2.4.RELEASE.jar

Spring事務管理

  • spring-tx-4.2.4.RELEASE.jar

Spring整合其他ORM框架

  • spring-orm-4.2.4.RELEASE.jar

Spring在web中使用

  • spring-web-4.2.4.RELEASE.jar

Spring整合Junit測試

  • spring-test-4.2.4.RELEASE.jar

第二步:web.xml配置文件
web.xml 核心監聽器,初始化容器

<!-- spring的核心監聽器:初始化spring容器 -->
<listener>
	<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
   <!-- spring的核心監聽器:定義spring容器的位置,在src下 -->
<context-param>
	<param-name>contextConfigLocation</param-name>
	<param-value>classpath:applicationContext.xml</param-value>
</context-param>

第三步:在src下applicationContext.xml ,引入bean、context、aop、tx的約束

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       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/context
                           http://www.springframework.org/schema/context/spring-context.xsd
                           http://www.springframework.org/schema/aop
                           http://www.springframework.org/schema/aop/spring-aop.xsd
                           http://www.springframework.org/schema/tx
                           http://www.springframework.org/schema/tx/spring-tx.xsd">

1.3 hibernate5框架

第一步:導入Jar包
在這裏插入圖片描述
第二步:配置文件 ,在src下 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>
	<!-- JDBC基本連接參數 -->
	<session-factory> 
		<!-- conntion配置-mysql -->
		<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
		<property name="hibernate.connection.url">jdbc:mysql:///itcastspring</property>
		<property name="hibernate.connection.username">root</property>
		<property name="hibernate.connection.password">root</property>
		<!-- 配置方言-mysql -->
		<property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
		
		<!-- 常見其它配置 -->
		<property name="hibernate.show_sql">true</property> <!-- 控制檯上打印SQL -->
		<property name="hibernate.format_sql">true</property> <!-- 控制檯輸出時,對SQL語句格式化 -->
		<!-- 測試環境 create/ create-drop 正式環境 update validate -->
		<property name="hibernate.hbm2ddl.auto">update</property> <!-- 自動建表 -->
		
		<!-- 引入映射配置 -->
		<mapping resource="cn/itcast/ssh/domain/Book.hbm.xml"/>

	</session-factory>
</hibernate-configuration>

2.Spring整合Hibernate

複習:Hibernate是如何使用的

  1. 編寫實體類映射文件
    映射文件(例:Customer.hbm.xml)反映了持久化類和數據庫表的映射信息
  2. 編寫主配置文件
    hibernate.cfg.xml主要用來配置數據庫連接以及Hibernate運行時所需要的各個屬性的值
  3. 創建工具類HibernateUtil,使用靜態代碼塊獲取SessionFactory
    默認會去src下讀取 hibernate.cfg.xml配置文件,也可指定目錄
public class HibernateUtil {
    private static SessionFactory factory;
    // 使用靜態代碼塊獲取SessionFactory
    static {
        //細節:Hibernate把所有可預見的異常,都轉成了運行時異常(工具中不會提示要添加異常塊)
        try {
            // 默認會去src下讀取 hibernate.cfg.xml配置文件
            Configuration config = new Configuration().configure();
            factory = config.buildSessionFactory();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 獲取一個新的Session對象(每次都是一個新對象)
     * @return
     */
    public static Session openSession(){
        return factory.openSession();
    }

    /**
     * 創建的Session實例會被綁定到當前線程中,它在提交或回滾操作時會自動關閉。
     * @return
     */
    public static Session getCurrentSession(){
        return factory.getCurrentSession();
    }
}

由於Session對象屬於線程不安全,當一個線程有多個Session時,無法保證事務。==所以一個線程要保障只有一個Session對象。==所以在業務中,我們使用getCurrentSession();


複習:用之前的方式使用Hibernate

第一步:數據庫腳本
在這裏插入圖片描述
第二步:建立cn.itcast.ssh.domain包,用來存放實體類Book.java和實體類的映射文件Book.hbm.xml:

//po實體類
public class Book {
	private Integer id;//oid
	private String name;
	private Double price;
	
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Double getPrice() {
		return price;
	}
	public void setPrice(Double price) {
		this.price = price;
	}
	
	public String toString() {
		return "Book [id=" + id + ", name=" + name + ", price=" + price + "]";
	}

}

編寫實體類的映射文件Book.hbm.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
	<class name="cn.itcast.ssh.domain.Book" table="book">
		<id name="id">
			<generator class="native"/>
		</id>
		<property name="name"/>
		<property name="price"/>
	</class>
</hibernate-mapping>

第三步:配置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>
	<!-- JDBC基本連接參數 -->
	<session-factory> 
	<!-- 理解爲連接池 -->
		<!-- conntion配置-mysql -->
		<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
		<property name="hibernate.connection.url">jdbc:mysql:///itcastspring</property>
		<property name="hibernate.connection.username">root</property>
		<property name="hibernate.connection.password">root</property>
		<!-- 配置方言-mysql -->
		<property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
		
		<!-- 常見其它配置 -->
		<property name="hibernate.show_sql">true</property> <!-- 控制檯上打印SQL -->
		<property name="hibernate.format_sql">true</property> <!-- 控制檯輸出時,對SQL語句格式化 -->
		<!-- 測試環境 create/ create-drop 正式環境 update validate -->
		<property name="hibernate.hbm2ddl.auto">update</property> <!-- 自動建表 -->
		
		<!-- 引入映射配置 -->
		<mapping resource="cn/itcast/ssh/domain/Book.hbm.xml"/>

	</session-factory>
</hibernate-configuration>

使用Junit測試連接數據庫:

public class HibernateTest {

	@Test
	public void test(){
		Configuration configuration = new Configuration();
		//加載src下的hibernate.cfg.xml
		configuration.configure();
		//創建SessionFactory工廠
		SessionFactory sf = configuration.buildSessionFactory();
		//打開Session
		Session s = sf.openSession();
		//開啓事務
		Transaction tr = s.beginTransaction();
		
		Book book = new Book();
		book.setName("金瓶梅");
		book.setPrice(122d);
		s.save(book);
		
		//事務提交
		tr.commit();
		//session關閉
		s.close();
		sf.close();
	}
}

2.1 Spring整合Hibernate第一步:SessionFactory交給spring管理

大家都知道,Hibernate的核心是SessionFactory,並由SessionFactory創建Session,再由Session操作數據庫。
之前的SessionFactory維護是通過主配置文件進行維護的(主配置文件最主要的標籤就是Session-Factory)

思想:將Hibernate中SessionFactory對象,由Spring管理通過 spring-orm包 提供LocalSessionFactoryBean實現

這裏有兩個方式

  • 直接在spring中加載hibernate配置文件 (零障礙整合)
  • 將hibernate參數配置到spring文件 (推薦)

方式一:直接在spring中加載hibernate配置文件

<!-- spring整合Hibernate:將session工廠交給spring管理,這是spring整合hibernate的核心 -->
<!-- 方式一: 直接在spring中加載hibernate配置文件 (零障礙整合) -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
	
	<!-- 注入Hibernate的核心配置文件
	提示技巧:xxxLocation,一般都要加classpath -->
	<property name="configLocation" value="classpath:hibernate.cfg.xml"/>
</bean>

測試:刪除book表,執行spring junit,查看錶是否自動創建

//目標:測試一下spring的bean的某些功能
@RunWith(SpringJUnit4ClassRunner.class) //junit整合spring的測試//立馬開啓了spring的註解
@ContextConfiguration(locations = "classpath:applicationContext.xml") //加載核心配置文件,自動構建spring容器
public class SpringTest {
    @Autowired
    private SessionFactory sessionFactory;

    @Test
    public void testHibernate() {

    }

}

原理:Web.xml 配置監聽器 —> 初始化spring容器 —> 初始化hibernate配置—>初始化所有單例對象 —> sessionFactory 建表
在這裏插入圖片描述

方式二: (推薦)將hibernate參數配置到spring文件
完全由spring進行管理,沒有hibernate.cfg.xml配置文件

經過分析: 需要三個方面的配置 (數據源配置、 常用屬性配置、 hbm映射加載 )

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


    <!-- 引入外部屬性配置文件 -->
    <context:property-placeholder location="classpath:db.properties"/>
    <!-- c3p0連接池 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driverClass}"/>
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="user" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>

    <!-- 方式二: (推薦)將hibernate參數配置到spring文件  -->
    <bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
        <!-- 1.數據源 -->
        <property name="dataSource" ref="dataSource"/>
        <!-- 2.Hibernate的屬性 -->
        <property name="hibernateProperties">
            <props>
                <!-- 設置方言 -->
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
                <!-- 設置打印sql語句 -->
                <prop key="hibernate.show_sql">true</prop>
                <!-- 格式化sql語句 -->
                <prop key="hibernate.format_sql">true</prop>
                <!-- 自動建表 -->
                <prop key="hibernate.hbm2ddl.auto">update</prop>
            </props>
        </property>
        <!-- 3.mapping映射 -->
        <property name="mappingResources">
            <list>
                <value>cn/itcast/ssh/domain/Book.hbm.xml</value>
            </list>
        </property>
    </bean>

</beans>

2.2 Spring整合dao和service

編寫dao

Spring 整合 Hibernate,提供 HibernateTemplate簡化原始Hibernate代碼 (不用關心session,你只需要用就行了)

HibernateTemplate常用的API

  • void save(Object entity)
  • void update(Object entity)
  • void delete(Object entity)
  • T get(Class entityClass, Serializableid)
  • T load(Class entityClass, Serializable id)
  • List find(String queryString, Object… values)
  • List findByCriteria(DetachedCriteria criteria)
  • List findByNamedQuery(String queryName, Object… values)

第一步:創建IBookDao接口

public interface IBookDao {

	//保存圖書
	public void save(Book book);
	//更新圖書(根據id)
	public void update(Book book);
	//刪除圖書(根據id)
	public void delete(Book book);
	
	//根據id查詢
	public Book findById(Integer id);
	
	//查詢所有
	public List<Book> findAll();
	
	//複雜條件條件
	//1.命名查詢:QBN
	public List<Book> findByNamedQuery(String queryName, Object... values);
	
	//2.離線條件查詢:QBC
	public List<Book> findByCriteria(DetachedCriteria criteria);
}

第二步:使用HibernateTemplate 實現增刪改查

//圖書的持久層
//HibernateDaoSupport用來簡化代碼,能提供HibernateTemplate,
public class BookDaoImpl extends HibernateDaoSupport implements IBookDao{
	
	//保存圖書
	public void save(Book book){
		//注入sesson工廠,獲取session--不會寫了
		//因爲:spring提供了模版類,來整合Hibernate
		super.getHibernateTemplate().save(book);
	}
	//更新圖書(根據id)
	public void update(Book book){
		super.getHibernateTemplate().update(book);
	}
	//刪除圖書(根據id)
	public void delete(Book book){
		super.getHibernateTemplate().delete(book);
	}
	
	//根據id查詢
	public Book findById(Integer id){
		return super.getHibernateTemplate().get(Book.class, id);
	}
	
	//查詢所有
	public List<Book> findAll(){
		return super.getHibernateTemplate().loadAll(Book.class);
//		return super.getHibernateTemplate().find("from Book");//hql方式
	}
	
	//複雜條件條件
	//1.命名查詢:QBN
	public List<Book> findByNamedQuery(String queryName, Object... values){
		return super.getHibernateTemplate().findByNamedQuery(queryName, values);
	}
	
	//2.離線條件查詢:QBC
	public List<Book> findByCriteria(DetachedCriteria criteria){
		return super.getHibernateTemplate().findByCriteria(criteria);
	}
	
}

查看HibernateDaoSupport類的底層,我們發現,要想創建、使用HibernateTemplate,必須要注入SessionFactory

第三步:配置applicationContext.xml

<!-- dao -->
<bean id="bookDao" class="cn.itcast.ssh.dao.BookDaoImpl">
	<!-- 注入sessionFactory,這是在Dao層使用hibernateTemplate的條件,用來操作數據庫的crud -->
	<property name="sessionFactory" ref="sessionFactory"/>
</bean>

編寫service

第一步:創建接口類IBookService.java

public interface IBookService {

	//保存圖書
	//方法名不能隨便寫,配置事務save*,事務才能可寫
	public void saveBook(Book book);
	
	//查詢:複雜條件查詢,根據書名模糊查詢,配置事務find*,表示查詢,事務只讀
	public List<Book> findBookListByNameLike(String name);
}

第二步:創建接口類的實現類BookServiceImpl實現接口類

//圖書業務層
public class BookServiceImpl implements IBookService {
	//注入dao層
	private IBookDao bookDao;
	
	public void setBookDao(IBookDao bookDao) {
		this.bookDao = bookDao;
	}

	//保存圖書
	//方法名不能隨便寫,配置事務save*
	public void saveBook(Book book){
		//調用dao層
		bookDao.save(book);
	}
	
	//查詢:複雜條件查詢,根據書名模糊查詢
	public List<Book> findBookListByNameLike(String name){
		//1.qbn
//		return bookDao.findByNamedQuery("Book.findBookListByNameLike", "%"+name+"%");
		
		//2.qbc
		DetachedCriteria criteria = DetachedCriteria.forClass(Book.class);//root對象類型
		criteria.add(Restrictions.like("name",  "%"+name+"%"));
		return bookDao.findByCriteria(criteria);
	}

}

第三步:Book.hbm.xml文件,定義命名查詢:使用qbn的方式查詢的時候使用

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
	<class name="cn.itcast.ssh.domain.Book" table="book">
		<id name="id">
			<generator class="native"/>
		</id>
		<property name="name"/>
		<property name="price"/>
	</class>
    <!--定義命名查詢-->
	<query name="Book.findBookListByNameLike">
		from Book where name like ?
	</query>
</hibernate-mapping>

配置applicationContext.xml

<!--service -->
<bean id="bookService" class="cn.itcast.ssh.service.BookServiceImpl">
	<!-- 注入dao -->
	<property name="bookDao" ref="bookDao"/>
</bean>

總結HibernateTemplate的查詢使用


2.3 聲明式事務管理 ,在Service層完成

<!-- 配置聲明式事務處理 -->
<!-- 平臺事務管理器的實現 -->
<bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
	<!-- 注入sessin工廠 -->
	<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<!-- 配置聲明式事務 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
	<!-- 具體事務的屬性策略 -->
	<tx:attributes>
		<tx:method name="save*"/>
		<tx:method name="update*"/>
		<tx:method name="delete*"/>
		<tx:method name="find*" read-only="true"/>
	</tx:attributes>
</tx:advice>


<!-- 事務的切入點和切面配置 -->
<aop:config>
	<!-- 切入點 -->
	<aop:pointcut expression="bean(*Service)" id="txPointcut"/>
	<!-- 切面 -->
	<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
</aop:config>

Spring_HibernateTemplate事務處理

問題:1.我們知道sessionFactory獲取session有兩種方式,而HibernateTemplate是基於sessionFactory,那麼HibernateTemplate底層使用的session是哪一種?
問題:2.如果兩個dao中的HibernateTemplate的底層使用的session不是同一個,那麼如何在一個方法中控制事務?


3.Spring整合Struts2

3.1 編寫action

第一步:在web下新建:addbook.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@taglib uri="/struts-tags" prefix="s"%>
<!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>添加圖書</title>
</head>
<body>
	<h1>歡迎使用Xxx的圖書管理系統</h1>
	<s:form action="book_add" namespace="/" method="post">
		圖書的名稱:<s:textfield name="name"/><br/>
		圖書的價格:<s:textfield name="price"/><br/>
		<s:submit value="保存"/><s:reset value="重置"/>
	</s:form>
</body>
</html>

第二步:新建cn.itcast.web.action包,存放action,編寫BookAction,配置add方法完成添加

//圖書管理的表現層
public class BookAction extends ActionSupport implements ModelDriven<Book>{
	//數據模型對象
	private Book book=new Book();
	
	public Book getModel() {
		return book;
	}
	
	//成員變量
	private IBookService bookService;
	//激活了自動注入裝配spring的bean的機制功能
	//在實例化action之後,自動到spring容器中,尋找xxx的名字的bean,調用setXxx
	public void setBookService(IBookService bookService){
		this.bookService = bookService;
	}
	
	//業務方法:保存圖書
	public String add(){
		System.out.println(book);
		//調用業務層保存...
		bookService.saveBook(book);
		return NONE;
	}
}
  • ActionSupport :實現action的一種方式
  • ModelDriven:接收參數的一種方式(數據模型對象

第三步:配置struts.xml

<package name="default" namespace="/" extends="struts-default">
	<!-- 圖書管理 -->
	<!-- action還是struts自己管理,自動裝配bean的機制 -->
	<action name="book_*" class="cn.itcast.ssh.web.action.BookAction" method="{1}">
		
	</action>
</package>

3.2 在Action類注入Service

方式一: Action自動裝配Service --(機制:struts整合了spring)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章