事务控制代码示例

标签: 控制 代码 | 发表时间:2014-12-29 10:07 | 作者:
出处:http://www.iteye.com
如果不了解事务的概念的话,可参见笔者的另一篇文章"事务和MVCC" http://frank1234.iteye.com/blog/2164232

1 JDBC事务
这个没啥好说的,直接上代码
public class JdbcTransactionMain {
    public static void main(String[] args) throws Exception{
        Class.forName("com.mysql.jdbc.Driver");
        Connection conn = null;
        Statement st = null;
        try{
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/springdemo","root","frank1234");
            //开始事务
            conn.setAutoCommit(false);
            st = conn.createStatement();
            st.executeUpdate("insertsql1");
            st.executeUpdate("insertsql2");
            //事务提交
            conn.commit();
        }catch (Exception e){
            e.printStackTrace();
            //注意有异常必须得回滚,否则执行成功的sql会持久化到数据库中
            conn.rollback();
        }finally {//记得释放资源
            if(st != null)
                st.close();
            if(conn != null)
                conn.close();
        }
    }
}


2 Hibernate事务

public class HibernateTransactionMain {
    public static void main(String[] args) throws Exception{
        Session session = null;
        Transaction tx = null;
        try {
            session = new Configuration().configure().buildSessionFactory().openSession();
            //开始事务
            tx = session.beginTransaction();
            session.save(po1);
            session.save(po2);
            //提交事务
            tx.commit();
        }catch (Exception e){
            e.printStackTrace();
            //回滚事务
            tx.rollback();
        }finally {
            if(session != null)
                session.close();
        }
    }
}


3 Spring声明式事务
下面代码示例操作数据库使用Sping的JdbcTemplate
后台数据库表:
CREATE TABLE `person` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) DEFAULT NULL,
  `sex` varchar(2) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=gb2312

CREATE TABLE `orders` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `cost` int(11) NOT NULL,
  `customerid` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=gb2312

Person对象
public class Person {

     /**
      * id号
      */
     private int id;
     /**
      * 姓名
      */
     private String name;
     /**
      * 年龄
      */
     private int age;
     /**
      * 性别
      */
     private String sex;


     public Person(int id, String name, int age, String sex) {
         this.id = id;
         this.name = name;
         this.age = age;
         this.sex = sex;
     }

     public Person() {
     }

     public int getId() {
         return id;
     }

     public void setId(int id) {
         this.id = id;
     }

     public String getName() {
         return name;
     }

     public void setName(String name) {
         this.name = name;
     }

     public int getAge() {
         return age;
     }

     public void setAge(int age) {
         this.age = age;
     }

     public String getSex() {
         return sex;
     }

     public void setSex(String sex) {
         this.sex = sex;
     }

}

Order对象:
public class Order {
    private int id;
    private int cost;
    private int customerId;
    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getCost() {
        return cost;
    }

    public void setCost(int cost) {
        this.cost = cost;
    }

    public int getCustomerId() {
        return customerId;
    }

    public void setCustomerId(int customerId) {
        this.customerId = customerId;
    }

    public String toString(){
        return "id="+id+",cost="+cost;
    }
}


TransactionDAO接口:
public interface TransactionDAO {
    public void savePersonAndOrder(Person person,Order order);
    public void savePerson(Person person);
    public void saveOrder(Order order);
}

TransactionDAOImpl实现类:
其中saveOrder()方法写错,让其操作不成功。
public class TransactionDAOImpl implements TransactionDAO{
    private JdbcTemplate jdbcTemplate;

    public void setDataSource(DataSource dataSource) {
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }

    public void savePersonAndOrder(Person person,Order order) {
        savePerson(person);
        saveOrder(order);
    }

    public void savePerson(Person person) {
        jdbcTemplate.update("insert into person(name,age,sex)values(?,?,?)",
                new Object[] { person.getName(), person.getAge(),
                        person.getSex() }, new int[] { java.sql.Types.VARCHAR,
                        java.sql.Types.INTEGER, java.sql.Types.VARCHAR });

    }

    public void saveOrder(Order order) {
        jdbcTemplate.update("insert into order1(cost,customerid)values(?,?)",
                new Object[] { order.getCost(), order.getCustomerId()}, new int[] {
                        java.sql.Types.INTEGER, Types.INTEGER });
    }
}


Spring配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
        "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
    <!-- MySQL -->
    <bean id="dataSource"
       class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
       <property name="driverClassName" value="com.mysql.jdbc.Driver" />
       <property name="url" value="jdbc:mysql://localhost:3306/springdemo" />
       <property name="username" value="root" />
       <property name="password" value="frank1234" />
   </bean>


    <bean id="transactionDAO" class="org.frank1234.spring.transaction.TransactionDAOImpl">
        <property name="dataSource" ref="dataSource" />
    </bean>
   
</beans>


测试类:
public class TransactionMain {
    public static void main(String[] args) throws Exception{
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        TransactionDAO personService = (TransactionDAO) ctx.getBean("transactionDAO");

        Person person = new Person();
        person.setName("frank1234");
        person.setAge(21);
        person.setSex("男");
        // 保存一条记录


        Order order= new Order();
        order.setCost(10);
        order.setCustomerId(12);

        personService.savePersonAndOrder(person,order);


    }
}


执行后,数据库记录截图:



可见person表的记录还是写入了。


修改Spring配置文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
        "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
    <!-- MySQL -->
    <bean id="dataSource"
       class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
       <property name="driverClassName" value="com.mysql.jdbc.Driver" />
       <property name="url" value="jdbc:mysql://localhost:3306/springdemo" />
       <property name="username" value="root" />
       <property name="password" value="frank1234" />
   </bean>


    <bean id="transactionDAOTarget" class="org.frank1234.spring.transaction.TransactionDAOImpl">
        <property name="dataSource" ref="dataSource" />
    </bean>
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource">
            <ref bean="dataSource"/>
        </property>
    </bean>
    <bean id="transactionDAO" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
        <property name="proxyInterfaces">
            <list>
                <value>org.frank1234.spring.transaction.TransactionDAO</value>
            </list>
        </property>
        <property name="target">
            <ref bean="transactionDAOTarget"/>
        </property>
        <property name="transactionManager">
            <ref bean="transactionManager"/>
        </property>
        <property name="transactionAttributeSource">
            <ref bean="transactionAttributeSource"/>
        </property>
    </bean>
    <bean id="transactionAttributeSource" class="org.springframework.transaction.interceptor.MatchAlwaysTransactionAttributeSource">

    </bean>
</beans>



清空数据库表记录,重新执行TransactionMain测试类。
数据库记录截图:



可见person没有写入,写入person和写入order是同一个事务了。

这就是Spring声明式事务,其本质是AOP,将事务相关的代码作为切面织入了目标对象的方法中。

4 JTA事务
JTA可以解决跨多个数据源的事务问题,但是性能较差,使用的话要慎重,可以考虑采用补偿机制等来解决,例如先执行a(), 接着执行b() ,如果a()执行成功,b()执行失败,那么再执行一下c(),c()是a()的反操作。
代码示例:
public class JTATransactionMain {
    public static void main(String[] args) throws Exception{
        UserTransaction tx = null;
        try{
            Properties props = new Properties();
            props.put(Context.INITIAL_CONTEXT_FACTORY, jndi_factory);// weblogic.jndi.WLInitialContextFactory
            props.put(Context.PROVIDER_URL, jndi_url);// t3://localhost:7001
            Context ctx = new InitialContext(props);
            tx=  (UserTransaction)ctx.lookup("transaction_url");
            //事务开始
            tx.begin();
            //执行。。。
           
            //事务提交
            tx.commit();
        }catch (Exception e){
            e.printStackTrace();
            tx.rollback();
        }
    }
}






已有 0 人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



相关 [控制 代码] 推荐:

代码是如何控制硬件的?

- - 知乎每日精选
既然楼主提到“低电平”,看来对数字电路是有一点了解的. 那么,翻开数字电路相关教材,最前面几页. 一般它都会告诉你,三极管/场效应管类似继电器(一种通过线圈产生磁场、然后用磁场控制物理开关的通断与否的设备);在它一个管脚上输入/切断电压信号,另一个管脚就会出现高/低电平. 那么,看下最简单的与门吧:数据有两个,分别通过两条不同的线路进入与门;输出只有一个,必须给它输入两个高电平,它才会输出高电平;否则就输出低电平(这一般简化表述为:只有输入两个1,它才输出1,否则输出0).

事务控制代码示例

