数据库事务管理

来源:互联网 发布:《云计算安全》 编辑:程序博客网 时间:2024/04/30 13:02

最近重新学习了数据库事务管理 纠正了好多错误的观念,下面从数据库事务的概念,JDBC事务,Spring+Hibernate事务管理三部分来介绍。

一.数据库事务的概念

数据库事务是指作为单个逻辑工作单元执行的一系列操作。设想网上购物的一次交易,其付款过程至少包括以下几步数据库操作:  1更新客户所购商品的库存信息  2保存客户付款信息--可能包括与银行系统的交互  3生成订单并且保存到数据库中  4更新用户相关信息,例如购物数量等等正常的情况下,这些操作将顺利进行,最终交易成功,与交易相关的所有数据库信息也成功地更新。但是,如果在这一系列过程中任何一个环节出了差错,例如在更新商品库存信息时发生异常、该顾客银行帐户存款不足等,都将导致交易失败。一旦交易失败,数据库中所有信息都必须保持交易前的状态不变,比如最后一步更新用户信息时失败而导致交易失败,那么必须保证这笔失败的交易不影响数据库的状态--库存信息没有被更新、用户也没有付款,订单也没有生成。否则,数据库的信息将会一片混乱而不可预测。

二.JDBC事务

这里要注意以下几个问题

1.使用con.setAutoCommit(false);更改JDBC事务的默认提交方式,默认为true,一旦关闭了自动提交,除非通过调用 commit() 显式地告诉它提交语句,否则无法提交 SQL 语句(即,数据库将不会被持久地更新)。在提交之前的任何时间,我们都可以调用 rollback() 回滚事务,并恢复最近的提交值(在尝试更新之前)。

2.使用try--catch--finally处理异常,并关闭连接

3.使用commit显式的提交事务,提交之后就无法更改。

使用上述方法可以在事务建立至事务提交之间添加多个SQL,即构成了事务。

