`

Ssi的整合(Struts2+Spring+Ibatis)

阅读更多

Ssi的整合(Struts2+Spring+Ibatis)

1 jar包的下载

         本文好用的三个框架版本分别为

         struts-2.3.8 spring-framework-3.0.5.RELEASEibatis-2.3.4.726

下载地址:struts

Struts2

http://archive.apache.org/dist/struts/binaries/struts-2.3.8-all.zip

Spring

http://www.springsource.org/spring-community-download(进入后需要录入信息后才能下载)

Ibatis

http://archive.apache.org/dist/ibatis/binaries/ibatis.java/ibatis-2.3.4.726.zip

 

2 程序搭建---Struts2

2.1首先在eclipse新建web工程,新建创建的web目录结构如下:

ssi-release

         |__compensate

         |___webapps

                   |___META-INF

                            |___MANIFEST.MF 

                   |___WEB-INF

                            |___classes

                            |___lib

                            |___web.xml

                   |___index.jsp

 

2.2拷贝Struts2基本的jar包到工程下的lib目录

commons-fileupload-1.2.2.jar

commons-io-2.0.1.jar

commons-lang3-3.1.jar

freemarker-2.3.19.jar

javassist-3.11.0.GA.jar

ognl-3.0.6.jar

struts2-core-2.3.8.jar

xwork-core-2.3.8.jar

log4j-1.2.15.jar(非必须,便于使用log4j所以此处添加本jar包)

2.3web.xml中添加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>

其中mapping<url-pattern>/*</url-pattern>表示过滤所有请求

 

2.3编写Struts2测试action

        创建com.jshand.ssi.action

        com.jshand.ssi.action包下创建TestAction类实现com.opensymphony.xwork2.Action接口

并实现方法execute方法,代码如下

package com.jshand.ssi.action;

 

import com.opensymphony.xwork2.Action;

 

/**

 *@file_nameTestAction.java

 *@project       ssi-release

 *@author     jshand

 *@createDateJun2,2013  12:37:18PM

 *@version    1.0

 *http://www.jshand.com

 *

 */

 

publicclass TestAction implements Action{

   

    public String actionStr = "com.jshand.ssi.action.TestAction";

   

    public String execute() throws Exception{

       System.out.println("execute Struts2 Action ......");

       returnSUCCESS;

    }

    public String getActionStr() {

       returnactionStr;

    }

 

    publicvoid setActionStr(String actionStr) {

       this.actionStr = actionStr;

    }

}

其中actionStr属性定义了一个字符串,并设置了setget方法目的是讲测试Struts2封装的参数传递,将接收的或者默认的字符串输出到jsp中。

2.3编写Struts2的配置文件struts.xml

在源文件目录(工程下compensate目录)创建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="struts2" extends="struts-default" >

        <action name="test" class="com.jshand.ssi.action.TestAction">

            <result name="success">/index.jsp</result>

        </action>

    </package>

</struts>

主要配置xmlaciton节点,

name属性为自定义属性,同一个package不允许出现相同name

class属性为之前编写的TestAction的全路径

<action name="test" class="com.jshand.ssi.action.TestAction">

      <result name="success">/index.jsp</result>

</action>

 

 

 

action子节点中添加一个result节点当执行完Action后跳转到index.jsp中,在index.jsp中添加如下代码${actionStr},使输入的参数或这作用域内的属性输出到index.jsp

<body>

    This is my JSP page. <br>

    ${actionStr}

  </body>

启动中间件,本文用到的是tomcat6,在浏览器中输入

http://localhost:8080/ssi-release/test.action?actionStr=testParameter

控制台输出如下:



 

 

浏览器跳转到index.jsp,并输出接受到的参数



 

说明Struts2配置成功!接下来我们整合SpringStruts2

3 程序搭建---整合SpringStruts2

Struts2一样大多数框架的第一个步骤都是拷贝jar包到工程中,并配置环境变量 Spring所需要的包如下,其中struts2-spring-plugin-2.3.8.jar为整合struts2Spring的包,当然这个包不是必须的,我们可以通过其他方法进行处理。

aopalliance-1.0.jar

aspectj-DEVELOPMENT-20130313082900.jar

aspectjlib-1.5.2.jar

aspectjweaver.jar

commons-attributes-api.jar

commons-attributes-compiler.jar

commons-logging-1.1.1.jar

commons-logging.jar

org.springframework.aop-3.0.5.RELEASE.jar

org.springframework.asm-3.0.5.RELEASE.jar

org.springframework.aspects-3.0.5.RELEASE.jar

org.springframework.beans-3.0.5.RELEASE.jar

org.springframework.context-3.0.5.RELEASE.jar

org.springframework.context.support-3.0.5.RELEASE.jar

org.springframework.core-3.0.5.RELEASE.jar

org.springframework.expression-3.0.5.RELEASE.jar

org.springframework.instrument-3.0.5.RELEASE.jar

org.springframework.instrument.tomcat-3.0.5.RELEASE.jar

org.springframework.jdbc-3.0.5.RELEASE.jar

org.springframework.jms-3.0.5.RELEASE.jar

org.springframework.orm-3.0.5.RELEASE.jar

org.springframework.oxm-3.0.5.RELEASE.jar

org.springframework.test-3.0.5.RELEASE.jar

org.springframework.transaction-3.0.5.RELEASE.jar

org.springframework.web-3.0.5.RELEASE.jar

org.springframework.web.portlet-3.0.5.RELEASE.jar

org.springframework.web.servlet-3.0.5.RELEASE.jar

org.springframework.web.struts-3.0.5.RELEASE.jar

struts2-spring-plugin-2.3.8.jar

 

3.1web.xml中注册,应用程序启动时,Spring的监听器(Listener),其中context-param节点是初始化监听器的配置文件,即注册的bean从哪里获取,此处使用的是默认文件

WEB-INF

|___applicationContext.xml

 

    <!-- 指明spring配置文件在何处 -->

<!--

    <context-param>

       <param-name>contextConfigLocation</param-name>

       <param-value>classpath*:applicationContext*.xml</param-value>

    </context-param>

-->

    <listener>

       <listener-class>

           org.springframework.web.context.ContextLoaderListener

       </listener-class>

    </listener>

 

3.2编写测试用bean对象

         此处模仿MVC三层机制,Action中去调用业务辑层bean对象,此对象有Spring创建实例化,Action中只进行声明。

3.2.1编业务逻辑层的接口,遵照面向接口编程的思想,所有业务逻辑层的类,都抽象成接口。

         编写TestService接口如下

package com.jshand.ssi.service;

 

/**

 *@file_nameTestService.java

 *@project       ssi-release

 *@author     jshand

 *@createDateJun2,2013  2:08:53PM

 *@version    1.0

 *http://www.jshand.com

 *

 */

 

publicinterface TestService {

    publicvoid service();

}

 

3.2.2编写TestService的实现类TestServiceImpl代码如下:

package com.jshand.ssi.service;

 

/**

 *@file_nameTestServiceImpl.java

 *@project       ssi-release

 *@author     jshand

 *@createDateJun2,2013  2:08:53PM

 *@version    1.0

 *http://www.jshand.com

 *

 */

 

publicclass TestServiceImpl implements TestService {

   

    publicvoid service()throws Exception {

       System.out.println("this is service function ");

    }

}

 

3.3 编写Spring配置文件,并在配置文件中注册TestActionTestService实现类

    WEB-INF目录下创建aplicationContext.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:tx="http://www.springframework.org/schema/tx" 

    xmlns:context="http://www.springframework.org/schema/context" 

    xsi:schemaLocation="  

          http://www.springframework.org/schema/beans   

          http://www.springframework.org/schema/beans/spring-beans-2.0.xsd

          http://www.springframework.org/schema/aop   

          http://www.springframework.org/schema/aop/spring-aop-2.0.xsd  

          http://www.springframework.org/schema/tx   

          http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">

     

 

    <bean id="testAction" class="com.jshand.ssi.action.TestAction">

       <property name="testService" ref="testService"></property>

    </bean>

   

    <bean id="testService" class="com.jshand.ssi.service.TestServiceImpl" />

   

</beans>

 

 

3.4TestAction中声明service的应用,并添加setget方法

声明的属性名称需要跟applicationContext.xml中注入的属性的那么相同

<property name="testService">testService</property>

TestActionexecute方法中添加service的调用,testService.service();

Execute方法如下:

    public String execute() throws Exception {

       System.out.println("execute Struts2 Action ...... && actionStr = "+actionStr);

      

         testService.service();

       returnSUCCESS;

    }

 

3.5 指定Struts2Action初始化由Spring接管

由于我们添加Spring依赖的jar包是已经将struts2-spring-plugin-2.3.8.jar添加到应用的环境变量中,该jar包中包含了如下的struts-plugin.xml

<?xml version="1.0" encoding="UTF-8" ?>

<!--

/*

 * $Id: struts-plugin.xml 1221225 2011-12-20 12:22:28Z jogep $

 *

 * Licensed to the Apache Software Foundation (ASF) under one

 * or more contributor license agreements.  See the NOTICE file

 * distributed with this work for additional information

 * regarding copyright ownership.  The ASF licenses this file

 * to you under the Apache License, Version 2.0 (the

 * "License"); you may not use this file except in compliance

 * with the License.  You may obtain a copy of the License at

 *

 *  http://www.apache.org/licenses/LICENSE-2.0

 *

 * Unless required by applicable law or agreed to in writing,

 * software distributed under the License is distributed on an

 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

 * KIND, either express or implied.  See the License for the

 * specific language governing permissions and limitations

 * under the License.

 */

-->

<!DOCTYPE struts PUBLIC

    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"

    "http://struts.apache.org/dtds/struts-2.3.dtd">

   

<struts>

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

   

    <!--  Make the Spring object factory the automatic default -->

    <constant name="struts.objectFactory" value="spring" />

 

    <constant name="struts.class.reloading.watchList" value="" />

    <constant name="struts.class.reloading.acceptClasses" value="" />

    <constant name="struts.class.reloading.reloadConfig" value="false" />

 

    <package name="spring-default">

        <interceptors>

            <interceptor name="autowiring" class="com.opensymphony.xwork2.spring.interceptor.ActionAutowiringInterceptor"/>

        </interceptors>

    </package>   

</struts>

 

 

那么Struts2启动扫描扩展插件时,会把该插件装载。其中如下声明即将Sturts2的创建对象工厂指定给Spring

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

如果没有导入此jar包则,需要在Struts2配置文件中进行相应的声明和处理。此处就不进行详细的讲述,感兴趣的可以上网搜索。下面打开浏览器重新敲入刚才的请求,



 

后台打印如下:

 



 

 

打印“execute Struts2 Action ...... && actionStr = testParameter”,说明进入到Actionexecute方法,执行testService.service();时,testService对象我们在声明的时候并没有实例化,说明此处的testService对象是由Spring帮助我们创建的,至此整合SpringStruts2的工作就完成了。

4 程序搭建---整合IbatisSpringStruts2

4.1拷贝Ibatis基本的jar包到工程下的lib目录

ibatis-2.3.4.726.jar     ibatis必备的jar

commons-dbcp-1.4.jar     dbcp连接池必备的包(便于整合Spring使用)

commons-pool-1.6.jar     便于整合Spring使用同上

mysql-connector-java-5.1.18-bin.jar    mysql数据库的驱动

classes12.jar                 Oracle数据库的驱动

4.2在前面的步骤没有添加log4j的属性文件,所以,所有的log4j都无法用,下面我们想使用log4j进行控制台信息的输出,所以此处添加log4j的属性文件,文件如下,此处不过多的对log4j进行介绍,感兴趣的朋友可以上网搜索相关内容,也可以参考我之前的一片文章

http://314649444.iteye.com/blog/1874814

#

# Log4J Settings for log4j 1.2.x (via jakarta-commons-logging)

#

# The five logging levels used by Log are (in order):

#

#   1. DEBUG (the least serious)

#   2. INFO

#   3. WARN

#   4. ERROR

#   5. FATAL (the most serious)

 

 

# Set root logger level to WARN and append to stdout

log4j.rootLogger=DEBUG,stdout

 

log4j.appender.stdout=org.apache.log4j.ConsoleAppender

log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

 

# Pattern to output the caller's file name and line number.

log4j.appender.stdout.layout.ConversionPattern=%d%5p(%c:%L)-%m%n

 

# Print only messages of level ERROR or above in the package noModule.

log4j.logger.noModule=FATAL

 

# OpenSymphony Stuff

log4j.logger.com.opensymphony=INFO

log4j.logger.org.apache.struts2=INFO

 

# Spring Stuff

log4j.logger.org.springframework=INFO

 

 

 

4.3下面首先让我们在数据库中创建一张表,本文采用的是mysql数据库

建表sql如下:

CREATETABLE`person`

(

 

`personid`

VARCHAR(100)

NOT NULL,

`name`

VARCHAR(100)

NOT NULL,

`age`

VARCHAR(100)

NOT NULL,

`sex`

VARCHAR(100)

NOT NULL,

PRIMARYKEY

(`personid`)

 

)

ENGINE=MYISAM

;

4.4.1创建com.jshand.ssi.model包,并在包下创建person表对应的实体类如下:

package com.jshand.ssi.model;

 

/**

 *@file_namePerson.java

 *@project       ssi-release

 *@author     jshand

 *@createDateJun26,2013  10:32:22AM

 *@version    1.0

 *http://www.jshand.com

 *

 */

 

publicclass Person {

   

    private String personid="";

    private String name="";

    private String age="";

    private String sex="";

   

   

    public String getPersonid() {

       returnpersonid;

    }

    publicvoid setPersonid(String personid) {

       this.personid = personid;

    }

    public String getName() {

       returnname;

    }

    publicvoid setName(String name) {

       this.name = name;

    }

    public String getAge() {

       returnage;

    }

    publicvoid setAge(String age) {

       this.age = age;

    }

    public String getSex() {

       returnsex;

    }

    publicvoid setSex(String sex) {

       this.sex = sex;

    }

}

 

4.4.2添加实体类Person对应的查询语句配置文件

<?xml version="1.0" encoding="UTF-8" ?>

 

<!DOCTYPE sqlMap     

    PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"     

    "http://ibatis.apache.org/dtd/sql-map-2.dtd">

 

<sqlMap namespace="Person">

 

  <!-- Use type aliases to avoid typing the full classname every time. -->

  <typeAlias alias="Person" type="com.jshand.ssi.model.Person"/>

 

  <!-- Result maps describe the mapping between the columns returned

       from a query, and the class properties.  A result map isn't

       necessary if the columns (or aliases) match to the properties

       exactly. -->

  <resultMap id="Person" class="Person">

        <result property="personid"  column="personid" />

       <result property="name"     column="name" />

       <result property="age"  column="age" />

       <result property="sex" column="sex" />

  </resultMap>

 

  <!-- A simpler select example without the result map.  Note the

       aliases to match the properties of the target result class. -->

  <select id="selectPersonById" parameterClass="String" resultClass="Person">

   select personid, name, age, sex  from Person where personid= #id#

  </select>

  

  <!-- Insert example, using the Person parameter class -->

  <insert id="insertPerson" parameterClass="Person">

    insert into Person

        (personid, name, age, sex )

    values

        (#personid#, #name#, #age#, #sex# )

  </insert>

 

  <!-- Update example, using the Person parameter class -->

  <update id="updatePerson" parameterClass="Person">

    update Person

   set name = #name#,

       age = #age#,

       sex = #sex#,

    where personid = #personid#

  </update>

 

  <!-- Delete example, using an integer as the parameter class -->

  <delete id="deletePersonById" parameterClass="String">

    delete from Person where personid = #personid#

  </delete>

 

</sqlMap>

 

 

 

4.5 添加一个sqlMapping.properties文件(当然文件名是可以随便起的,只要Spring读取的时候保持一致即可)用于Spring读取配置连接数据库配置包括驱动类,Url、用户名、密码等,内容如下:

#MY SQL

jdbc.driverClassName=com.mysql.jdbc.Driver

jdbc.url=jdbc:mysql://127.0.0.1:3306/test

jdbc.username=root

jdbc.password=root

 

4.6配置sqlMapConfig.xml文件,并在其中注册 TB_Person.xmlSQL

 

<?xml version="1.0" encoding="UTF-8"?>

 

<!DOCTYPE sqlMapConfig PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0//EN" "http://www.ibatis.com/dtd/sql-map-config-2.dtd">

 

<sqlMapConfig>

 

    <settings cacheModelsEnabled="true" enhancementEnabled="true"

       lazyLoadingEnabled="true" errorTracingEnabled="false" maxRequests="32"

       maxSessions="10" maxTransactions="5" useStatementNamespaces="false" />

 

    <sqlMap resource="com/jshand/ssi/model/TB_Person.xml" />

   

</sqlMapConfig>

 

 

4.7 Spring配置文件中声明数据源sqlMapClient操作如下:

Spring配置文件中添加如下xml节点

   <!-- 方便查找类路径下 sqlMapping.properties 并读取到内存中-->

    <bean id="propertyConfigurer"

    class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">

       <property name="locations">

           <list>

              <value>classpath:sqlMapping.properties</value>

           </list>

       </property>

    </bean>

 

    <!-- 数据源配制 -->

    <bean id="dataSource"

       class="org.apache.commons.dbcp.BasicDataSource">

       <property name="driverClassName">

           <value>${jdbc.driverClassName}</value>

       </property>

       <property name="url">

           <value>${jdbc.url}</value>

       </property>

       <property name="username">

           <value>${jdbc.username}</value>

       </property>

       <property name="password">

           <value>${jdbc.password}</value>

       </property>

    </bean>

 

    <!-- 此处应注入ibatis配置文件,而非sqlMap文件,否则会出现“there is no statement.....异常” -->

    <bean id="sqlMapClient"

       class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">

       <property name="configLocation">

           <value>classpath:SqlMapConfig.xml</value>

       </property>

       <property name="dataSource" ref="dataSource" />

    </bean>

 

 

4.8 编写PersonDao类,并继承由Spring提供的SqlMapClientDaoSupport

实现增删改查的操作,PersonDto内容如下:

package com.jshand.ssi.dao;

 

import java.sql.SQLException;

 

import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport;

 

import com.jshand.ssi.model.Person;

 

/**

 *@file_namePersonDao.java

 *@project       ssi-release

 *@author     jshand

 *@createDateJun26,2013  11:05:55AM

 *@version    1.0

 *http://www.jshand.com

 *

 */

 

publicclass PersonDao extends SqlMapClientDaoSupport{

   

    /**

     *按照主键查询

     *@paramid

     *@return

     *@throwsSQLException

     */

    public  Object selectObjectById  (String id) throws SQLException {

       System.out.println("ID = "+id);

       return  getSqlMapClientTemplate().queryForObject("selectPersonById", id);

    }

   

    /**

     *插入一条数据

     *@paramobject

     *@return

     *@throwsSQLException

     */

    public Object insertObject (Person person) throws SQLException {

       return getSqlMapClientTemplate().insert("insertPerson", person);

    }

   

    /**

     *按主键更新一条记录

     *@paramobject

     *@return

     *@throwsSQLException

     */

    public  int updateObject (Person person) throws SQLException {

       return getSqlMapClientTemplate().update("updatePerson", person);

    }

   

    /**

     *按主键删除一条记录

     *@paramid

     *@return

     *@throwsSQLException

     */

    public  int deleteObject (String id) throws SQLException {

       return getSqlMapClientTemplate().delete("deletePerson", id);

    }

}

 

 

 

4.9 PersonDao类交给Spring管理,即在Spring配置文件中注册PersonDao

并将PersonDao注入到上面步骤的testService里面去,最后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:aop="http://www.springframework.org/schema/aop"

    xmlns:tx="http://www.springframework.org/schema/tx" 

    xmlns:context="http://www.springframework.org/schema/context" 

    xsi:schemaLocation="  

          http://www.springframework.org/schema/beans   

          http://www.springframework.org/schema/beans/spring-beans-2.0.xsd

          http://www.springframework.org/schema/aop   

          http://www.springframework.org/schema/aop/spring-aop-2.0.xsd  

          http://www.springframework.org/schema/tx   

          http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">

 

      <!-- 方便查找类路径下 sqlMapping.properties 并读取到内存中-->

    <bean id="propertyConfigurer"

        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">

       <property name="locations">

           <list>

              <value>classpath:sqlMapping.properties</value>

           </list>

       </property>

    </bean>

 

    <!-- 数据源配制 -->

    <bean id="dataSource"

       class="org.apache.commons.dbcp.BasicDataSource">

       <property name="driverClassName">

           <value>${jdbc.driverClassName}</value>

       </property>

       <property name="url">

           <value>${jdbc.url}</value>

       </property>

       <property name="username">

           <value>${jdbc.username}</value>

       </property>

       <property name="password">

           <value>${jdbc.password}</value>

       </property>

    </bean>

 

    <!-- 此处应注入ibatis配置文件,而非sqlMap文件,否则会出现“there is no statement.....异常” -->

    <bean id="sqlMapClient"

       class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">

       <property name="configLocation">

           <value>classpath:SqlMapConfig.xml</value>

       </property>

       <property name="dataSource" ref="dataSource" />

    </bean>

     

    <bean id="testAction" class="com.jshand.ssi.action.TestAction">

       <property name="testService" ref="testService"></property>

    </bean>

   

    <bean id="testService" class="com.jshand.ssi.service.TestServiceImpl" >

           <property name="personDao" ref="personDao"></property>

    </bean>

   

    <bean id="personDao" class="com.jshand.ssi.dao.PersonDao" />

   

</beans>

 

4.10下面就是看效果的时候了,我们在testService中声明一个personDao属性,名称与Spring中注册的com.jshand.ssi.dao.PersonDao类的id保持一致即可并设置settergetterpersonDao属性只需声明即可不用实例化,因为此处验证Spring托管

 

因为之前我们整合SpringStruts2的时候Struts2Action接收访问后会调用TestServiceImplservice方法,所以我们在service方法中调用PersonDao的方法插入和查询方法已验证配置是否成功。

内容如下:

package com.jshand.ssi.service;

 

import java.sql.SQLException;

 

import org.apache.log4j.Logger;

 

import com.jshand.ssi.dao.PersonDao;

import com.jshand.ssi.model.Person;

 

/**

 *@file_nameTestService.java

 *@project       ssi-release

 *@author     jshand

 *@createDateJun2,2013  2:08:53PM

 *@version    1.0

 *http://www.jshand.com

 *

 */

 

publicclass TestServiceImpl implements TestService {

    Logger logger = Logger.getLogger(TestServiceImpl.class);

    private PersonDao personDao = null;

   

    publicvoid service() throws SQLException{

       System.out.println("this is service function ");

       Person personInsert  = new Person();

       personInsert.setPersonid("001");

       personInsert.setName("Jhoon");

       personInsert.setAge("23");

       personInsert.setSex("");

       personDao.insertObject(personInsert);

      

       logger.debug("插入成功");

       Person personQuery = null;

       personQuery = (Person) personDao.selectObjectById("001");

      

       logger.debug("查询结果 Name = "+personQuery.getName()+"\t age = "+personQuery.getAge()+"\tsex = "+personQuery.getSex());

      

      

    }

 

    public PersonDao getPersonDao() {

       returnpersonDao;

    }

 

    publicvoid setPersonDao(PersonDao personDao) {

       this.personDao = personDao;

    }

}

 

 

 

 

下面我们来发布一下程序,并查看执行结果:



 
 
 

控制台打印如上,说明配置成功

5 ibatis的事物交给Spring管理,

即将数据源的事物交给Spring处理,然后Spring在一个指定的切面打开事物,切面执行完之后如果产生异常就将事物回滚,否则提交。

具体配置,在Spring配置文件添加如下xml节点,这里的切面为

public * com.jshand.ssi.services.*.*(..)  即所有Service类的所有方法

<!-- 事务的定义 -->

    <bean id="transactionManager"

        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

       <property name="dataSource">

           <ref local="dataSource" />

       </property>

    </bean>

 

    <aop:config>

       <aop:pointcut id="daoMethods" expression="execution(public * com.jshand.ssi.services.*.*(..))" />

       <aop:advisor advice-ref="txAdvice" pointcut-ref="daoMethods" />

    </aop:config>

 

    <tx:advice id="txAdvice" transaction-manager="transactionManager">

       <tx:attributes>

           <tx:method name="*" rollback-for="Exception" propagation="REQUIRED" />

       </tx:attributes>

    </tx:advice>

 

下面我们将TestServiceImpl类的service方法改造一下,因为我们之前已经插入过一条id001的对象,现在我们先插入一条002的后插入一条001的记录,因为id是主键所以在此插入的时候001是不能插入的,按照事物的一致性原则,如果成功开始事物,并且回滚的话这两条记录都应该插入不成功,下面来执行看下效果

改造后如下:

    publicvoid service() throws SQLException{

      

       Person personInsert2  = new Person();

       personInsert2.setPersonid("002");

       personInsert2.setName("Jhoon");

       personInsert2.setAge("23");

       personInsert2.setSex("");

       personDao.insertObject(personInsert2);

      

       Person personInsert1  = new Person();

       personInsert1.setPersonid("001");

       personInsert1.setName("Jhoon");

       personInsert1.setAge("23");

       personInsert1.setSex("");

       personDao.insertObject(personInsert1);

      

    }

 

执行后:后台报错如下,

execute Struts2 Action ...... && actionStr = com.jshand.ssi.action.TestAction

2013-06-26 14:30:58,670 DEBUG (java.sql.Connection:27) - {conn-100000} Connection

2013-06-26 14:30:58,701 DEBUG (java.sql.Connection:27) - {conn-100000} Preparing Statement:      insert into Person     (personid, name, age, sex )  values     (?, ?, ?, ? )  

2013-06-26 14:30:58,780 DEBUG (java.sql.PreparedStatement:27) - {pstm-100001} Executing Statement:      insert into Person     (personid, name, age, sex )  values     (?, ?, ?, ? )  

2013-06-26 14:30:58,780 DEBUG (java.sql.PreparedStatement:27) - {pstm-100001} Parameters: [002, Jhoon, 23, ]

2013-06-26 14:30:58,780 DEBUG (java.sql.PreparedStatement:27) - {pstm-100001} Types: [java.lang.String, java.lang.String, java.lang.String, java.lang.String]

2013-06-26 14:31:21,026 DEBUG (java.sql.Connection:27) - {conn-100002} Connection

2013-06-26 14:31:21,026 DEBUG (java.sql.Connection:27) - {conn-100002} Preparing Statement:      insert into Person     (personid, name, age, sex )  values     (?, ?, ?, ? )  

2013-06-26 14:31:21,041 DEBUG (java.sql.PreparedStatement:27) - {pstm-100003} Executing Statement:      insert into Person     (personid, name, age, sex )  values     (?, ?, ?, ? )  

2013-06-26 14:31:21,041 DEBUG (java.sql.PreparedStatement:27) - {pstm-100003} Parameters: [001, Jhoon, 23, ]

2013-06-26 14:31:21,058 DEBUG (java.sql.PreparedStatement:27) - {pstm-100003} Types: [java.lang.String, java.lang.String, java.lang.String, java.lang.String]

2013-06-26 14:31:21,214  INFO (org.springframework.beans.factory.xml.XmlBeanDefinitionReader:315) - Loading XML bean definitions from class path resource [org/springframework/jdbc/support/sql-error-codes.xml]

2013-06-26 14:31:21,495  INFO (org.springframework.jdbc.support.SQLErrorCodesFactory:126) - SQLErrorCodes loaded: [DB2, Derby, H2, HSQL, Informix, MS-SQL, MySQL, Oracle, PostgreSQL, Sybase]

2013-06-26 14:31:24,396 ERROR (org.apache.struts2.dispatcher.Dispatcher:38) - Exception occurred during processing request: SqlMapClient operation; SQL [];  

--- The error occurred in com/jshand/ssi/model/TB_Person.xml. 

--- The error occurred while applying a parameter map. 

--- Check the insertPerson-InlineParameterMap. 

--- Check the statement (update failed). 

--- Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '001' for key 1; nested exception is com.ibatis.common.jdbc.exception.NestedSQLException:  

--- The error occurred in com/jshand/ssi/model/TB_Person.xml. 

--- The error occurred while applying a parameter map. 

--- Check the insertPerson-InlineParameterMap. 

--- Check the statement (update failed). 

--- Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '001' for key 1

org.springframework.dao.DuplicateKeyException: SqlMapClient operation; SQL [];  

--- The error occurred in com/jshand/ssi/model/TB_Person.xml. 

--- The error occurred while applying a parameter map. 

--- Check the insertPerson-InlineParameterMap. 

--- Check the statement (update failed). 

--- Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '001' for key 1; nested exception is com.ibatis.common.jdbc.exception.NestedSQLException:  

--- The error occurred in com/jshand/ssi/model/TB_Person.xml. 

--- The error occurred while applying a parameter map. 

--- Check the insertPerson-InlineParameterMap. 

--- Check the statement (update failed). 

--- Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '001' for key 1

    at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:241)

    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72)

    at org.springframework.orm.ibatis.SqlMapClientTemplate.execute(SqlMapClientTemplate.java:203)

    at org.springframework.orm.ibatis.SqlMapClientTemplate.insert(SqlMapClientTemplate.java:364)

    at com.jshand.ssi.dao.PersonDao.insertObject(PersonDao.java:39)

    at com.jshand.ssi.service.TestServiceImpl.service(TestServiceImpl.java:38)

    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)

    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

    at java.lang.reflect.Method.invoke(Method.java:597)

    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:309)

    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)

    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)

    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)

    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)

    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89)

    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)

    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)

    at $Proxy4.service(Unknown Source)

    at com.jshand.ssi.action.TestAction.execute(TestAction.java:24)

    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)

    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

    at java.lang.reflect.Method.invoke(Method.java:597)

    at com.opensymphony.xwork2.DefaultActionInvocation.invokeAction(DefaultActionInvocation.java:446)

    at com.opensymphony.xwork2.DefaultActionInvocation.invokeActionOnly(DefaultActionInvocation.java:285)

    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)

    at org.apache.struts2.interceptor.debugging.DebuggingInterceptor.intercept(DebuggingInterceptor.java:256)

    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:242)

    at com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor.doIntercept(DefaultWorkflowInterceptor.java:176)

    at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)

    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:242)

    at com.opensymphony.xwork2.validator.ValidationInterceptor.doIntercept(ValidationInterceptor.java:265)

    at org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor.doIntercept(AnnotationValidationInterceptor.java:68)

    at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)

    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:242)

    at com.opensymphony.xwork2.interceptor.ConversionErrorInterceptor.intercept(ConversionErrorInterceptor.java:138)

    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:242)

    at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:238)

    at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)

    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:242)

    at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:238)

    at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)

    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:242)

    at com.opensymphony.xwork2.interceptor.StaticParametersInterceptor.intercept(StaticParametersInterceptor.java:191)

    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:242)

    at org.apache.struts2.interceptor.MultiselectInterceptor.intercept(MultiselectInterceptor.java:73)

    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:242)

    at org.apache.struts2.interceptor.CheckboxInterceptor.intercept(CheckboxInterceptor.java:91)

    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:242)

    at org.apache.struts2.interceptor.FileUploadInterceptor.intercept(FileUploadInterceptor.java:252)

    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:242)

    at com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor.intercept(ModelDrivenInterceptor.java:100)

    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:242)

    at com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor.intercept(ScopedModelDrivenInterceptor.java:141)

    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:242)

    at com.opensymphony.xwork2.interceptor.ChainingInterceptor.intercept(ChainingInterceptor.java:145)

    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:242)

    at com.opensymphony.xwork2.interceptor.PrepareInterceptor.doIntercept(PrepareInterceptor.java:171)

    at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)

    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:242)

    at com.opensymphony.xwork2.interceptor.I18nInterceptor.intercept(I18nInterceptor.java:176)

    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:242)

    at org.apache.struts2.interceptor.ServletConfigInterceptor.intercept(ServletConfigInterceptor.java:164)

    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:242)

    at com.opensymphony.xwork2.interceptor.AliasInterceptor.intercept(AliasInterceptor.java:193)

    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:242)

    at com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor.intercept(ExceptionMappingInterceptor.java:187)

    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:242)

    at org.apache.struts2.impl.StrutsActionProxy.execute(StrutsActionProxy.java:54)

    at org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:544)

    at org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:77)

    at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:91)

    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)

    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)

    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)

    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)

    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)

    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)

    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)

    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)

    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:861)

    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:606)

    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)

    at java.lang.Thread.run(Thread.java:619)

Caused by: com.ibatis.common.jdbc.exception.NestedSQLException:  

--- The error occurred in com/jshand/ssi/model/TB_Person.xml. 

--- The error occurred while applying a parameter map. 

--- Check the insertPerson-InlineParameterMap. 

--- Check the statement (update failed). 

--- Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '001' for key 1

    at com.ibatis.sqlmap.engine.mapping.statement.MappedStatement.executeUpdate(MappedStatement.java:107)

    at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.insert(SqlMapExecutorDelegate.java:393)

    at com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl.insert(SqlMapSessionImpl.java:82)

    at org.springframework.orm.ibatis.SqlMapClientTemplate$8.doInSqlMapClient(SqlMapClientTemplate.java:366)

    at org.springframework.orm.ibatis.SqlMapClientTemplate.execute(SqlMapClientTemplate.java:200)

    ... 82 more

Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '001' for key 1

    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)

    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)

    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)

    at java.lang.reflect.Constructor.newInstance(Constructor.java:513)

    at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)

    at com.mysql.jdbc.Util.getInstance(Util.java:386)

    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1039)

    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3609)

    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3541)

    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2002)

    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2163)

    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2624)

    at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2127)

    at com.mysql.jdbc.PreparedStatement.execute(PreparedStatement.java:1362)

    at org.apache.commons.dbcp.DelegatingPreparedStatement.execute(DelegatingPreparedStatement.java:172)

    at org.apache.commons.dbcp.DelegatingPreparedStatement.execute(DelegatingPreparedStatement.java:172)

    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)

    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

    at java.lang.reflect.Method.invoke(Method.java:597)

    at com.ibatis.common.jdbc.logging.PreparedStatementLogProxy.invoke(PreparedStatementLogProxy.java:62)

    at $Proxy7.execute(Unknown Source)

    at com.ibatis.sqlmap.engine.execution.SqlExecutor.executeUpdate(SqlExecutor.java:80)

    at com.ibatis.sqlmap.engine.mapping.statement.MappedStatement.sqlExecuteUpdate(MappedStatement.java:216)

    at com.ibatis.sqlmap.engine.mapping.statement.MappedStatement.executeUpdate(MappedStatement.java:94)

    ... 86 more

 

表中的数据还是之前插入的一条,新插入的两条都没成功。



 

下面我们将service方法再次改造一下,将001id换成003,我们DEBUG执行下

改造后的service方法如下:

        publicvoid service() throws SQLException{

      

       Person personInsert2  = new Person();

       personInsert2.setPersonid("002");

       personInsert2.setName("Jhoon");

       personInsert2.setAge("23");

       personInsert2.setSex("");

       personDao.insertObject(personInsert2);

      

       Person personInsert3  = new Person();

       personInsert3.setPersonid("003");

       personInsert3.setName("Jhoon");

       personInsert3.setAge("23");

       personInsert3.setSex("");

       personDao.insertObject(personInsert3);

      

    }

我们在Person personInsert3  = new Person();句话上打一个端点,当我们执行到这酷话的时候如果没有开启事物那么id002的记录应该是插入到数据库中的,在这里测试事物的正确与否:

开始执行:



 

说明插入002的操作已经执行这个时候我们看一下数据库:



 

发现记录中不存在002id所以证明事物成功开启未提交,当把service全部执行完毕后,在查看数据库发现,id002003的记录都已经成功插入,说明数据库事物是正确的。

 

 

总结:至此整合Struts2SpringIbatis已经结束了,需要值得注意的是,

mysql中表创建时需要选择存储引擎,本文中用的是mysql5.4提供七种种Storage Engine

,而其中MyISAM对事物的支持比较特殊,所以没有使用个,本文中建表使用   InnoDB作为存储引擎的。

 

 

 

本文中搭建好的应用可以到下面的地址下载:

http://test-jshand.googlecode.com/files/ssi-release.rar

  • 大小: 57.9 KB
  • 大小: 56.3 KB
  • 大小: 53.2 KB
  • 大小: 77.4 KB
  • 大小: 127.8 KB
  • 大小: 9.5 KB
  • 大小: 84.5 KB
分享到:
评论
4 楼 alvin2000 2017-11-14  
楼主,能发一份ssi-release.rar给我吗?alvin2000@hotmail.com

谢谢!!
3 楼 bbbmail 2016-09-10  
楼主能不能将ssi-release.rar发一份给我,学习一下,感谢
bbbmail@163.com
2 楼 Mecca_273 2013-12-31  
Mecca_273 写道
4.9过程中,在applicationContext.xml中,楼主可能不小心忘记了将sqlMapClient注入到personDao里边……

不好意思,是我之前配错了
1 楼 Mecca_273 2013-12-31  
4.9过程中,在applicationContext.xml中,楼主可能不小心忘记了将sqlMapClient注入到personDao里边……

相关推荐

Global site tag (gtag.js) - Google Analytics