如果不了解事务的概念的话,可参见笔者的另一篇文章"事务和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推荐