public int delete(int sID) {    dbc = new DataBaseConnection();    Connection con = dbc.getConnection();    try {   con.setAutoCommit(false);// 更改JDBC事务的默认提交方式,默认为true,  dbc.executeUpdate("delete from bylaw where ID=" + sID);   dbc.executeUpdate("delete from bylaw _content where ID=" + sID);   dbc.executeUpdate("delete from bylaw _affix where bylawid=" + sID);   con.commit();//提交JDBC事务,commit之后就无法从数据库中抹去con.setAutoCommit(true);// 恢复JDBC事务的默认提交方式   dbc.close();   return 1;    }    catch (Exception exc) {   con.rollBack();//回滚JDBC事务   exc.printStackTrace();   dbc.close();   return -1;    }   }  
三 spring hibernate整合事务

一个较为典型的Spring 托管hibernate的applicationContext的配置:

<?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:p="http://www.springframework.org/schema/p"xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:tx="http://www.springframework.org/schema/tx"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.xsdhttp://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd         http://www.springframework.org/schema/aop         http://www.springframework.org/schema/aop/spring-aop-3.0.xsd          http://www.springframework.org/schema/tx          http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"><!-- property configure 获取property配置文件的路径 --><context:property-placeholderlocation="classpath:conf/constant.properties,classpath:conf/db.properties,classpath:conf/ctx.properties" />        <!-- 自动搜索 base-package 的注解配置--><context:component-scan base-package="com"/><!-- DataSource 配置数据源--><bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"><property name="driverClassName" value="${jdbc.driverClassName}"></property><property name="url" value="${jdbc.url}"></property><property name="username" value="${jdbc.user}"></property><property name="password" value="${jdbc.password}"></property><property name="maxActive" value="200"></property><property name="maxIdle" value="30"></property><property name="maxWait" value="500"></property><property name="defaultAutoCommit" value="true"></property></bean><!-- Hibernate Properties --><bean id="hibernateProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean"><property name="properties"><props><prop key="hibernate.dialect">${hibernate.dialect}</prop><prop key="hibernate.show_sql">${hibernate.show_sql}</prop><prop key="jdbc.fetch_size">50</prop><prop key="jdbc.batch_size">25</prop><prop key="hibernate.connection.autocommit">false</prop><!--<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop><prop key="hibernate.cache.use_query_cache">true</prop><prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop> --><prop key="hibernate.query.substitutions">true 1,false 0</prop></props></property></bean><!-- SessionFactory 配置 SessionFactory  以便注入--><bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"><property name="dataSource"><ref bean="dataSource" /></property><property name="hibernateProperties"><ref local="hibernateProperties"/></property><property name="mappingResources"><list><value>com/amazon/model/User.hbm.xml</value></list></property><!--  <property name="mappingDirectoryLocations"><list><value>com/amazon/model/User.hbm.xml</value></list></property>--></bean><!-- Transaction Manager 事务管理--><bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"><property name="sessionFactory"><ref local="sessionFactory"/></property></bean><tx:annotation-driven transaction-manager="transactionManager" /><!--  Base Transaction Proxy --><!-- <bean id="baseTxProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true"><property name="transactionManager"><ref local="transactionManager"/></property><property name="transactionAttributes"><props><prop key="*">PROPAGATION_REQUIRED</prop><prop key="save*">PROPAGATION_REQUIRED</prop><prop key="load*">PROPAGATION_REQUIRED,readOnly</prop><prop key="get*">PROPAGATION_REQUIRED,readOnly</prop><prop key="find*">PROPAGATION_REQUIRED,readOnly</prop></props></property></bean>--><!-- views configuration 配置前端视图,可以完成多视图配置--><bean id="freeMarkerConfigurer"class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer"><property name="templateLoaderPath" value="/" /><property name="freemarkerSettings"><props><prop key="locale">zh_cn</prop><prop key="template_update_delay">0</prop><prop key="number_format">0.##########</prop><prop key="defaultEncoding">UTF-8</prop><prop key="auto_include"></prop></props></property><property name="freemarkerVariables"><map><entry key="xml_escape" value-ref="fmXmlEscape" /></map></property></bean><bean id="fmXmlEscape" class="freemarker.template.utility.XmlEscape" /><bean id="viewResolver"class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver"><property name="contentType"><value>text/html; charset=UTF-8</value></property><property name="cache" value="true" /><property name="prefix" value="/WEB-INF/tmpl/" /><property name="suffix" value=".ftl" /><property name="exposeSpringMacroHelpers" value="true"></property><property name="exposeRequestAttributes" value="true"></property></bean></beans>


Dao的实现

import org.hibernate.Session;import org.hibernate.SessionFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Repository;import org.springframework.transaction.annotation.Transactional;import com.amazon.dao.UserDao;import com.amazon.model.User;@Repository("userDao")public class UserDaoImpl implements UserDao{ @Autowiredprivate SessionFactory sessionFactory;public void getAll() {// TODO Auto-generated method stub}@Overridepublic void getById(long id) {// TODO Auto-generated method stub}//添加Transactional 才能使用getCurrentSession@Transactional@Override public void insert(User user) {// TODO Auto-generated method stubSession session=sessionFactory.getCurrentSession();//openSession();session.save(user);}public void setSesionFactory(SessionFactory sesionFactory) {this.sessionFactory = sesionFactory;}public SessionFactory getSesionFactory() {return sessionFactory;}}


测试文件

import javax.annotation.Resource;import org.hibernate.SessionFactory;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import org.springframework.stereotype.Component;import com.amazon.dao.UserDao;import com.amazon.model.User;@Componentpublic class BaseTest {private static  SessionFactory sessionFactory;@Resourcepublic  void setSessionFactory(SessionFactory sessionFactory) {BaseTest.sessionFactory = sessionFactory;}public  SessionFactory getSessionFactory() {return sessionFactory;}public static void main(String args[]){ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");System.out.println(sessionFactory);UserDao userDao=(UserDao)ctx.getBean("userDao");User user=new User();user.setUserName("aaa");user.setUserStatus("Admin");userDao.insert(user);}}

在此要注意openSession和getCurrentSession的区别

1 openSession  
  a.永远创建session 
  b.需要关闭 session 2.getCurrentSession  
 a.如果当前上下文中存在可用的session会获取,如果不存在则会创建  b.不需要关闭session  
getCurrentSession()   
1.用途:界定事务边界 2.事务提交自动关闭

2.只有在抛出RuntimeException的时候才能回滚,其他的Exception不能够回滚

3.在事务的设置上,最好在Service上设置事务




原创粉丝点击