Ssi的整合(Struts2+Spring+Ibatis)
Ssi的整合(Struts2+Spring+Ibatis)
1 jar包的下载
本文好用的三个框架版本分别为
struts-2.3.8 ,spring-framework-3.0.5.RELEASE,ibatis-2.3.4.726
下载地址:struts
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.3在web.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属性定义了一个字符串,并设置了set、get方法目的是讲测试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> |
主要配置xml中aciton节点,
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配置成功!接下来我们整合Spring到Struts2中
3 程序搭建---整合Spring和Struts2
同Struts2一样大多数框架的第一个步骤都是拷贝jar包到工程中,并配置环境变量 ,Spring所需要的包如下,其中struts2-spring-plugin-2.3.8.jar为整合struts2和Spring的包,当然这个包不是必须的,我们可以通过其他方法进行处理。
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.1在web.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配置文件,并在配置文件中注册TestAction和TestService实现类
在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.4在TestAction中声明service的应用,并添加set、get方法
声明的属性名称需要跟applicationContext.xml中注入的属性的那么相同
<property name="testService">testService</property>
在TestAction的execute方法中添加service的调用,testService.service();
Execute方法如下:
public String execute() throws Exception { System.out.println("execute Struts2 Action ...... && actionStr = "+actionStr);
testService.service(); returnSUCCESS; } |
3.5 指定Struts2的Action初始化由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”,说明进入到Action的execute方法,执行testService.service();时,testService对象我们在声明的时候并没有实例化,说明此处的testService对象是由Spring帮助我们创建的,至此整合Spring和Struts2的工作就完成了。
4 程序搭建---整合Ibatis到Spring、Struts2
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.xml的SQL
<?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保持一致即可并设置setter、getter。personDao属性只需声明即可不用实例化,因为此处验证Spring托管
因为之前我们整合Spring、Struts2的时候Struts2的Action接收访问后会调用TestServiceImpl的service方法,所以我们在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方法改造一下,因为我们之前已经插入过一条id为001的对象,现在我们先插入一条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方法再次改造一下,将001的id换成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();这句话上打一个端点,当我们执行到这酷话的时候如果没有开启事物那么id为002的记录应该是插入到数据库中的,在这里测试事物的正确与否:
开始执行:
说明插入002的操作已经执行这个时候我们看一下数据库:
发现记录中不存在002的id所以证明事物成功开启未提交,当把service全部执行完毕后,在查看数据库发现,id为002、003的记录都已经成功插入,说明数据库事物是正确的。
总结:至此整合Struts2、Spring、Ibatis已经结束了,需要值得注意的是,
mysql中表创建时需要选择存储引擎,本文中用的是mysql5.4提供七种种Storage Engine
,而其中MyISAM对事物的支持比较特殊,所以没有使用个,本文中建表使用 InnoDB作为存储引擎的。
本文中搭建好的应用可以到下面的地址下载: