看你是什么事务,jdbc事务,还是分布式事务,还是容器事务
创新互联建站长期为上1000+客户提供的网站建设服务,团队从业经验10年,关注不同地域、不同群体,并针对不同对象提供差异化的产品和服务;打造开放共赢平台,与合作伙伴共同营造健康的互联网生态环境。为新沂企业提供专业的网站制作、网站建设,新沂网站改版等技术服务。拥有10余年丰富建站经验和众多成功案例,为您定制开发。
1,编程式事务管理(jdbc的事务是绑定在connection上的)
Connection conn = null;
try
{
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:oracle:thin:@host:1521:SID","username","password");
conn.setAutoCommit(false); //取消自动提交
PreparedStatement ps = conn.prepareCall("update something");
ResultSet rs = ps.executeQuery();
conn.commit(); //手动提交
}
catch (Exception e)
{
conn.rollback();
e.printStackTrace();
}
finally
{
conn.close();
}
2,声明式事务
先在工程的application.xml配置文件中添加如下代码,开启事务
!-- 声明式事务控制配置 --
tx:annotation-driven transaction-manager="txManager"/
bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
property name="datasource" ref="bassDataSource"/property
/bean
然后在你需要开启事务的接口前面添加注解
@Transactional(rollbackFor = IOException.class)
public void add(String name) throws IOException
{
System.out.println("可以再类里和方法里面添加事务注解0~0");
throw new IOException();
}
直接调用接口方法就好
分布式事务处理(mysql貌似在5.X之后才支持) 的话,
1.可以直接使用spring+atomikos框架进行管理
参考:
就不贴测试代码了,自己看着配置吧
2,使用JTA(Java Transaction API)进行分布式事务管理(测试代码如下)
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import javax.naming.InitialContext;
import javax.sql.DataSource;
import javax.transaction.SystemException;
import javax.transaction.UserTransaction;
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
//分布式事务处理
public class transferAccount
{
@SuppressWarnings("null")
public void testTransferAccount()
{
UserTransaction userts = null;
Connection connA = null;
PreparedStatement psA = null;
InitialContext context = null;
Connection connB = null;
PreparedStatement psB = null;
try
{
//获得事务管理对象
userts = (UserTransaction) context.lookup("java:comp/UserTransaction");
//获取两个数据库
connA = getDataSourceA().getConnection();
connB = getDataSourceB().getConnection();
//开启事务
userts.begin();
//sql语句
psA = connA.prepareStatement("我加1");
psB = connB.prepareStatement("我减1");
//执行sql
psA.executeUpdate();
psB.executeUpdate();
//事务提交
userts.commit();
} catch (Exception e)
{
try
{
userts.rollback();
} catch (IllegalStateException | SecurityException
| SystemException e1)
{
e1.printStackTrace();
}
e.printStackTrace();
}
finally
{
try
{
psA.close();
psB.close();
connA.close();
connB.close();
} catch (SQLException e)
{
e.printStackTrace();
}
}
}
public DataSource getDataSourceA()
{
MysqlDataSource dataSource = new MysqlDataSource();
dataSource.setDatabaseName("mysql");
dataSource.setServerName("server");
dataSource.setPortNumber(1433);
dataSource.setUser("test");
dataSource.setPassword("test");
return dataSource;
}
public DataSource getDataSourceB()
{
MysqlDataSource dataSource = new MysqlDataSource();
dataSource.setDatabaseName("mysql");
dataSource.setServerName("server");
dataSource.setPortNumber(1435);
dataSource.setUser("test1");
dataSource.setPassword("test1");
return dataSource;
}
}
是的, 如果有错误就回滚,否则就提交
IF t_error = 1 THEN
ROLLBACK;
ELSE
COMMIT;
mysql_options(mysql,MYSQL_INIT_COMMAND,"SET autocommit=0");
取消自动提交
mysql_commit()
提交事务
mysql_rollback()
回滚事务!
一个事务里面有若干操作 必须一起完成 或者哪个也不要做 如果有一个操作因故不能完成 那么之前已经完成的就要回滚
手动提交 可以对逻辑进行控制,打个比方:
你程序需要做两件事情,一个是 结账,一个是打印账单。这两个事情必须都要成功,才算是结账成功,否则认为失败。
那么这个时候我们就要使用手动提交了,因为打印账单不属于数据库控制范畴。
我们可以 先添加结账数据到数据库,然后等待打印机打印
,这个时候虽然我们的数据是添加成功了,如果打印机打印报错了,那么这个任务就没有完成,就必须回滚掉之前的数据库操作。
手动提交事务: 可以控制整个程序的任务完成情况和完成的逻辑。数据添加成功,打印失败,造成的结果就是:数据显示未结账,也没有账单打印出来。数据就是一致的!
自动提交:只管你数据库添加是否成功,打印机有没有打印账单就不能控制了,造成的结果就是,数据显示已结账,但是没有账单打印出来。那么就出现数据不一致的情况。
手动的话:整个任务完成,就完成,中间任何一个环节出错 就等于什么都没做
自动提交:整个任务完成一个是算一个!