事务具有ACID属性,即原子性(Atomicity),一致性(Consistency),隔离性(Isolation),持久性(Durablity)
注解配置:
BbtForumlmpl.Java
package com.baobaotao.service.impl;
import java.sql.SQLException;
import org.springframework.dao.PessimisticLockingFailureException;
import org.springframework.transaction.annotation.Transactional;
import com.baobaotao.dao.ForumDao;
import com.baobaotao.dao.PostDao;
import com.baobaotao.dao.TopicDao;
import com.baobaotao.domain.Forum;
import com.baobaotao.domain.Topic;
import com.baobaotao.service.BbtForum;
@Transactional
public class BbtForumImpl implements BbtForum {
private ForumDao forumDao;
private TopicDao topicDao;
private PostDao postDao;
public void addTopic(Topic topic) throws Exception {
topicDao.addTopic(topic);
// if(true) throw new PessimisticLockingFailureException("fail");
postDao.addPost(topic.getPost());
}
@Transactional(readOnly=true)
public Forum getForum(int forumId) {
return forumDao.getForum(forumId);
}
public void updateForum(Forum forum) {
forumDao.updateForum(forum);
}
public int getForumNum() {
return forumDao.getForumNum();
}
public void setForumDao(ForumDao forumDao) {
this.forumDao = forumDao;
}
public void setPostDao(PostDao postDao) {
this.postDao = postDao;
}
public void setTopicDao(TopicDao topicDao) {
this.topicDao = topicDao;
}
}
@Transactional 可以被应用于类定义和类的public 方法上,可以但很少用于接口定义和接口方法。
只需要添加这个标注,就完成了业务类事务属性的配置,注解本身不能完成事务切面的织入的功能,我们还需要配置文件,通过spring容器对标注 @Transactional 的Bean进行加工处理。
<?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:context="http://www.springframework.org/schema/context"
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.xsd">
<context:property-placeholder
location="classpath:jdbc.properties"/>
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close"
p:driverClassName="${jdbc.driverClassName}"
p:url="${jdbc.url}"
p:username="${jdbc.username}"
p:password="${jdbc.password}"/>
<bean id="jdbcTemplate"
class="org.springframework.jdbc.core.JdbcTemplate"
p:dataSource-ref="dataSource"/>
<bean id="abstracDao" abstract="true"
p:jdbcTemplate-ref="jdbcTemplate"/>
<bean id="forumDao" parent="abstracDao" class="com.baobaotao.dao.jdbc.ForumJdbcDao"/>
<bean id="topicDao" parent="abstracDao" class="com.baobaotao.dao.jdbc.TopicJdbcDao"/>
<bean id="postDao" parent="abstracDao" class="com.baobaotao.dao.jdbc.PostJdbcDao"/>
</beans>
第一个配置文件是在配置数据源 "dataSource" ,还有各种Dao,然后被第二个配置文件引入,第二个配置文件为主要的。
application-anno.xml
<bean id="bbtForum"
class="com.baobaotao.service.impl.BbtForumImpl"
p:forumDao-ref="forumDao"
p:topicDao-ref="topicDao"
p:postDao-ref="postDao" />
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
p:dataSource-ref="dataSource"/>
<tx:annotation-driven transaction-manager="txManager" proxy-target-class="true" />
解说如下:
<bean id="bbtForum"
class="com.baobaotao.service.impl.BbtForumImpl"
p:forumDao-ref="forumDao"
p:topicDao-ref="topicDao"
p:postDao-ref="postDao" />
配置需要事务增强的业务类,由于配置了@Transactional , 所以会被最后一句注解驱动自动织入事务。
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
p:dataSource-ref="dataSource"/>
声明事务管理器
<tx:annotation-driven transaction-manager="txManager" proxy-target-class="true" />
自动织入事务。
@Transactional(propagation=Propagation.NESTED)
// readOnly=true只读,不能更新,删除
@Transactional (propagation = Propagation.REQUIRED,readOnly=true)
// 设置超时时间
@Transactional (propagation = Propagation.REQUIRED,timeout=30)
// 设置数据库隔离级别
@Transactional (propagation = Propagation.REQUIRED,isolation=Isolation.DEFAULT)
XML配置:
Student.java
package com.bean;
public class Student {
private String name;
private int age;
private String sex;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public Student(String name, int age, String sex) {
super();
this.name = name;
this.age = age;
this.sex = sex;
}
public Student() {
super();
}
public void setAge(int age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
package com.dao;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import com.bean.Student;
public class AddStuDao extends JdbcDaoSupport {
public void add(Student stu)
{
JdbcTemplate template=getJdbcTemplate();
template.execute("insert into student(name,age,sex) values('"+stu.getName()+"',"+stu.getAge()+",'"+stu.getSex()+"')");
template.execute("insert into student(name,age,sex) values('"+stu.getName()+"',"+stu.getAge()+",'"+stu.getSex()+"')");
}
}
beans.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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<bean id="student" class="com.bean.Student"> </bean>
<bean id="addStuDao" class="com.dao.AddStuDao">
<property name="dataSource" ref="dataSource"></property>
</bean>
<bean id="proxyFactoryBean" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="transactionManager"/>
<property name="target" ref="addStuDao"> </property>
<property name="proxyTargetClass" value="true"></property>
<property name="transactionAttributes">
<props>
<prop key="add*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="password" value="fpy/.123698741"></property>
<property name="username" value="root"></property>
<property name="url" value="jdbc:mysql://localhost:3306/springstudy"></property>
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
</beans>
测试类:
public static void main(String[]args)
{
ApplicationContext cxt = new ClassPathXmlApplicationContext("beans.xml");
AddStuDao add=(AddStuDao) cxt.getBean("proxyFactoryBean");
add.add(new Student("wh",21,"男"));
}
同时插入两个主键值相同的数据,会报错,且没有一条数据进入数据库。