Spring----JDBC,transaction

JDBC模板 

xml中配置事务管理,aop的约束

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

引入jar包(声明式事务管理用到aop的jar)后,

在xml中配置连接池(内置的连接池,DBCP,C3P0) 和JDBC模板

<!-- 配置Spring的jdbc模板================================================= -->
	<bean id="JdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
		<property name="dataSource" ref="DataSource"></property>
	</bean>
	
<!-- 配置Spring内置连接池============================== -->
	<!-- 
		<bean id="DataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
			属性注入
			<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
			<property name="url" value="jdbc:mysql:///spring4_day03?useSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8"></property>
			<property name="username" value="root"></property>
			<property name="password" value="root"></property>
		</bean> 
	-->
	
	<!-- 配置DBCP连接池=================================== -->
	<!-- 
		<bean id="DataSource" class="org.apache.commons.dbcp.BasicDataSource">
			<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
			<property name="url" value="jdbc:mysql:///spring4_day03?useSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8"></property>
			<property name="username" value="root"></property>
			<property name="password" value="root"></property>
		</bean> 
	-->
	
	<!-- 引入属性文件======================================= -->
	<!-- 通过context标签引入 -->
	<context:property-placeholder location="classpath:jdbc.properties"/>
			
	<!-- 配置c3p0连接池========================================== -->
	<bean id="DataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<!-- 直接写
			<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
			<property name="jdbcUrl" value="jdbc:mysql:///spring4_day03?useSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8"></property>
			<property name="user" value="root"></property>
			<property name="password" value="root"></property> 
		-->
		<!-- 借用引入的属性文件 -->
		<property name="driverClass" value="${jdbc.driverClass}"></property>
		<property name="jdbcUrl" value="${jdbc.url}"></property>
		<property name="user" value="${jdbc.username}"></property>
		<property name="password" value="${jdbc.password}"></property> 
	</bean>

jdbc属性文件

jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///spring4_day03?useSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8
jdbc.username=root
jdbc.password=root 

使用单元测试,测试JDBC模板

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class JdbcDemo2 {

	@Resource(name="JdbcTemplate")
	private JdbcTemplate jdbcTemplate;
	
	@Test
	//保存操作
	public void test1(){
		jdbcTemplate.update("insert into account values(null,?,?)","张如花",400d);
	}
	
	@Test
	//修改操作
	public void test2(){
		jdbcTemplate.update("update account set name = ?,money = ? where id = ?","张如花",500d,6);
	}
	
	@Test
	//删除操作
	public void test3(){
		jdbcTemplate.update("delete from account  where id = ?",7);
	}
	
	@Test
	//查询操作
	public void test4(){
		String name = jdbcTemplate.queryForObject("select name from account where id = ?",String.class,6);
		System.out.println(name);
	}
	
	@Test
	//统计查询
	public void test5(){
		Long count = jdbcTemplate.queryForObject("select count(*) from account ",Long.class);
		System.out.println(count);
	}
	
	@Test
	//封装到对象中
	public void test6(){
		Account account = jdbcTemplate.queryForObject("select *from account where id = ? ",new MyRowMapper(),6);
		System.out.println(account);
	}
	
	class MyRowMapper implements RowMapper<Account>{
		@Override
		public Account mapRow(ResultSet rs, int rowNum) throws SQLException {
			Account account = new Account(rs.getInt("id"),rs.getString("name"), rs.getDouble("money"));
			return account;
		}
	}
}



class Account {
	private Integer id;
	private String name;
	private Double money;

	public Account() {
	}
	public Account(Integer id, String name, Double money) {
		super();
		this.id = id;
		this.name = name;
		this.money = money;
	}
	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 getMoney() {
		return money;
	}
	public void setMoney(Double money) {
		this.money = money;
	}
	@Override
	public String toString() {
		return "Account [id=" + id + ", name=" + name + ", money=" + money + "]";
	}
}

事务管理

public interface AccountDao {
	public void outMoney(String from,Double money);
	public void inMoney(String to,Double money);
}

public class AccountDaoImpl  extends JdbcDaoSupport implements AccountDao{

	@Override
	public void outMoney(String from, Double money) {
		this.getJdbcTemplate().update("update account set money = money - ? where name = ?",money,from);
	}

	@Override
	public void inMoney(String to, Double money) {
		
		this.getJdbcTemplate().update("update account set money = money + ? where name = ?",money,to);
	}
}

public interface AccountService {
	public void transfer(String from,String to,Double money);
}

public class AccountServiceImpl implements AccountService {

	private AccountDao accountDao;
	
	public void setAccountDao(AccountDao accountDao) {
		this.accountDao = accountDao;
	}
	
	@Override
	public void transfer( String from,  String to,  Double money) {
			accountDao.outMoney(from, money);
                        //设置除0异常
			int d = 1/0;
			accountDao.inMoney(to, money);
		
	}

}

一个转账的实例,dao中完成对数据库的操作

  dao实现类继承JdbcDaoSupport,JdbcDaoSupport源码中

