java中事务是什么?
事务是访问数据库的一个操作序列,DB应用系统通过事务集来完成对数据的存取。
事务必须遵循4个原则,即常说的 ACID
A,Automicity,原子性,即事务要么被全部执行,要么被全部不执行。如果事务下的子事务全部提交成功,则所有数据库操作被提交,否则,应进行事务回滚。
C,Consistency,一致性,即状态转换必须是由一种正确的状态转换到另外一种正确的状态。
I,Isolation,隔离性,即相互间必须不能被影响。
D,Durabillity,持久性,即事务提交后将被永久保存,即便出现其他故障,事务处理结果也应得到保存。
事务的隔离级别
串行化,Serializable,一个事务在执行过程中完全看不到其他事务对数据库所做的更新。
可重复读,Repeatable Read,一个事务在执行过程中可以看到其他事务已经提交的记录,但是不能看到其他事务对已有记录的更新。
读已提交数据,Read Commited,一个事务在执行过程中可以看到其他事务已经提交的记录,而且能看到其他事务对已有记录的更新。
读未提交数据,Read UnCommited,一个事务在执行过程中可以看到其他事务没有提交的记录,而且能看到其他事务没有提交的记录的更新
简单介绍完事务之后,我们用一个例子来具体使用一下事务:购买股票的案例
第一步:准备工作
1)数据表
股票表:stock
账户余额表:account
2)实体类
Account类
package demo22tx.entity; /** * Created by mycom on 2018/3/15. */ public class Account { private Integer aid; private String aname; public Integer getAid() { return aid; } public void setAid(Integer aid) { this.aid = aid; } public String getAname() { return aname; } public void setAname(String aname) { this.aname = aname; } public Integer getAblance() { return ablance; } public void setAblance(Integer ablance) { this.ablance = ablance; } private Integer ablance; }
Stock类
package demo22tx.entity; import javax.jnlp.IntegrationService; /** * Created by mycom on 2018/3/15. */ public class Stock { private Integer sid; private String sname; private Integer scount; public Integer getSid() { return sid; } public void setSid(Integer sid) { this.sid = sid; } public String getSname() { return sname; } public void setSname(String sname) { this.sname = sname; } public Integer getScount() { return scount; } public void setScount(Integer scount) { this.scount = scount; } }
3)dao层
AccountDao接口
package demo22tx.dao; /** * Created by mycom on 2018/3/15. */ public interface IAccountDao { public boolean updateAccount(int aid,int ablance,boolean isbuy); }
AccountDaoImpl实现类
package demo22tx.dao; import org.springframework.jdbc.core.support.JdbcDaoSupport; /** * Created by mycom on 2018/3/15. */ public class AccountDaoImpl extends JdbcDaoSupport implements IAccountDao { public boolean updateAccount(int aid, int ablance, boolean isbuy) { String sql=""; boolean flag=false; if(isbuy){ //买入购票 sql="update account set balance=balance-? where aid=?"; }else{ sql="update account set balance=balance+? where aid=?"; } int update = this.getJdbcTemplate().update(sql, ablance, aid); if(update>0){ flag=true; } return flag; } }
StockDao接口
package demo22tx.dao; /** * Created by mycom on 2018/3/15. */ public interface IStockDao { public boolean updateStock(int sid,int count,boolean isbuy); }
StockDaoImpl实现类
package demo22tx.dao; import org.springframework.jdbc.core.support.JdbcDaoSupport; /** * Created by mycom on 2018/3/15. */ public class StockDaoImpl extends JdbcDaoSupport implements IStockDao { public boolean updateStock(int sid, int count, boolean isbuy) { String sql=""; boolean flag=false; if(isbuy){ //买入购票 sql="update stock set count=count+? where sid=?"; }else{ sql="update stock set count=count+? where sid=?"; } int update = this.getJdbcTemplate().update(sql, count, sid); if(update>0){ flag=true; } return flag; } }
4)service层
IStockService接口
package demo22tx.service; import demo22tx.entity.StockException; import org.springframework.transaction.annotation.Transactional; /** * Created by mycom on 2018/3/15. */ public interface IStockService { public boolean buyStock(int aid,int abalance,int sid,int count) throws StockException; }
StockServiceImpl实现类
package demo22tx.service; import demo22tx.dao.IAccountDao; import demo22tx.dao.IStockDao; import demo22tx.entity.StockException; import org.springframework.transaction.annotation.Transactional; /** * Created by mycom on 2018/3/15. */ public class StockServiceImpl implements IStockService{ private IAccountDao accountDao; private IStockDao stockDao; @Transactional public boolean buyStock(int aid, int abalance, int sid, int count) throws StockException { boolean isbuy=true; //异常 if(1==1){ throw new StockException("出错了"); } boolean account = accountDao.updateAccount(aid, abalance, isbuy); boolean stock = stockDao.updateStock(sid, count, isbuy); if(account&&stock){ return true; }else{ return false; } } public IAccountDao getAccountDao() { return accountDao; } public void setAccountDao(IAccountDao accountDao) { this.accountDao = accountDao; } public IStockDao getStockDao() { return stockDao; } public void setStockDao(IStockDao stockDao) { this.stockDao = stockDao; } }
第二步:配置文件
JDBC.properties文件
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql:///s2228 jdbc.username=root jdbc.password=
applicationContextdemo22tx.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.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.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"> <!--配置数据源--> <bean id="dateSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="${jdbc.driver}"></property> <property name="url" value="${jdbc.url}"></property> <property name="username" value="${jdbc.username}"></property> <property name="password" value="${jdbc.password}"></property> </bean> <!--识别到jdbc.properties--> <!--配置1--> <!--<context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>--> <!--配置2--> <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="location" value="classpath:jdbc.properties"></property> </bean> <!--配置Dao--> <bean id="accountDao" class="demo22tx.dao.AccountDaoImpl"> <property name="dataSource" ref="dateSource"></property> </bean> <bean id="stockDao" class="demo22tx.dao.StockDaoImpl"> <property name="dataSource" ref="dateSource"></property> </bean> <!--service id--> <bean id="stockService" class="demo22tx.service.StockServiceImpl"> <property name="accountDao" ref="accountDao"></property> <property name="stockDao" ref="stockDao"></property> </bean> <!--事务--> <!--事务管理器--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dateSource"></property> </bean> <!--事务代理工厂bean 方式一--> <!--<bean id="stockServiceProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">--> <!--<property name="transactionManager" ref="transactionManager"></property>--> <!--<property name="target" ref="stockService"></property>--> <!--<property name="transactionAttributes">--> <!--<props>--> <!--<prop key="buyStock">ISOLATION_DEFAULT,PROPAGATION_REQUIRED</prop>--> <!--</props>--> <!--</property>--> <!--</bean>--> <!--事务代理工厂bean 方式二--> <!--<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>--> <!--事务代理工厂bean 方式三--> <tx:advice id="stockAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="buyStock" isolation="DEFAULT" propagation="REQUIRED"/> </tx:attributes> </tx:advice> <aop:config> <aop:pointcut id="mypointcut" expression="execution(* demo22tx.service.*.*(..))"></aop:pointcut> <aop:advisor advice-ref="stockAdvice" pointcut-ref="mypointcut"></aop:advisor> </aop:config> </beans>
第三步:测试类
import demo21.entity.Book; import demo21.service.IBookservice; import demo22tx.entity.StockException; import demo22tx.service.IStockService; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import java.util.List; /** * Created by mycom on 2018/3/3. */ public class TestTrasaction20180315 { //JDBCtemplate测试类 @Test public void t1() throws StockException { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContextdemo22tx.xml"); IStockService stockService =(IStockService) context.getBean("stockService"); stockService.buyStock(1,100,1,10); } }