1.开发实验环境
导入相关开发库:
aspectjrt.jar
aspectjweaver.jar
cglib-nodep-2.1_3.jar4
common-annotations.jar
commons-dbcp.jar
commons-logging.jar
commons-pool.jar
dom4j-1.6.1.jar
jaxen-1.1-beta-6.jar
mysql-connector-java-5.0.8-bin.jar
spring.jar
2.配置数据源
beans.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:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
<context:property-placeholder location="classpath:jdbc.properties"/>
<!-- commons-dbcp.jar -->
<bean id="dataSource" destroy-method="close"
class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="initialSize" value="${jdbc.initialSize}" />
<property name="maxActive" value="${jdbc.maxActive}" />
<property name="maxIdle" value="${jdbc.maxIdle}" />
<property name="minIdle" value="${jdbc.minIdle}" />
</bean>
<!-- 自动扫描cn.itcast包下的 所有Bean-->
<context:component-scan base-package="cn.itcast"/>
<!-- 依赖注入所有对象 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg index="0" ref="dataSource"></constructor-arg>
</bean>
<context:annotation-config></context:annotation-config>
</beans>
jdbc.properties
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc\:mysql\://localhost\:3306/itcast?useUnicode\=true&charsetEncoding\=UTF-8
jdbc.username=root
jdbc.password=lisai
jdbc.initialSize=1
jdbc.maxActive=500
jdbc.maxIdle=2
jdbc.minIdle=1
PersonDaoImpl.java
package cn.itcast.dao.impl;
import java.util.List;
import javax.annotation.Resource;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import cn.itcast.dao.PersonDao;
import cn.itcast.domain.Person;
@Transactional @Repository
public class PersonDaoImpl implements PersonDao {
@Resource private JdbcTemplate jdbcTemplate;
/* (non-Javadoc)
* @see cn.itcast.dao.impl.PersonDao#add(cn.itcast.domain.Person)
*/
public void add(Person person){
jdbcTemplate.update("insert into tb_person(name) values(?) ", new Object[]{person.getName()}, new int[]{java.sql.Types.VARCHAR});
}
/* (non-Javadoc)
* @see cn.itcast.dao.impl.PersonDao#update(cn.itcast.domain.Person)
*/
public void update(Person person){
jdbcTemplate.update("update tb_person set name = ? where id = ? ", new Object[]{person.getName(),person.getId()}, new int[]{java.sql.Types.VARCHAR,java.sql.Types.INTEGER});
}
/* (non-Javadoc)
* @see cn.itcast.dao.impl.PersonDao#findByID(java.lang.Integer)
*/
public Person findByID(Integer id){
return (Person) jdbcTemplate.queryForObject("select id,name from tb_person where id=?", new Object[]{id},new int[]{java.sql.Types.INTEGER},new PersonRowMapper());
}
/* (non-Javadoc)
* @see cn.itcast.dao.impl.PersonDao#findAll()
*/
@SuppressWarnings("unchecked")
public List<Person> findAll(){
return (List<Person>)jdbcTemplate.query("select id,name from tb_person",new PersonRowMapper());
}
/* (non-Javadoc)
* @see cn.itcast.dao.impl.PersonDao#delete(java.lang.Integer)
*/
public void delete(Integer id){
jdbcTemplate.update("delete from tb_person where id = ? ", new Object[]{id}, new int[]{java.sql.Types.INTEGER});
}
}
PersonRowMapper.java
package cn.itcast.dao.impl;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.springframework.jdbc.core.RowMapper;
import cn.itcast.domain.Person;
public class PersonRowMapper implements RowMapper {
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
Person person = new Person();
person.setId(rs.getInt("id"));
person.setName(rs.getString("name"));
return person;
}
}
Person.java
package cn.itcast.domain;
public class Person {
private Integer id;
private String name;
public Person(String name){
this.name = name;
}
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 Person() {
super();
// TODO Auto-generated constructor stub
}
public Person(Integer id, String name) {
super();
this.id = id;
this.name = name;
}
}
CREATE TABLE tb_person (
id int(12) NOT NULL auto_increment,
name varchar(20) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
测试代码:JdbcSpringTest.java
package junit.test;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import cn.itcast.dao.PersonDao;
import cn.itcast.domain.Person;
public class JdbcSpringTest {
private static PersonDao personDao;
@BeforeClass
public static void setUpBeforeClass() throws Exception{
ApplicationContext ctx=new ClassPathXmlApplicationContext("beans.xml");
personDao=(PersonDao) ctx.getBean("personDaoImpl");
}
@Test
public void testAdd() {
personDao.add(new Person("mmmn"));
System.out.println("OK");
}
@Test
public void testUpdate() {
Person person = new Person(4, "token");
personDao.update(person);
System.out.println("Ok");
}
@Test
public void testFindByID() {
System.out.println(personDao.findByID(4).getName());
}
@Test
public void testFindAll() {
for(Person person:personDao.findAll()){
System.out.println(person.getName());
}
}
@Test
public void testDelete() {
personDao.delete(4);
}
}
测试结果:通过查看数据库数据结果一致.
//~
3.注解方式配置事务
a. beans.xml的修改
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
b. 引入事务管理的命名空间
xmlns:tx="http://www.springframework.org/schema/tx"
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
c. 采用注解方式@Transactional
<tx:annotation-driven transaction-manager="txManager"/>
@Transactional 注解是用来指定接口、类或方法必须拥有事务语义的元数据。 如:“当一个方法开始调用时就开启一个新的只读事务,并停止掉任何现存的事务”。
默认的 @Transactional 设置如下:
事务传播设置是 PROPAGATION_REQUIRED
事务隔离级别是 ISOLATION_DEFAULT
事务是 读/写
事务超时默认是依赖于事务系统的,或者事务超时没有被支持。
任何 RuntimeException 将触发事务回滚,但是任何 checked Exception 将不触发事务回滚
4.声明实事务管理(基于XML配置文件)
<!-- 开启事务 -->
<aop:config>
<aop:pointcut expression="execution(* cn.itcast.dao..*.*(..))" id="transactionPointcut"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="transactionPointcut"/>
</aop:config>
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="*" read-only="true" propagation="NOT_SUPPORTED"/>
</tx:attributes>
</tx:advice>
Spring的声明式事务管理是通过Spring AOP实现的,因为事务方面的代码与Spring绑定并以一种样板式风格使用, 不过尽管如此,你一般并不需要理解AOP概念就可以有效地使用Spirng的声明式事务管理。
从考虑EJB CMT和Spring声明式事务管理的相似以及不同之处出发是很有益的。它们的基本方法是相似的: 都可以指定事务管理到单独的方法;如果需要可以在事务上下文调用 setRollbackOnly() 方法。不同之处在于:
不像EJB CMT绑定在JTA上,Spring声明式事务管理可以在任何环境下使用。只需更改配置文件, 它就可以和JDBC、JDO、Hibernate或其他的事务机制一起工作。
Spring的声明式事务管理可以被应用到任何类(以及那个类的实例)上,不仅仅是像EJB那样的特殊类。
Spring提供了声明式的 回滚规则:EJB没有对应的特性,我们将在下面讨论。回滚可以声明式的控制,不仅仅是编程式的。
Spring允许你通过AOP定制事务行为。例如,如果需要,你可以在事务回滚中插入定制的行为。 你也可以增加任意的通知,就象事务通知一样。使用EJB CMT,除了使用setRollbackOnly(),你没有办法能够影响容器的事务管理。
Spring不提供高端应用服务器提供的跨越远程调用的事务上下文传播。如果你需要这些特性,我们推荐你使用EJB。 然而,不要轻易使用这些特性。因为通常我们并不希望事务跨越远程调用。
TransactionProxyFactoryBean在哪儿?
Spring2.0及以后的版本中声明式事务的配置与之前的版本有相当大的不同。主要差异在于不再需要配置TransactionProxyFactoryBean了。
Spring2.0之前的旧版本风格的配置仍然是有效的;你可以简单地认为新的<tx:tags/>替你定义了TransactionProxyFactoryBean。
回滚规则的概念比较重要:它使我们能够指定什么样的异常(和throwable)将导致自动回滚。我们在配置文件中声明式地指定,无须在Java代码中。同时,我们仍旧可以通过调用 TransactionStatus 的 setRollbackOnly() 方法编程式地回滚当前事务。通常,我们定义一条规则, 声明 MyApplicationException 必须总是导致事务回滚。 这种方式带来了显著的好处,它使你的业务对象不必依赖于事务设施。典型的例子是你不必在代码中导入Spring API,事务等。
对EJB来说,默认的行为是EJB容器在遇到 系统异常(通常指运行时异常)时自动回滚当前事务。 EJB CMT遇到 应用异常(例如,除了 java.rmi.RemoteException 外别的checked exception)时并不会自动回滚。 默认式Spring处理声明式事务管理的规则遵守EJB习惯(只在遇到unchecked exceptions时自动回滚),但通常定制这条规则会更有用。
end.......