关于这里的配置可参看 spring文档9.5.6 步骤二、准备使用环境。 建立UserDao接口,代码如下: packagecom.asm.dao; public interface UserDao { voidsave(User user); voiddelete(User user); voidupdate(User user); User get(int id); ListgetUsers(); } 建立UserDaoImp类实现UseDao接口,代码如下: packagecom.asm.dao.impl; @Transactional public class UserDaoImp implements UserDao { privateJdbcTemplate jdbcTemplate; public void setDatasouce(DataSource datasource) { jdbcTemplate= new JdbcTemplate(datasource); } public void delete(User user) { jdbcTemplate.update("delete from user where id=?", new Object[] { user.getId() }, new int[] { java.sql.Types.INTEGER }); } publicUser get(int id) { return(User) jdbcTemplate.queryForObject("select * from user where id=?", newObject[] { id }, new int[] { java.sql.Types.INTEGER }, newRowMapper() { publicObject mapRow(ResultSet rs, int arg1) throws SQLException { User user = new User(); user.setId(rs.getInt("id")); user.setName(rs.getString("name")); returnuser; } }); } @SuppressWarnings("unchecked") publicList getUsers() { return(List) jdbcTemplate.query("select * from user", new RowMapper() { publicObject mapRow(ResultSet rs, int arg1) throws SQLException { User user = new User(); user.setId(rs.getInt("id")); user.setName(rs.getString("name")); returnuser; } }); } public void save(User user) { jdbcTemplate.update("insert into user(name) values(?)", new Object[] { user.getName() }, new int[] { java.sql.Types.VARCHAR }); } public void update(User user) { jdbcTemplate.update("update user set name=? where id=?", new Object[] { user.getName(), user.getId() }, new int[] { java.sql.Types.VARCHAR, java.sql.Types.INTEGER }); } } 步骤三、把UserDaoImp纳入spring容器管理。 在beans.xml中增加对应的配置内容如下: 结合配置文件解析UserDaoImp实现类:(1)此类作为一个bean实例纳入spring容器管理, 使用setter注入方式完成对datasource的注入,实质是完成的JdbcTemplate对象的初始 化。(2)该类CRUD方法都使用了Spring容器提供的JdbcTemplate对象来简化了CRUD操作, 在spring文档的11.2.1.节对JdbcTemplate类作了较详细的介绍。(3)此类打上了 @Transactional注解,表示此类中的业务方法都会受beans.xml配置的 管理 步骤四、编写测试类 packagecom.asm.test; public class TestSJ { privateUserDao ud = (UserDao) new ClassPathXmlApplicationContext("beans.xml").getBean("userDaoImp"); public static void main(String[] args) { TestSJ sj = new TestSJ(); sj.save(); sj.delete(); } public void save() { User user = new User(); user.setName("张某某"); ud.save(user); } public void delete() { User user = new User(); user.setId(1); ud.delete(user); } //其它测试方法省略... } 说明:注意这里通过getBean获取的是UserDao接口对象,而非UserDao接口的实现类 UserDaoImp对象,因为spring的事务管理也是利用了aop技术,所以必须要面向接口,如果 想通过getBean获取它的实现类对象将会报错。 步骤五、感知事务管理。 在UserDaoImp的delete方法中增加如下代码: jdbcTemplate.update("delete from user where id=?", new Object[] { user.getId() }, new int[] { java.sql.Types.INTEGER }); inti=5/0; jdbcTemplate.update("delete from user where id=2"); spring 默认的事务管理方式:运行期异常进行事务回滚,非运行期异常不进行事务回滚。 因此增加上面的代码后,会出现ArithmeticException 运行期异常。所以当出现此异常时, delete 方法中的数据库操作都会进行回滚,因而id=1 和2 这两条记录都不会被删除。如 果把UseDaoImp 类前标记@Transactional 的注解去掉,id=1 的记录会被删除,因为失去 了spring 容器的事务管理。 小结spring 事务: (1)在beans.xml 中配置事务管理器,可以是依赖于数据源的事务管理器,也可以其它的 事务管理器(比如和JPA 集成的事务管理器等),这些事务管理器类都继承自 AbstractPlatformTransactionManager 抽象类。(2)事务管理器配置后,要想让配置的事 务管理器对某些类的事务管理起作用,可以有两种方式配置:一种是声明式配置(两种:基 于注解或基于XML),一种是编程是配置。(3)上面的一些操作,都是基于注解的声明式 事务配置:关键两点:开启基于事务的注解支持();被管理的类打上事务注解标记。(4)除了 可以在类前声明事务标记,也可以在类的方法中具体声明详细的事务标记。(5)事务标记 具有多个可选属性,具体可参文档。 3.简析事务注解属性 @Transactional 注解具有大属性: (1)传播属性propagation: 可选属性说明 REQUIRED 业务方法需要在一个事务中运行,如果方法运行时,已经处在一个事务中, 那么加入到该事务,否则自己创建一个新的事务。 REQUIRESNEW 不管是否存在事务,业务方法总会为自己发起一个新的事务,如果方法已 经运行在一个事务中,则原有事务会被挂起,新的事务会被创建,直到方 法执行结束,新事务才算结束,原先的事务才恢复执行。 SUPPORTS 如果业务方法在某个事务范围内被调用,则业务方法成为该事务的一部分。 如果业务方法在事务范围外被调用,则方法在没有事务的环境下执行 NOT_SUPPORTED 声明业务方法不需要事务,如果方法没有关联到一个事务,容器不会为它 开启事务,如果方法在一个事务中被调用,则该事务会被挂起,在该方法 调用结束后,原先的事务恢复执行 NEVER 指定业务方法绝对不能在事务范围中执行,如果业务方法在某个事务中执 行,容器会抛出例外;只有业务方法没有关联到任何事务,才能正常执行。 MANDATORY 指定业务方法只能在一个已经存在的事务中执行,业务方法不能发起自己 的事务。如果业务方法在没有事务的环境下调用,容器就会抛出例外 NESTED 如果一个活动的事务存在,它会自己产生一个单独的而且拥有多个可以回 滚的保存点的事务,然后嵌套运行在活动的事务中,实质它可以看成是一 个内部事务且具有回滚保存点,所以内部自身的事务回滚并不会引起外部 活动事务的回滚,它只是回滚到内部事务的保存点。如果没有活动事务, 则按REQIIRED 属性执行。需要注意的是此配置只对 DataSourceTransactionManager 事务管理器生效。 说明:上面多次提到业务方法,它实质就是UserDaoImp 中save 等这样的方法。但是这些方 法前会有一个设定了详细属性的@Transactional 注解。比如: @Transactional(propagation="",isolation="",noRollbackFor="") (2)隔离级别属性isolation:这个是依赖数据库系统而言,数据库系统提供四种事务隔 离级别。(具体的事务隔离级别分析在些略过,可以参看网络资源及相关文档) (3)只读属性readOnly:false--读写性、true--只读性事务. (4)超时属性timeout:int 型,以秒为单位。 (5)回滚属性:根据抛出的异常决定是否回滚事务,它包括四种可选属性。参文档 的表9.3 4.扩展:抽取dpcp 配置文件。 如果希望把dbcp的配置单独放到一个properties配置文件中去,可以使用如下做法。操作步 骤:在src的路径下建立perties文件,内容如下: driverClassName=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/sjdbc username=root password=123456 initialSize=2 maxActive=100 maxIdle=2 minIdle=1 然后把此配置读取数据源bean中去,形式如下: ...省略部分属性的获取,形式如下: ... 注意的是使用${}来获取值,必须把properties 文件引入到spring 的容器管理,因此要想 成功通过${}来获取相应的值,还应beans.xml 中增加如下内容: 而要想使用还应在beans.xml 增加名称空间: xmlns:context="/schema/context" 和schema 信息:/schema/context /schema/context/spring-context-2.5.xsd 关于这里的名称空间及schema 信息可参A2.8 节。 5.基于XML 的事务管理 步骤一、拷贝UserDaoImp 为UserDaoImp2,然后把内面所有关于事务的注解去掉 步骤二、建立beansXML.xml文件,并配置事务管理器(和六.2.步骤一完全相同)。 步骤三、配置事务 -->拦截get开头的方法,并设置只读属性 -->拦截所有方法 解析:根据txManager 事务管理器来配置一个事务通知器:txAdvice。而中的 name 属性指定方法名(可以使用通配符),其它属性就好比注解的传播属性配置(可参 六.3(1))。然后再使用切面配置一个切入点,再对这个切入点引入事务通知器。 步骤四、把UserDaoImp2 纳入spring 容器管理。即在beansXML.xml 做如下配置: 步骤五、编写写测试类,测试事务管理器是否起作用,省略... 5.总结与JDBC 的集成 (1)首先是配置好一个事务管理器(2)基于注解:一是涉及到事务的类打上事务注解标 记,二是在xml 配置文件中开启事务注解功能;基于配置:事务通知器加进apo 配置中。(3) 涉及到事务的类必须纳入spring 容器管理,事务才能起作用。(4)强调:不论是基于注解 还是基于xml 配置实现事务,都要依赖于动态代理技术。以UserDaoImp 说明,它实现了接 口,所以它的代理对象实质是一个接口对象,因而通过getBean 获取的UseDaoImp 实质上是 一个接口对象,所以特别要注意类型转换(参六.2.步骤四.说明)。(5)为了简化CRUD 操作, 我们通常会使用spring 提供的JdbcTemplate 类。 七、SSH 集成实例 1.分析实例及准备环境 建立spring_06_SSH 项目,此项目主要演示struts1.x、hibernate、spring 的集成。集成 前的一个比较关键的因素是搭建好环境,这一步要求我们对集成的框架所用到的jar 包有比 较清楚的认识。下面列表展示了三个框架所用到的jar 包。 hibernate3.3 所用到的jar 包: antlr-2.7.6.jar 开源语法分析生成器(lib\required) commons-collections-3.1.jar Commons 集合类库,与连接池有关(lib\required) dom4j-1.6.1.jar xml 解析类库(lib\required) javassist-3.9.0.GA.jar 分析,编辑和创建java 字节码类库(lib\required) jta-1.1.jar 事务处理api (lib\required) slf4j-api-1.5.8.jar 日志处理(lib\required)-->用log4j 实现 hibernate3.jar 核心 ehcache-1.2.3.jar 二级缓存(lib\optional\ehcache) Spring2.5 安装包所用的jar 包: dist\spring.jar lib\aspectj\aspectjweaver.jar、aspectjrt.jar lib\cglib\cgligb-nodep-2.1_3.jar lib\j2ee\common-annotations.jar lib\jakarta-commons\commons-logging.jar 、commons-dbcp.jar、commons-pool.jar dist\modules\spring-webmvc-struts.jar lib\log4j\log4j-1.2.15.jar 供srping 与hibernate 使用的日志记录jar 包lib\slf4j\ slf4j-log4j12-1.5.0.jar 日志转换jar 包,实现把log4j.jar 包适配到slf4j 标准。 struts1.10 所用到的jar 包 导入lib 目录下的所有jar 包。但为了避免jar 包冲突,不要导入antlr.jar(hibernate 已经导入) jar 包说明:绿色字样是框架所需的一些基本包。