1. 程式人生 > >Spring(3)之 Spring事務管理

Spring(3)之 Spring事務管理

Spring AOP

Spring JDBC

Spring 使用 AOP對事務進行實現

Spring 宣告式事務實現:

  1. XML方式
    XML檔案中配置資料庫連線池、事務管理器、事務增強、aop:事務管理器中 ref引用 dataSource資料來源;事務增強中 transaction-manager用到事務管理器,並且設定哪些方法、是否只讀;aop中:配置切入點表示式並通過pointcut-ref引入、advice-ref引入事務通知
  2. 註解方式
    設定註解方式實現事務:
    <tx:annotation-driven transaction-manager=“txManager”/>
    Service層的類或者方法上使用@Transactional註解:
    若放在方法上,則對於此方法新增事務
    若放在類上,則對於此類中全部方法都有事務

程式中事務的控制:使用者——》action——》service——》dao
(一個程式執行成功,service要是成功,dao寫入資料庫成功)
事務控制放在service層

事務管理:

  1. 程式設計式事務 conn.setAutoCommit(false)
  2. Spring對於事務管理,宣告式事務
    配置事務,AOP

0 .eg: 沒有事務操作時
模擬: 呼叫Dao,兩次操作,一次成功,一次失敗,沒有事務時沒有回滾,即使失敗的操作也會對資料庫產生影響
開發步驟:


1.後臺:資料庫、service、dao、entity
2.Dao使用 JdbcTemplate
3.物件的建立使用 IOC容器

0.1 UserDao.java

public class UserDao{
	private JdbcTemplate jdbcTemplate;
	public void setJdbcTemplate(JdbcTemplate jdbcTemplate){
		this.jdbcTemplate=jdbcTemplate;
	}
	public void save(User user) throws Exception{ //新增方法
		String sql="insert into user(username,age) values(?,?)";
		jdbcTemplate.update(sql,new Object[]{user.getUsername(),user.getAge()});
	}
}

0.2 UserService.java

public class UserService{
	private UserDao userDao;
	public void setUserDao(UserDao userDao){
		this.userDao=userDao;
	}
	public void save(User user) throws Exception{
		userDao.save(user);
		//出異常
		int i=1/0;
		userDao.save(user);
	}
}

0.3 bean.xml

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       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/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!-- 建立連線池物件 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    	<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
    	<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"></property>
    	<property name="user" value="root"></property>
    	<property name="password" value="12345"></property>
    </bean>
    <!-- JdbcTemplate工具類 -->
    <!-- 建立jdbcTemplate物件(將dataSource注入) -->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    	<property name="dataSource" ref="dataSource"></property>
    </bean>
     <!-- dao -->
     <!-- 建立UserDao物件(將jdbcTemplate注入) -->
    <bean id="userDao" class="com.asd.spring.UserDao">
    	<property name="dataSource" ref="dataSource"></property>
    </bean>
    <!-- service-->
    <bean id="userService" class="com.asd.spring.UserService">
    	<property name="userDao" ref="userDao"></property>
    </bean>
    
</beans>

Test.java

public class Test{
	ApplicationContext applicationContext=new ClassPathXmlApplicationContext("bean.xml");
	@Test
	public void test() throws Exception{
		UserService userService=(UserService)applicationContext.getBean("userService");
		User user=new User();
		user.setUsername("測試");
		user.setAge(9);
		userService.save(user);
	}
}

一、 XML方式配置事務

bean.xml中:配置事務管理器、事務增強、aop:事務管理器中 ref引用 dataSource資料來源;事務增強中 transaction-manager用到事務管理器,並且設定哪些方法、是否只讀;aop中:配置切入點表示式並通過pointcut-ref引入、advice-ref引入事務通知。)

1.1 UserDao.java

public class UserDao{
	private JdbcTemplate jdbcTemplate;
	public void setJdbcTemplate(JdbcTemplate jdbcTemplate){
		this.jdbcTemplate=jdbcTemplate;
	}
	public void save(User user) throws Exception{ //新增方法
		String sql="insert into user(username,age) values(?,?)";
		jdbcTemplate.update(sql,new Object[]{user.getUsername(),user.getAge()});
	}
}

1.2 UserService.java

public class UserService{
	private UserDao userDao;
	public void setUserDao(UserDao userDao){
		this.userDao=userDao;
	}
	public void save(User user) throws Exception{
		userDao.save(user);
		//出異常
		int i=1/0;
		userDao.save(user);
	}
}

