spring+mybatis之声明式事务管理初识(小实例)
前幾篇的文章都只是初步學習spring和mybatis框架,所寫的實例也都非常簡單,所進行的數據訪問控制也都很簡單,沒有加入事務管理.這篇文章將初步接觸事務管理.
1.事務管理
理解事務管理之前,先通過一個例子講一下什么是事務管理:取錢。?
比如你去ATM機取1000塊錢,大體有兩個步驟:首先輸入密碼金額,銀行卡扣掉1000元錢;然后ATM出1000元錢。這兩個步驟必須是要么都執行要么都不執行。如果銀行卡扣除了1000塊但是ATM出錢失敗的話,你將會損失1000元;如果銀行卡扣錢失敗但是ATM卻出了1000塊,那么銀行將損失1000元。所以,如果一個步驟成功另一個步驟失敗對雙方都不是好事,如果不管哪一個步驟失敗了以后,整個取錢過程都能回滾,也就是完全取消所有操作的話,這對雙方都是極好的。?事務就是用來解決類似問題的。事務是一系列的動作,它們綜合在一起才是一個完整的工作單元,這些動作必須全部完成,如果有一個失敗的話,那么事務就會回滾到最開始的狀態,仿佛什么都沒發生過一樣。?在企業級應用程序開發中,事務管理必不可少的技術,用來確保數據的完整性和一致性。?
事務有四個特性:ACID
- 原子性(Atomicity):事務是一個原子操作,由一系列動作組成。事務的原子性確保動作要么全部完成,要么完全不起作用。
- 一致性(Consistency):一旦事務完成(不管成功還是失敗),系統必須確保它所建模的業務處于一致的狀態,而不會是部分完成部分失敗。在現實中的數據不應該被破壞。
- 隔離性(Isolation):可能有許多事務會同時處理相同的數據,因此每個事務都應該與其他事務隔離開來,防止數據損壞。
- 持久性(Durability):一旦事務完成,無論發生什么系統錯誤,它的結果都不應該受到影響,這樣就能從任何系統崩潰中恢復過來。通常情況下,事務的結果被寫到持久化存儲器中。
2.小實例工程
(1)工程目錄:
(2)建立數據庫transaction,建立一張user表:
(3)建立User.java類:
package com.gnc.model;public class User {private String id;private String name;public String getId() {return id;}public void setId(String id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public User() {}public User(String id, String name) {super();this.id = id;this.name = name;} }
(4)建立UserDao.java數據訪問接口:
package com.gnc.dao;import java.util.List; import java.util.Map;import com.gnc.model.User;public interface UserDao {public int countAll();public void insertUser(User user);public List<User> getAllUser();public User getById(String id);public void deleteUser(String id);public void updateUser(Map<String,Object> map);}
(5)建立實現UserDaoImpl.java類:
package com.gnc.daoImpl;import java.util.List; import java.util.Map;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service;import com.gnc.dao.UserDao; import com.gnc.mapper.UserMapper; import com.gnc.model.User;@Service("userDao") public class UserDaoImpl implements UserDao {@Autowiredprivate UserMapper userMapper;public int countAll() {return this.userMapper.countAll();}@Overridepublic void insertUser(User user) {this.userMapper.insertUser(user);}@Overridepublic List<User> getAllUser() {return this.userMapper.getAllUser();}@Overridepublic User getById(String id) {return this.userMapper.getById(id);}@Overridepublic void deleteUser(String id) {this.userMapper.deleteUser(id);}@Overridepublic void updateUser(Map<String, Object> map) {this.userMapper.updateUser(map);}}
(6)建立UserDao接口訪問映射文件UserDaoMapper.xml:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.gnc.mapper.UserMapper"><parameterMap id="parameterMapUser" type="com.gnc.model.User" ><parameter property="id" /><parameter property="name" /></parameterMap><resultMap id="resultMapUser" type="com.gnc.model.User" ><result property="id" column="id" /><result property="name" column="name" /></resultMap><insert id="insertUser" parameterMap="parameterMapUser">INSERT INTO user(id,name)VALUES(?,?)</insert><select id="countAll" resultType="int">select count(*) c from user;</select><select id="getAllUser" resultMap="resultMapUser">SELECT * FROM user</select><select id="getById" parameterType="String" resultMap="resultMapUser">SELECT * FROM userWHERE id=#{value}</select><delete id="deleteUser" parameterType="String">DELETE FROM userWHERE id=#{value}</delete><update id="updateUser" parameterType="java.util.Map">UPDATE userSET name=#{name}WHERE id=#{id}</update> </mapper>
(7)建立UserService.java接口類:
package com.gnc.service;import java.util.Map;import com.gnc.model.User;public interface UserService {public int countAll();public void insertUser(User user);public void update_insert(Map map, User user);}
(8)建立UserServiceImpl.java實現類:
package com.gnc.serviceImpl;import java.util.Map;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service;import com.gnc.dao.UserDao; import com.gnc.model.User; import com.gnc.service.UserService;@Service("userService") public class UserServiceImpl implements UserService {@Autowiredprivate UserDao userDao;public int countAll() {return this.userDao.countAll();}@Overridepublic void insertUser(User user) {this.userDao.insertUser(user);throw new RuntimeException("Error");}@Overridepublic void update_insert(Map map, User user) {this.userDao.updateUser(map);this.userDao.insertUser(user);throw new RuntimeException("Error");}}
(9)建立mybatis配置文件MyBatis-Configuration.xml:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration><mappers><mapper resource="UserDaoMapper.xml"/></mappers> </configuration>
(10)建立數據庫配置文件config.properties:
db.driverClass=org.gjt.mm.mysql.Driver db.jdbcUrl=jdbc:mysql://localhost:3306/transaction db.user=root db.password=geningchao # db.initialPoolSize=20 db.maxIdleTime=60 db.maxPoolSize=200 db.minPoolSize=50 # db.acquireIncrement=3 db.acquireRetryDelay=1000 db.acquireRetryAttempts=30 db.breakAfterAcquireFailure=false
(11)建立spring配置文件applicationContext.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:context="http://www.springframework.org/schema/context"xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop"xmlns:mvc="http://www.springframework.org/schema/mvc"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-3.0.xsdhttp://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"><!-- 加載配置文件 --><context:property-placeholder location="config.properties" /><!-- 指定spring注解注入層 --><context:component-scan base-package="com.gnc" /><!-- 數據庫連接池管理 --><bean id="c3p0DataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"destroy-method="close"><property name="driverClass" value="${db.driverClass}"></property><property name="jdbcUrl" value="${db.jdbcUrl}"></property><property name="user" value="${db.user}"></property><property name="password" value="${db.password}"></property><property name="initialPoolSize" value="${db.initialPoolSize}"></property><!--最大空閑時間,60秒內未使用則連接被丟棄。若為0則永不丟棄。Default: 0 --><property name="maxIdleTime" value="${db.maxIdleTime}"></property><!--連接池中保留的最大連接數。Default: 15 --><property name="maxPoolSize" value="${db.maxPoolSize}"></property><property name="minPoolSize" value="${db.minPoolSize}"></property><!--當連接池中的連接耗盡的時候c3p0一次同時獲取的連接數。Default: 3 --><property name="acquireIncrement" value="${db.acquireIncrement}"></property><!--兩次連接中間隔時間,單位毫秒。Default: 1000 --><property name="acquireRetryDelay" value="${db.acquireRetryDelay}"></property><!--定義在從數據庫獲取新連接失敗后重復嘗試的次數。Default: 30 --><property name="acquireRetryAttempts" value="${db.acquireRetryAttempts}"></property><!--獲取連接失敗將會引起所有等待連接池來獲取連接的線程拋出異常。但是數據源仍有效保留,并在下次調用getConnection()的時候繼續嘗試獲取連接。如果設為true,那么在嘗試 獲取連接失敗后該數據源將申明已斷開并永久關閉。Default: false --><property name="breakAfterAcquireFailure" value="${db.breakAfterAcquireFailure}"></property></bean><!-- ================================事務相關控制================================================= --><bean name="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="c3p0DataSource"></property></bean><tx:advice id="userTxAdvice" transaction-manager="transactionManager"><tx:attributes><tx:method name="delete*" propagation="REQUIRED" read-only="false"rollback-for="java.lang.Exception" no-rollback-for="java.lang.RuntimeException" /><tx:method name="insert*" propagation="REQUIRED" read-only="false"rollback-for="java.lang.RuntimeException" /><tx:method name="update*" propagation="REQUIRED" read-only="false"rollback-for="java.lang.Exception" /><tx:method name="find*" propagation="SUPPORTS" /><tx:method name="get*" propagation="SUPPORTS" /><tx:method name="select*" propagation="SUPPORTS" /></tx:attributes></tx:advice><aop:config><aop:pointcut id="pc"expression="execution(public * com.gnc.service.*.*(..))" /> <!--把事務控制在Service層 --><aop:advisor pointcut-ref="pc" advice-ref="userTxAdvice" /></aop:config><bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><property name="dataSource" ref="c3p0DataSource" /><property name="configLocation" value="MyBatis-Configuration.xml" /></bean><bean class="org.mybatis.spring.mapper.MapperFactoryBean"><property name="mapperInterface" value="com.gnc.mapper.UserMapper" /><property name="sqlSessionFactory" ref="sqlSessionFactory" /></bean></beans>
(12)建立測試類UserServiceTest.java:
package com.gnc.test;import java.util.HashMap; import java.util.Map;import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;import com.gnc.model.User; import com.gnc.service.UserService;public class UserServiceTest {@Testpublic void userServiceTest(){@SuppressWarnings("resource")ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");UserService userService = (UserService)context.getBean("userService");User user =new User();user.setId("003");user.setName("櫻木花道");Map map=new HashMap();map.put("id", "001");map.put("name", "方舟子");try {System.out.println(userService.countAll());userService.update_insert(map, user);} catch (Exception e) {e.printStackTrace();}} }
?3.工程分析
該工程屬于聲明式事務管理,事務管理的主要配置是寫在spring的配置文件當中,工程運行時,先加載spring配置文件,通過spring配置文件得到mybatis配置文件,得到映射文件,進行事務處理以及書屋管理.但是這種事務管理方式限制了包的分級結構和函數名的前綴,所以一般情況下,我們使用注解式事務管理,注解式事務管理實例將在下一章節給出并進行說明!
?
以上僅是個人觀點,若有不對,敬請扶正!
?
轉載于:https://www.cnblogs.com/geningchao/p/6628452.html
總結
以上是生活随笔為你收集整理的spring+mybatis之声明式事务管理初识(小实例)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 搜索引擎原理和简单过程【转】
- 下一篇: 用xml画水平虚线和竖直虚线.md