只要传入一个 连接池,就会自动创建JdbcTemplate,而且JdbcDaoSupport这个类中都有相应的set方法,所以直接在xml中注入连接池就行。

        <!-- 配置连接池 -->
	<!-- 通过context标签引入属性文件 -->
	<context:property-placeholder location="classpath:jdbc.properties"/>
	<!-- 配置c3p0连接池 -->
	<bean id="DataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<property name="driverClass" value="${jdbc.driverClass}"></property>
		<property name="jdbcUrl" value="${jdbc.url}"></property>
		<property name="user" value="${jdbc.username}"></property>
		<property name="password" value="${jdbc.password}"></property> 
	</bean>

        <!-- 配置service和dao -->
	<bean id="AccountDao" class="txDemo1_编程式.AccountDaoImpl">
		<property name="dataSource" ref="DataSource"></property>
	</bean>
	<bean id="AccountService" class="txDemo1_编程式.AccountServiceImpl">
		<property name="accountDao" ref="AccountDao"></property>
	</bean>

 没有进行事务管理时,进行如下测试,由于AccountServiceImpl 中设置了除零异常,收账的没收到,转账的扣钱了

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:tx1.xml")
public class SpringDemo1 {

	@Resource(name="AccountService")
	private AccountService accountService;

	@Test
	public void test1(){
		accountService.transfer("aaa", "bbb", 700d);
	}

 编程式

在xml中配置事务管理器和事务管理的模板

DataSourceTransactionManager底层使用jdbc管理事务

	<!-- 配置平台事务管理器==================== -->
	<bean id="TransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="DataSource"></property>
	</bean>
	<!-- 配置事务管理的模板 -->
	<bean id="TransactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
		<property name="transactionManager" ref="TransactionManager"></property>
	</bean>

在AccountServiceImpl中设置一个transactionTemplate属性,执行它的excute方法

将可能发生异常的代码写到内部类重写的方法中就可以解决问题

public class AccountServiceImpl implements AccountService {
	//注入dao
	private AccountDao accountDao;
	//注入事务管理的模板
	private TransactionTemplate transactionTemplate;
	
	@Override
	public void transfer(final String from,final String to,final Double money) {

		transactionTemplate.execute(new TransactionCallbackWithoutResult() {
			
			@Override
			protected void doInTransactionWithoutResult(TransactionStatus arg0) {
				
				accountDao.outMoney(from, money);
				int i = 1 / 0;
				accountDao.inMoney(to, money);
			}
		});
	}
	
	public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
		this.transactionTemplate = transactionTemplate;
	}

	public void setAccountDao(AccountDao accountDao){
		this.accountDao = accountDao;
	}
}

声明式

xml方式(aop)

       配置事务管理器

<!-- 配置事务管理器 -->
	<bean id="TransactonManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="DataSource"></property>
	</bean>
        <!-- 配置事务的增强 -->
	<tx:advice id="txAdvice" transaction-manager="TransactonManager">
		<tx:attributes>
			<tx:method name="transfer" propagation="REQUIRED"/>
		</tx:attributes>
	</tx:advice>
	<!-- aop的配置 -->
	<aop:config>
		<aop:pointcut expression="execution(* txDemo2_声明式_xml.AccountServiceImpl.*(..))" id="pointcut1"/>
		<aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut1"/>
	</aop:config>

 其中,propagation设置的是事务的传播行为

 

 Spring中提供了七种事务的传播行为:

             保证多个操作在同一个事务中

         PROPAGATION_REQUIRED     默认值,如果A中有事务,使用A中的事务,如果A没有,创建一个新的事务,将操作包含进来

          PROPAGATION_SUPPORTS    :支持事务,如果A中有事务,使用A中的事务。如果A没有事务,不使用事务。

          PROPAGATION_MANDATORY   :如果A中有事务,使用A中的事务。如果A没有事务,抛出异常。

 

             保证多个操作不在同一个事务中

              PROPAGATION_REQUIRES_NEW    如果A中有事务,将A的事务挂起(暂停),创建新事务,只包含自身操作。如果A中没有事务,创建一个新事务,包含自身操作。

              PROPAGATION_NOT_SUPPORTED :如果A中有事务,将A的事务挂起。不使用事务管理。

              PROPAGATION_NEVER          :如果A中有事务,报异常。

 

                       嵌套式事务

              PROPAGATION_NESTED       嵌套事务,如果A中有事务,按照A的事务执行,执行完成后,设置一个保存点,执行B中的操作,如果没有异常,执行通过,如果有异常,可以选择回滚到最初始位置,也可以回滚到保存点。

注解方式

        配置事务管理器

	<!-- 配置事务管理器 -->
	<bean id="TransactonManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="DataSource"></property>
	</bean>

                  开启注解事务

        <!-- 开启注解事务 -->
	<tx:annotation-driven transaction-manager="TransactonManager"/>

                在需要目标类(AccountServiceImpl )上加一个@Transactional注解,这个注解上也可以设置传播行为等属性

@Transactional
public class AccountServiceImpl implements AccountService {

	//注入dao
	private AccountDao accountDao;
	
	@Override
	public void transfer(String from, String to, Double money) {
					
				accountDao.outMoney(from, money);
				int i = 1 / 0;
				accountDao.inMoney(to, money);
	}
	
	public void setAccountDao(AccountDao accountDao){
		this.accountDao = accountDao;
	}
}

猜你喜欢

转载自blog.csdn.net/qq_40605913/article/details/82082352
今日推荐