1.3 bean.xml
(配置事務管理器、事務增強、aop:事務管理器中 ref引用 dataSource資料庫連線池;事務增強中 transaction-manager用到事務管理器,並且設定哪些方法、是否只讀;aop中:配置切入點表示式並通過pointcut-ref引入、advice-ref引入事務通知。)

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       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/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!-- 建立連線池物件 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    	<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
    	<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"></property>
    	<property name="user" value="root"></property>
    	<property name="password" value="12345"></property>
    </bean>
    <!-- JdbcTemplate工具類 -->
    <!-- 建立jdbcTemplate物件(將dataSource注入) -->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    	<property name="dataSource" ref="dataSource"></property>
    </bean>
     <!-- dao -->
     <!-- 建立UserDao物件(將jdbcTemplate注入) -->
    <bean id="userDao" class="com.asd.spring.UserDao">
    	<property name="dataSource" ref="dataSource"></property>
    </bean>
    <!-- service-->
    <bean id="userService" class="com.asd.spring.UserService">
    	<property name="userDao" ref="userDao"></property>
    </bean>
    
    
    <!-- Spring對於事務的管理 -->
    <!-- 1.配置事務管理器 -->
    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    	<property name="dataSource" ref="dataSource"></property>
    </bean>
    <!-- 2.配置事務管理增強(即如何管理) -->
    <tx:advice id="txAdvice" transaction-manager="txManager">
    	<tx:attributes>
    		<tx:method name="get" read-only="true"/>
    		<tx:method name="*" read-only="false"/>
    	</tx:attributes>
    </tx:advice>
    <!-- 3.配置AOP,攔截什麼方法(切入點表示式)+增強 -->
    <aop:config>
    	<aop:pointcut id="pt" expression="execution(* com.asd.spring.UserService.save(..))"/>
    	<aop:advisor advice-ref="txAdvice" pointcut-ref="pt"/>
    </aop:config>
    
</beans>

Test.java

public class Test{
	ApplicationContext applicationContext=new ClassPathXmlApplicationContext("bean.xml");
	@Test
	public void test() throws Exception{
		UserService userService=(UserService)applicationContext.getBean("userService");
		User user=new User();
		user.setUsername("測試2");
		user.setAge(9);
		userService.save(user);
	}
}

二、 註解方式實現宣告式事務

bean.xml中:開啟註解掃描、建立資料庫連線池 dataSource、配置事務管理器 txManager、配置事務註解:配置事務管理器時 ref引用 dataSource; 配置事務註解時 transaction-manager使用 txManager。UserService.java中:使用@Service、@Resource註解將 userDao注入進來,此時不需要用 setUserDao方法注入了;在方法或者類上使用@Transactional來新增事務。UserDao.java中:使用@Repository、@Resource註解將 jdbcTemplate注入進來,此時不需要用 setJdbcTemplate進行注入了。)
2.1 UserDao.java
(使用@Repository、@Resource註解將 jdbcTemplate注入進來,此時不需要用 setJdbcTemplate進行注入了。)

@Repository
public class UserDao{
	@Resource
	private JdbcTemplate jdbcTemplate;
	public void save(User user) throws Exception{ //新增方法
		String sql="insert into user(username,age) values(?,?)";
		jdbcTemplate.update(sql,new Object[]{user.getUsername(),user.getAge()});
	}
}

2.2 UserService.java
(使用@Service、@Resource註解將 userDao注入進來,此時不需要用 setUserDao方法注入了;在方法或者類上使用@Transactional來新增事務。)

@Service
@Transactional
public class UserService{
	@Resource
	private UserDao userDao;
	// @Transactional
	public void save(User user) throws Exception{
		userDao.save(user);
		//出異常
		int i=1/0;
		userDao.save(user);
	}
}

2.3 bean.xml
(配置事務管理器、事務增強、aop:事務管理器中 ref引用 dataSource資料來源;事務增強中 transaction-manager用到事務管理器,並且設定哪些方法、是否只讀;aop中:配置切入點表示式並通過pointcut-ref引入、advice-ref引入事務通知。)

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       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/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!-- 開啟註解掃描 -->
    <context:component-scan base-package="com.asd"></context:component-scan>
    
    <!-- 建立連線池物件 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    	<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
    	<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"></property>
    	<property name="user" value="root"></property>
    	<property name="password" value="12345"></property>
    </bean>
    <!-- JdbcTemplate工具類 -->
    <!-- 建立jdbcTemplate物件(將dataSource注入) -->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    	<property name="dataSource" ref="dataSource"></property>
    </bean>
    
    <!-- Spring對於事務的管理 -->
    <!-- 1.配置事務管理器 -->
    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    	<property name="dataSource" ref="dataSource"></property>
    </bean>
    <!-- 2.註解方式實現事務,指定註解方式實現事務 -->
    <tx:annotation-driven transaction-manager="txManager"/>
        
</beans>

Test.java

public class Test{
	ApplicationContext applicationContext=new ClassPathXmlApplicationContext("bean.xml");
	@Test
	public void test() throws Exception{
		UserService userService=(UserService)applicationContext.getBean("userService");
		User user=new User();
		user.setUsername("測試3");
		user.setAge(9);
		userService.save(user);
	}
}