Spring中提供了对JDBC功能的封装。
1、使用配置
导入依赖:
<dependencies>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>5.3.1version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-ormartifactId>
<version>5.3.1version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-testartifactId>
<version>5.3.1version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
<scope>testscope>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>8.0.16version>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druidartifactId>
<version>1.0.31version>
dependency>
dependencies>
创建jdbc.properties文件
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssm?serverTimezone=UTC
jdbc.username=root
jdbc.password=123456
配置spring核心文件
<context:property-placeholder location="jdbc.properties">context:property-placeholder>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}">property>
<property name="url" value="${jdbc.url}">property>
<property name="username" value="${jdbc.username}">property>
<property name="password" value="${jdbc.password}">property>
bean>
<bean class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource">property>
bean>
测试:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring-jdbctemplate.xml")
public class TestJdbcTemplate {
@Autowired
public JdbcTemplate jdbcTemplate;
@Test
public void JdbcTemplateTest() {
String sql = "insert into t_user values(null,'王五',28,'男')";
int update = jdbcTemplate.update(sql);
System.out.println(update);
}
}
jdbcTemplate具备增删改查功能的实现,除了查询功能其他都是调用update函数,利用重写实现不同需求的更新数据功能。
利用注解实现声明式事务比较简单,只需要在spring核心配置文件中配置两个标签,然后就可以使用注解进行标识事务了。
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource">property>
bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
配置完成之后在要实现事务功能的方法或者类上面加@Transactional注解即可。(若在类上面加代表所有方法均实现事务)一般加在Service层。
@Service
public class bookServiceImpl implements bookService {
@Autowired
public bookDao bookdao;
public bookDao getBookdao() {
return bookdao;
}
@Transactional
public void buybook(Integer uid, Integer bid) {
//要么都执行成功,要么都失败。
Integer price = bookdao.queryprice(bid);
bookdao.bookaccount(bid);
bookdao.buy(uid,price);
}
}
1、readOnly——只读
@Transactional(readOnly = true)
public void buybook(Integer uid, Integer bid) {
/**
* 设置事务只读属性则无法对数据库中的数据进行修改
* 只能执行查询操作。
*/
Integer price = bookdao.queryprice(bid);//查询书籍的价格,可以执行
bookdao.bookaccount(bid);//修改书籍的数量,不能执行
bookdao.buy(uid,price);//修改用户的余额,不能执行
}
2、timeout——超时
@Transactional(timeout = 3)
public void buybook(Integer uid, Integer bid) {
/**
* 超时属性,防止事务因为异常卡死而占用资源不释放。
* 当业务超时未完成,将会抛出异常TransactionTimedOutException
*/
try {
TimeUnit.SECONDS.sleep(5);
Integer price = bookdao.queryprice(bid);
bookdao.bookaccount(bid);
bookdao.buy(uid,price);
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
}
}
3、回滚策略
回滚策略有四个属性可以选择设置,具体来说分两类就是遇到什么异常回滚,遇到什么异常不会滚。
rollbackFor = TransactionTimedOutException.class //遇到TransactionTimedOutException异常回滚
rollbackForClassName ="TransactionTimedOutException"//遇到TransactionTimedOutException异常回滚
noRollbackFor =TransactionTimedOutException.class //遇到TransactionTimedOutException异常不回滚
noRollbackForClassName ="TransactionTimedOutException"//遇到TransactionTimedOutException异常不回滚
@Transactional(noRollbackFor =TransactionTimedOutException.class )
public void buybook(Integer uid, Integer bid) {
try {
TimeUnit.SECONDS.sleep(5);
Integer price = bookdao.queryprice(bid);
bookdao.bookaccount(bid);
bookdao.buy(uid,price);
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
}
}
4、隔离级别
@Transactional(isolation = Isolation.DEFAULT)//使用数据库默认的隔离级别
@Transactional(isolation = Isolation.READ_UNCOMMITTED)//读未提交
@Transactional(isolation = Isolation.READ_COMMITTED)//读已提交
@Transactional(isolation = Isolation.REPEATABLE_READ)//可重复读
@Transactional(isolation = Isolation.SERIALIZABLE)//串行化
5、传播行为
传播行为可以理解为:事务之中还有事务的情况下,如果出错是全部回滚还是部分回滚。
比如买一本书是事务,将买多本书的操作封装在一个大事务中,如果第一本书成功购买(对于买一本书的事务已经提交了),第二本出错,那第一本买的书还要回滚吗?
@Transactional(propagation = Propagation.REQUIRED),是默认情况,一旦出错全部回滚。
@Transactional(propagation = Propagation.REQUIRES_NEW),一旦出错,将出错部分回滚。
利用xml实现事务声明需要引入aspectj依赖:
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-aspectsartifactId>
<version>5.3.1version>
dependency>
在spring核心配置文件配置事务声明,要将之前注解实现的以下配置删除
<tx:annotation-driven transaction-manager="transactionManager"/>
xml实现:
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource">property>
bean>
<aop:config>
<aop:advisor advice-ref="txAdvice" pointcut="execution(* com.lu.Spring.service.*.*(..))">aop:advisor>
aop:config>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="get*" read-only="true"/>
<tx:method name="query*" read-only="true"/>
<tx:method name="find*" read-only="true"/>
<tx:method name="save*" read-only="false" rollback-for="java.lang.Exception" propagation="REQUIRES_NEW"/>
<tx:method name="update*" read-only="false" rollback-for="java.lang.Exception" propagation="REQUIRES_NEW"/>
<tx:method name="delete*" read-only="false" rollback-for="java.lang.Exception" propagation="REQUIRES_NEW"/>
tx:attributes>
tx:advice>