- - ITeye博客
如果不了解事务的概念的话,可参见笔者的另一篇文章"事务和MVCC" http://frank1234.iteye.com/blog/2164232. 这个没啥好说的,直接上代码.             //开始事务.             //事务提交.             //注意有异常必须得回滚,否则执行成功的sql会持久化到数据库中.

Nginx带宽控制

- - 火丁笔记
有个老项目,通过 Squid 提供文件下载功能,利用  delay_parameters 实现带宽控制,问题是我玩不转 Squid,于是盘算着是不是能在 Nginx 里找到类似的功能. 好消息是 Nginx 提供了  limit_rate 和  limit_rate_after,举个例子来说明一下:.

代码重构

- - ITeye博客
随着程序的演化,我们有必要重新思考早先的决策,并重写部分代码. 代码需要演化;它不是静态的事物. 重写、重做和重新架构代码合起来,称为重构.    当你遇到绊脚石  ---  代码不在合适,你注意到有两样东西其实应该合并或是其他任何对你来说是"错误"的东西  -------- . 如果代码具备以下特征,你都应该考虑重构代码:.

Firebug控制台详解

- boho - 阮一峰的网络日志
Firebug是网页开发的利器,能够极大地提升工作效率. 我曾经翻译过一篇《Firebug入门指南》,介绍了一些基本用法. 控制台(Console)是Firebug的第一个面板,也是最重要的面板,主要作用是显示网页加载过程中产生各类信息. Firebug内置一个console对象,提供5种方法,用来显示信息.

HBase 之访问控制

- gengmao - Trend Micro CDC SPN Team
构建和运维HBase集群是一个非常有挑战性的工作. HBase凭借其在海量数据的良好的扩展性和高效的读写能力,受到越来越多公司的重视. 在公司里,HBase越来越受欢迎. 希望通过HBase读写数据的产品越来越多,在兴奋之余,头疼的问题也来了. 毕竟,作为线上的产品,我们不希望过多人随意的访问,会照成很多潜在的风险,比如误删,误操作.

当算法控制世界

- 芸窗 - Solidot
BBC的报导称,看不见的算法正在控制我们在数字世界里的互动,而糟糕的是我们正失去对这些代码的控制. 从图书和电影推荐算法,到Facebook的朋友推荐和图像标记服务,到搜索引擎,算法已经渗透到了我们生活之中. 在上月的TED大会上,算法专家Kevin Slavin描述了算法是如何塑造我们的世界,他发出警告,我们生的活正日益为算法所控制,我们正在编写我们无法理解的,可能不受控制的代码.

高并发库存控制

- - 企业架构 - ITeye博客
1、在秒杀的情况下,肯定不能如此高频率的去读写数据库,会严重造成性能问题的. 必须使用缓存,将需要秒杀的商品放入缓存中,并使用锁来处理其并发情况. 当接到用户秒杀提交订单的情况下,先将商品数量递减(加锁/解锁)后再进行其他方面的处理,处理失败在将数据递增1(加锁/解锁),否则表示交易成功. 当商品数量递减到0时,表示商品秒杀完毕,拒绝其他用户的请求.

Socket的速率控制

- - CSDN博客互联网推荐文章
做一个以精确速率向外输出数据的数据源,要完成这个目标,最基础的是:. 1、找到一种精确的计时器,在精确的时间范围内控制数据源以指定的速度向外发送数据. 2、通过对套接字选项和线程优先级的设置减少网络因素对发送速度造成的影响,从而提高发送精度,保证数据的实际发送量尽可能的达到指定的理论发送量.      针对第一个要求,通过寻找到一种时间精度达到微秒级的精确计数器来保证,在硬件支持的情况下可以通过WindowsAPI获取时钟频率以及震荡次数,通过在事件两端分别调用函数得到震荡次数的差值并结合时钟频率可以计算出精确的时间间隔,通过指定的传输速度和精确的延时可以计算出需要发送的数据量.

JDBC事务控制管理

- - 编程语言 - ITeye博客
事务指逻辑上的一组操作,组成这组操作的各个单元,要不全部成功,要不全部不成功. 例如:A——B转帐,对应于如下两条sql语句. 数据库默认事务是自动提交的,也就是发一条sql它就执行一条. 如果想多条sql放在一个事务中执行,则需要使用如下语句. 方式一:利用SQL语句管理事务. start transaction;--开启事务,这条语句之后的sql语句将处在一个事务当中,这些sql语句并不会立即执行.