Spring框架(三)

目錄

一、JDBC模板技術概述

1.1 什么是JDBC模板

二、JdbcTemplate使用實戰

2.1?基礎使用(手動創建對象)

2.2?使用Spring管理模板類

2.3 使用開源連接池(Druid)

三、模擬轉賬開發

3.1 基礎實現

3.1.1 Service層

3.1.2?Dao層

3.1.3 配置文件

3.1.4?測試代碼

3.2 使用JdbcDaoSupport實現

3.2.1 DAO層改進

3.2.2 配置文件

3.2.3?測試代碼

四、Spring框架的事務管理

4.1 事務管理相關API

4.1.1 PlatformTransactionManager接口

4.1.2 TransactionDefinition接口

4.2 聲明式事務管理

4.2.1 配置文件方式

4.2.2 配置文件+注解方式

4.2.3 純注解方式

4.3?轉賬案例與事務管理

4.3.1 Service層

4.3.2 Dao層

4.3.3 測試代碼

4.4 事務傳播行為

4.5 事務隔離級別

總結


一、JDBC模板技術概述

1.1 什么是JDBC模板

Spring框架提供的JdbcTemplate類簡化了傳統JDBC開發流程,解決了以下痛點:

  • 自動管理連接資源(Connection/Statement/ResultSet)

  • 自動處理JDBC異常(將Checked異常轉換為RuntimeException)

  • 提供簡潔的API執行SQL語句

  • 支持事務管理

二、JdbcTemplate使用實戰

2.1?基礎使用(手動創建對象)

1. 環境搭建(創建 maven 工程,引入坐標依賴

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.qcby</groupId><artifactId>springAOP03</artifactId><version>1.0-SNAPSHOT</version><dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.0.2.RELEASE</version></dependency><dependency><groupId>commons-logging</groupId><artifactId>commons-logging</artifactId><version>1.2</version></dependency><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.12</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>5.0.2.RELEASE</version></dependency><dependency><groupId>aopalliance</groupId><artifactId>aopalliance</artifactId><version>1.0</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>5.0.2.RELEASE</version></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.8.13</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.25</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.0.2.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-tx</artifactId><version>5.0.2.RELEASE</version></dependency><!-- 三、Druid開源的連接池 --><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.10</version></dependency></dependencies></project>

2. 測試代碼

package com.qcby.demo1;import org.junit.Test;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;import java.util.List;
import java.util.Map;public class Demo1 {/*** 一、使用 new 對象方式完成*/@Testpublic void run1(){// 創建連接池對象,Spring 框架內置了連接池對象DriverManagerDataSource dataSource = new DriverManagerDataSource();// 設置 4 個參數dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");dataSource.setUrl("jdbc:mysql:///spring_db");dataSource.setUsername("root");dataSource.setPassword("12345");try {// 提供模板,創建對象JdbcTemplate template = new JdbcTemplate(dataSource);// 完成數據的增刪改查//1.新增
//            template.update("insert into account values (null,?,?)","耶耶 ",1000);
//            System.out.println("添加成功!");//2.刪除
//            template.update("delete from account where name = ? ","耶耶");
//            System.out.println("刪除成功!");//3.更新
//            template.update("update account set money=money-? where name = ? ",100.00,"可可");
//            System.out.println("更新成功!");//4.查詢List<Map<String, Object>> accounts=template.queryForList("select * from account");//遍歷結果集System.out.println("\n當前賬戶信息:");for (Map<String, Object> account:accounts){System.out.println("ID:"+ account.get("id") +";姓名:" + account.get("name") +";余額:" + account.get("money"));}}catch (Exception e){System.out.println("操作失敗!!!");e.printStackTrace();}}}

2.2?使用Spring管理模板類

1. 將數據源和模板類交給Spring容器管理

<?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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd"><!-- 使用Spring框架管理 --><!-- 二、Spring管理內置的連接池 demo1_1.java測試--><!-- 配置連接池 --><bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"><property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/><property name="url" value="jdbc:mysql:///spring_db" /><property name="username" value="root" /><property name="password" value="12345" /></bean><!--配置 jdbc 模板 --><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource" /></bean> </beans>

2. 測試代碼

package com.qcby.demo1;import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;import java.util.List;
import java.util.Map;@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value = "classpath:applicationContext_jdbc.xml")
public class Demo1_1 {@Autowiredprivate JdbcTemplate jdbcTemplate;/*** 測試的方式*/@Testpublic void run1(){try {jdbcTemplate.update("insert into account values (null,?,?)","圖圖",500);System.out.println("添加成功!");}catch (Exception e){e.printStackTrace();}}@Testpublic void run2(){try {jdbcTemplate.update("delete from account where name = ? ","圖圖");System.out.println("刪除成功!");}catch (Exception e){e.printStackTrace();}}@Testpublic void run3(){try {jdbcTemplate.update("update account set money=money-? where name = ? ",100.00,"可可");System.out.println("更新成功!");}catch (Exception e){e.printStackTrace();}}@Testpublic void run4(){try {List<Map<String, Object>> accounts=jdbcTemplate.queryForList("select * from account");//遍歷結果集System.out.println("\n當前賬戶信息:");for (Map<String, Object> account:accounts){System.out.println("ID:"+ account.get("id") +";姓名:" + account.get("name") +";余額:" + account.get("money"));}}catch (Exception e){e.printStackTrace();}}}

2.3 使用開源連接池(Druid)

1. 添加Druid依賴

<dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.10</version>
</dependency>

2. 創建jdbc.properties

jdbc.driverClassName=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql:///spring_db
jdbc.username=root
jdbc.password=12345

3. Spring配置

<?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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd"><!-- 三、Spring 框架管理開源的連接池  屬性文件:jdbc.properties--><!-- 第一種寫法 --><!-- 使用開源連接池<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"><property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/><property name="url" value="jdbc:mysql:///spring_db" /><property name="username" value="root" /><property name="password" value="12345" /></bean>--><!-- 加載屬性文件<bean id="placeholderConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"><property name="location" value="classpath:jdbc.properties" /></bean>--><!-- 第二種寫法:使用提供標簽的方式 --><!-- 引入屬性文件 --><context:property-placeholder location="classpath:jdbc.properties" /><!-- 加載屬性的文件 配置Druid數據源 --><bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"><property name="driverClassName" value="${jdbc.driverClassName}" /><property name="url" value="${jdbc.url}" /><property name="username" value="${jdbc.username}" /><property name="password" value="${jdbc.password}" /></bean><!-- 配置 jdbc 模板 --><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><!-- 注入屬性,set方法 --><property name="dataSource" ref="dataSource" /></bean></beans>

4. 測試

package com.qcby.demo1;import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value = "classpath:applicationContext_jdbc.xml")
public class Demo1_2 {@Autowiredprivate JdbcTemplate jdbcTemplate;/*** 測試的方式*/@Testpublic void run1(){jdbcTemplate.update("insert into account values (null,?,?)","熊四",800);System.out.println("新增成功!");}/*** 修改*/@Testpublic void run2(){jdbcTemplate.update("update account set name = ?,money = ? where id = ?","小鳳",100,7);System.out.println("修改成功!");}/*** 刪除*/@Testpublic void run3(){jdbcTemplate.update("delete from account where id = ?",9);System.out.println("刪除成功!");}/*** 通過 id 查詢*/@Testpublic void run4(){Account account = jdbcTemplate.queryForObject("select * from account where id = ?", new BeanMapper(), 6);System.out.println(account);}/*** 查詢所有的數據*/@Testpublic void run5(){List<Account> list = jdbcTemplate.query("select * from account", new BeanMapper());for (Account account : list) {System.out.println(account);}}
}/*** 實現類,用來進行數據封裝的*/
class BeanMapper implements RowMapper<Account> {/*** 是一行一行進行數據封裝的* @param resultSet* @param i* @return* @throws SQLException*/public Account mapRow(ResultSet resultSet, int i) throws SQLException {Account account = new Account();account.setId(resultSet.getInt("id"));account.setName(resultSet.getString("name"));account.setMoney(resultSet.getDouble("money"));return account;}}

三、模擬轉賬開發

3.1 基礎實現

3.1.1 Service層

package com.qcby.demo2.service;public interface AccountService {/*** 轉賬的方法* @param out 付款人* @param in 收款人* @param money 金額*/public void pay(String out,String in,double money);
}package com.qcby.demo2.service;import com.qcby.demo2.dao.AccountDao;public class AccountServiceImpl implements AccountService{private AccountDao accountDao;public void setAccountDao(AccountDao accountDao) {this.accountDao = accountDao;}/*** 轉賬方法* @param out 付款人* @param in 收款人* @param money 金額*/public void pay(String out, String in, double money) {// 調用 dao 方法accountDao.outMoney(out,money);accountDao.inMoney(in,money);}
}

3.1.2?Dao層

package com.qcby.demo2.dao;public interface AccountDao {/*** 付款* @param out* @param money*/public void outMoney(String out,double money);/*** 收款* @param in* @param money*/public void inMoney(String in,double money);}package com.qcby.demo2.dao;import org.springframework.jdbc.core.JdbcTemplate;public class AccountDaoImpl implements AccountDao{private JdbcTemplate jdbcTemplate;public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {this.jdbcTemplate = jdbcTemplate;}/*** 付款* @param out* @param money*/public void outMoney(String out, double money) {jdbcTemplate.update("update account set money = money - ? where name = ?",money,out);}/*** 收款* @param in* @param money*/public void inMoney(String in, double money) {jdbcTemplate.update("update account set money = money + ? where name = ?",money,in);}
}

3.1.3 配置文件

<?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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd"><!--第二種寫法:使用提供標簽的方式--><context:property-placeholder location="classpath:jdbc.properties" /><!--加載屬性的文件--><bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"><property name="driverClassName" value="${jdbc.driverClassName}" /><property name="url" value="${jdbc.url}" /><property name="username" value="${jdbc.username}" /><property name="password" value="${jdbc.password}" /></bean><!--配置 Jdbc 模板類--><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource" /></bean><!--配置 service--><bean id="accountService" class="com.qcby.demo2.service.AccountServiceImpl"><property name="accountDao" ref="accountDao"/></bean><!--配置 service--><bean id="accountDao" class="com.qcby.demo2.dao.AccountDaoImpl"><property name="jdbcTemplate" ref="jdbcTemplate" /></bean></beans>

3.1.4?測試代碼

package com.qcby.demo2;import com.qcby.demo2.service.AccountService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value = "classpath:applicationContext_dao1.xml")
public class Demo2 {@Autowiredprivate AccountService accountService;/*** 測試轉賬的方法*/@Testpublic void testPay(){accountService.pay("熊大","熊二",100);}}

3.2 使用JdbcDaoSupport實現

3.2.1 DAO層改進

package com.qcby.demo2.dao;import org.springframework.jdbc.core.support.JdbcDaoSupport;//extends JdbcDaoSupport
public class AccountDaoImpl1 extends JdbcDaoSupport implements AccountDao{/*** 付款* @param out* @param money*/public void outMoney(String out, double money) {this.getJdbcTemplate().update("update account set money = money - ? where name = ?",money,out);}/*** 收款* @param in* @param money*/public void inMoney(String in, double money) {this.getJdbcTemplate().update("update account set money = money + ? where name = ?",money,in);}
}

3.2.2 配置文件

<?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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd"><!--第二種寫法:使用提供標簽的方式--><context:property-placeholder location="classpath:jdbc.properties" /><!--加載屬性的文件--><bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"><property name="driverClassName" value="${jdbc.driverClassName}" /><property name="url" value="${jdbc.url}" /><property name="username" value="${jdbc.username}" /><property name="password" value="${jdbc.password}" /></bean><!--配置 Jdbc 模板類<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource" /></bean>--><!--配置 service--><bean id="accountService" class="com.qcby.demo2.service.AccountServiceImpl"><property name="accountDao" ref="accountDao"/></bean><!--配置 dao<bean id="accountDao" class="com.qcby.demo2.dao.AccountDaoImpl"><property name="jdbcTemplate" ref="jdbcTemplate" /></bean>--><!-- 在accountDaoImpl中extends JdbcDaoSupport --><bean id="accountDao" class="com.qcby.demo2.dao.AccountDaoImpl1"><property name="dataSource" ref="dataSource"/></bean></beans>

3.2.3?測試代碼

package com.qcby.demo2;import com.qcby.demo2.service.AccountService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value = "classpath:applicationContext_dao2.xml")
public class Demo2_1 {@Autowiredprivate AccountService accountService;/*** 測試轉賬的方法*/@Testpublic void testPay(){accountService.pay("熊大","熊二",100);}
}

四、Spring框架的事務管理

4.1 事務管理相關API

4.1.1 PlatformTransactionManager接口

這是Spring事務管理的核心接口,根據不同的持久層框架有不同的實現:

  • DataSourceTransactionManager:用于JDBC

  • HibernateTransactionManager:用于Hibernate

  • JpaTransactionManager:用于JPA

4.1.2 TransactionDefinition接口

定義事務屬性:

  • 事務隔離級別

  • 事務傳播行為

  • 事務超時時間

  • 是否只讀事務

4.2 聲明式事務管理

4.2.1 配置文件方式

<!-- applicationContext_1.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"xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsd"><!--第二種寫法:使用提供標簽的方式--><context:property-placeholder location="classpath:jdbc.properties" /><!--加載屬性的文件--><bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"><property name="driverClassName" value="${jdbc.driverClassName}" /><property name="url" value="${jdbc.url}" /><property name="username" value="${jdbc.username}" /><property name="password" value="${jdbc.password}" /></bean><!--配置平臺事務管理器--><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource" /></bean><!--配置事務的通知(沒有自己編寫切面類,通知方法也不是自己編寫,Spring框架提供的)--><tx:advice id="txAdvice" transaction-manager="transactionManager"><tx:attributes><!--對 pay 進行增強,設置隔離級別,傳播行為,超時的時間--><tx:method name="pay" isolation="DEFAULT" propagation="REQUIRED" /><tx:method name="find*" read-only="true" /></tx:attributes></tx:advice><!-- 配置 AOP 的增強 --><aop:config><!-- Spring 框架提供系統通知,使用 advisor 標簽 --><aop:advisor advice-ref="txAdvice" pointcut="execution(public * com.qcby.demo3.AccountServiceImpl.pay(..))" /></aop:config><!-- 配置 service --><bean id="accountService" class="com.qcby.demo3.AccountServiceImpl"><property name="accountDao" ref="accountDao"/></bean><!-- 配置 dao --><bean id="accountDao" class="com.qcby.demo3.AccountDaoImpl"><property name="dataSource" ref="dataSource" /></bean></beans>

4.2.2 配置文件+注解方式

<?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"xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsd"><!--開啟注解的掃描--><context:component-scan base-package="com.qcby.demo3" /><!--第二種寫法:使用提供標簽的方式--><context:property-placeholder location="classpath:jdbc.properties" /><!--加載屬性的文件--><bean id="dataSource"class="com.alibaba.druid.pool.DruidDataSource"><property name="driverClassName"value="${jdbc.driverClassName}" /><property name="url" value="${jdbc.url}" /><property name="username" value="${jdbc.username}" /><property name="password" value="${jdbc.password}" /></bean><!--配置平臺事務管理器--><bean id="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource" /></bean><!--配置 Jdbc 模板類--><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource" /></bean><!--開啟事務注解的支持--><tx:annotation-driven transaction-manager="transactionManager" /></beans>
package com.qcby.demo3;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;@Service
@Transactional(isolation = Isolation.DEFAULT)
public class AccountServiceImpl implements AccountService{@Autowiredprivate AccountDao accountDao;/*** 轉賬方法* @param out 付款人* @param in 收款人* @param money 金額*/public void pay(String out, String in, double money) {// 調用 dao 方法accountDao.outMoney(out,money);// int a = 10 / 0;accountDao.inMoney(in,money);// 模擬在轉賬過程中發生異常//int a = 10 / 0;}
}

4.2.3 純注解方式

package com.qcby.demo3;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;import javax.annotation.Resource;
import javax.sql.DataSource;/*** 配置類* @author Administrator*/
@Configuration
@ComponentScan(basePackages="com.qcby.demo3")
@EnableTransactionManagement // 開啟事務注解
public class SpringConfig {/*** @return* @throws Exception*/@Bean(name="dataSource")public DataSource createDataSource() throws Exception{// 創建連接池對象,Spring 框架內置了連接池對象DriverManagerDataSource dataSource = new DriverManagerDataSource();// 設置 4 個參數dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");dataSource.setUrl("jdbc:mysql:///spring_db");dataSource.setUsername("root");dataSource.setPassword("12345");return dataSource;}/*** 創建模板對象* @return*/@Resource(name="dataSource") // 不僅可以作用在屬性上,也可以作用方法上。@Bean(name="jdbcTemplate") // 把 JdbcTemplate 保存到 IOC容器中public JdbcTemplate createJdbcTemplate(DataSource dataSource){JdbcTemplate template = new JdbcTemplate(dataSource);return template;}/*** 創建平臺事務管理器對象* @param dataSource* @return*/@Resource(name="dataSource")@Bean(name="transactionManager")public PlatformTransactionManagercreateTransactionManager(DataSource dataSource){DataSourceTransactionManager manager = new DataSourceTransactionManager(dataSource);return manager;}}

4.3?轉賬案例與事務管理

4.3.1 Service層

package com.qcby.demo3;public interface AccountService {public void pay(String out, String in, double money);
}package com.qcby.demo3;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;@Service
@Transactional(isolation = Isolation.DEFAULT)
public class AccountServiceImpl implements AccountService{@Autowiredprivate AccountDao accountDao;/*** 轉賬方法* @param out 付款人* @param in 收款人* @param money 金額*/public void pay(String out, String in, double money) {// 調用 dao 方法accountDao.outMoney(out,money);// int a = 10 / 0;accountDao.inMoney(in,money);// 模擬在轉賬過程中發生異常//int a = 10 / 0;}
}

4.3.2 Dao層

package com.qcby.demo3;public interface AccountDao {/*** 付款* @param out* @param money*/public void outMoney(String out, double money);/*** 收款* @param in* @param money*/public void inMoney(String in, double money);}package com.qcby.demo3;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;@Repository
public class AccountDaoImpl implements AccountDao {@Autowiredprivate JdbcTemplate jdbcTemplate;/*** 付款* @param out* @param money*/public void outMoney(String out, double money) {jdbcTemplate.update("update account set money = money - ? where name = ?",money,out);}/*** 收款* @param in* @param money*/public void inMoney(String in, double money) {jdbcTemplate.update("update account set money = money + ? where name = ?",money,in);}
}

4.3.3 測試代碼

package com.qcby.demo3;import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;// 1.配置文件+注解方式
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value = "classpath:applicationContext_2.xml")// 2.純注解方式
//@RunWith(SpringJUnit4ClassRunner.class)
//@ContextConfiguration(classes = SpringConfig.class)public class Demo3 {@Autowiredprivate com.qcby.demo3.AccountService accountService;/*** 測試轉賬的方法*/@Testpublic void testPay() {try {accountService.pay("熊大", "熊二", 100);System.out.println("轉賬成功!!!");} catch (Exception e) {e.printStackTrace();System.out.println("轉賬失敗,事務已回滾!");}}
}

4.4 事務傳播行為

Spring定義了7種事務傳播行為:

  1. ??PROPAGATION_REQUIRED??(默認):如果當前存在事務,則加入該事務;如果當前沒有事務,則創建一個新的事務。

  2. ??PROPAGATION_SUPPORTS??:如果當前存在事務,則加入該事務;如果當前沒有事務,則以非事務的方式繼續運行。

  3. ??PROPAGATION_MANDATORY??:如果當前存在事務,則加入該事務;如果當前沒有事務,則拋出異常。

  4. ??PROPAGATION_REQUIRES_NEW??:創建一個新的事務,如果當前存在事務,則把當前事務掛起。

  5. ??PROPAGATION_NOT_SUPPORTED??:以非事務方式運行,如果當前存在事務,則把當前事務掛起。

  6. ??PROPAGATION_NEVER??:以非事務方式運行,如果當前存在事務,則拋出異常。

  7. ??PROPAGATION_NESTED??:如果當前存在事務,則在嵌套事務內執行;如果當前沒有事務,則創建一個新的事務。

4.5 事務隔離級別

Spring支持以下隔離級別:

  1. ??ISOLATION_DEFAULT??:使用底層數據庫的默認隔離級別。

  2. ??ISOLATION_READ_UNCOMMITTED??:允許讀取未提交的數據變更,可能導致臟讀、幻讀或不可重復讀。

  3. ??ISOLATION_READ_COMMITTED??:只能讀取已提交的數據,防止臟讀,但可能發生幻讀和不可重復讀。

  4. ??ISOLATION_REPEATABLE_READ??:對同一字段的多次讀取結果都是一致的,除非數據被當前事務修改,防止臟讀和不可重復讀,但可能發生幻讀。

  5. ??ISOLATION_SERIALIZABLE??:最高的隔離級別,完全服從ACID的隔離級別,確保事務串行執行,防止臟讀、不可重復讀和幻讀。

總結

????????本文詳細介紹了Spring框架中JDBC模板技術的使用方法,Spring的JDBC模板技術大大簡化了數據庫操作代碼,使開發者能夠更專注于業務邏輯而非底層數據庫交互細節。聲明式事務管理則提供了靈活的事務控制方式,確保數據的一致性和完整性。

????????在實際開發中,建議優先使用注解方式配置事務,它更簡潔直觀。對于復雜的事務需求,可以結合使用@Transactional的各種屬性進行精細化控制。同時,合理選擇事務隔離級別和傳播行為,可以在保證數據安全的前提下提高系統性能。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/905871.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/905871.shtml
英文地址,請注明出處:http://en.pswp.cn/news/905871.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

[計算機網絡]網絡層

文章目錄 408考研大綱IPV4數據報格式協議: IPv4 地址DHCP協議IP組播 408考研大綱 IPV4數據報格式 協議: 1:ICMP 6:TCP 17:UDP IPv4 地址 特殊IP 網絡號全1又稱直接廣播地址&#xff0c;32位全1又稱受限廣播地址 因為255.255.255.255只能在本網絡內廣播&#xff0c;路由器不…

影樓精修-膚色統一算法解析

注意&#xff1a;本文樣例圖片為了避免侵權&#xff0c;均使用AIGC生成&#xff1b; 本文介紹影樓精修中膚色統一算法的實現方案&#xff0c;并以像素蛋糕為例&#xff0c;進行分析說明。 膚色統一就是將人像照片中皮膚區域的顏色進行統一&#xff0c;看起來顏色均勻一致&…

計算機網絡:什么是計算機網絡?它的定義和組成是什么?

計算機網絡是指通過通信設備和傳輸介質&#xff0c;將分布在不同地理位置的計算機、終端設備及其他網絡設備連接起來&#xff0c;實現資源共享、數據傳輸和協同工作的系統。其核心目標是使設備之間能夠高效、可靠地交換信息。 關鍵組成部分 硬件設備 終端設備&#xff1a;如計算…

深度學習---獲取模型中間層輸出的意義

一、什么是 Hook&#xff08;鉤子函數&#xff09;&#xff1f; 在 PyTorch 中&#xff0c;Hook 是一種機制&#xff0c;允許我們在模型的前向傳播或反向傳播過程中&#xff0c;插入自定義的函數&#xff0c;用來觀察或修改中間數據。 最常用的 hook 是 forward hook&#xf…

存儲器上如何存儲1和0

在計算機存儲器中&#xff0c;數據最終以**二進制形式&#xff08;0和1&#xff09;**存儲&#xff0c;這是由硬件特性和電子電路的物理特性決定的。以下是具體存儲方式的詳細解析&#xff1a; 一、存儲的物理基礎&#xff1a;半導體電路與電平信號 計算機存儲器&#xff08;…

Qt中的RCC

Qt資源系統(Qt resource system)是一種獨立于平臺的機制&#xff0c;用于在應用程序中傳輸資源文件。如果你的應用程序始終需要一組特定的文件(例如圖標、翻譯文件和圖片)&#xff0c;并且你不想使用特定于系統的方式來打包和定位這些資源&#xff0c;則可以使用Qt資源系統。 最…

2918. 數組的最小相等和

2918. 數組的最小相等和 題目鏈接&#xff1a;2918. 數組的最小相等和 代碼如下&#xff1a; class Solution { public:long long minSum(vector<int>& nums1, vector<int>& nums2) {auto [sum1, zero1] calc(nums1);auto [sum2, zero2] calc(nums2);i…

使用 Docker 部署 OnlyOffice

使用 Docker 部署 OnlyOffice 在如今容器化技術盛行的時代&#xff0c;Docker 已成為應用快速部署和隔離的最佳選擇。OnlyOffice 作為一款功能強大的在線辦公套件&#xff0c;通過 Docker 部署不僅能夠簡化安裝和維護流程&#xff0c;還能在不同環境中保持一致性&#xff0c;極…

DDD領域驅動介紹

&#x1f4d5;我是廖志偉&#xff0c;一名Java開發工程師、《Java項目實戰——深入理解大型互聯網企業通用技術》&#xff08;基礎篇&#xff09;、&#xff08;進階篇&#xff09;、&#xff08;架構篇&#xff09;清華大學出版社簽約作家、Java領域優質創作者、CSDN博客專家、…

前端 CSS 樣式書寫與選擇器 基礎知識

1.CSS介紹 CSS是Cascading Style Sheet的縮寫&#xff0c;中文意思為"層疊樣式表"&#xff0c;它是網頁的裝飾者&#xff0c;用來修飾各標簽 排版(大小、邊距、背景、位置等)、改變字體的樣式(字體大小、字體顏色、對齊方式等)。 2.CSS書寫位置 2.1 樣式表特征 層…

鴻蒙 從打開一個新窗口到Stage模型的UIAbility組件

打開一個新的窗口 我們首先來實現如何在一個應用中打開一個新窗口&#xff0c;使用的模型是 Stage 模型 在項目文件里&#xff0c;新建一個 newWindow.ets 新文件 src/main/ets/pages/newWindow.ets newWindow.ets文件里面隨便寫點什么都行&#xff0c;這里是第一步創建的文件…

Linux的日志管理

日志管理服務rsyslogd 配置文件 | 日志類型 | 說明 | | -------------------- | ----------------------------------- | | auth | pam產生的日志 | | authpriv | ssh、ftp等…

【PhysUnits】4.1 類型級比特位實現解釋(boolean.rs)

一、源碼 該代碼實現了一個類型級(type-level)的布爾系統&#xff0c;允許在編譯時進行布爾運算。 //! 類型級比特位實現 //! //! 這些是基礎的比特位類型&#xff0c;作為本庫中其他數值類型的構建基礎 //! //! 已實現的**類型運算符**&#xff1a; //! //! - 來自 core::op…

【docker】--數據卷掛載

文章目錄 存儲卷管理創建存儲卷查看存儲卷詳細信息查看存儲卷刪除存儲卷 存儲卷管理 # 目錄掛載 docker run -v 本機目錄&#xff1a;容器目錄#1&#xff09; # 將容器內部的 “/usr/share/nginx/html” 進行持久化掛載 會在宿主機生成一個隨機的存儲卷 docker run -v /usr/sh…

雙重差分模型學習筆記2(理論)

【DID最全總結】90分鐘帶你速通雙重差分&#xff01;_嗶哩嗶哩_bilibili 目錄 一、staggered DID 交錯雙重差分 二、動態雙重差分 動態雙重差分法公式解釋 符號解釋 公式邏輯與案例 與標準DID的區別 總結 “雙減” 政策動態差分模型 &#xff08;一&#xff09;設定處…

預測模型開發與評估:基于機器學習的數據分析實踐

在當今數據驅動的時代&#xff0c;預測模型已成為各行各業決策制定的核心工具。本文將分享我在COMP5310課程項目中開發預測模型的經驗&#xff0c;探討從數據清洗到模型優化的完整過程&#xff0c;并提供詳細的技術實現代碼。 ## 研究問題與數據集 ### 研究問題 我們的研究聚焦…

Java 并發編程歸納總結(可重入鎖 | JMM | synchronized 實現原理)

1、鎖的可重入 一個不可重入的鎖&#xff0c;搶占該鎖的方法遞歸調用自己&#xff0c;或者兩個持有該鎖的方法之間發生調用&#xff0c;都會發生死鎖。以之前實現的顯式獨占鎖為例&#xff0c;在遞歸調用時會發生死鎖&#xff1a; public class MyLock implements Lock {/* 僅…

數據治理域——數據同步設計

摘要 本文主要介紹了數據同步的多種方式&#xff0c;包括直連同步、數據文件同步和數據庫日志解析同步。每種方式都有其適用場景、技術特點、優缺點以及適用的數據類型和實時性要求。文章還詳細探討了數據直連同步的特點、工作原理、優點、缺點、適用場景等&#xff0c;并對數…

AI人工智能在教育領域的應用

AI人工智能在教育領域的應用 隨著科技的飛速發展&#xff0c;人工智能&#xff08;AI&#xff09;逐漸成為推動教育變革的重要力量。AI在教育領域的應用不僅改變了傳統的教學模式&#xff0c;還為個性化學習、教育資源優化和教育管理帶來了前所未有的機遇。本文將從多個方面探…

ohttps開啟群暉ssl證書自動更新

開啟群暉ssl證書自動更新OHTTPS ohttps是一個免費自動簽發ssl證書、管理、部署的項目。 https://ohttps.com 本文舉例以ohttps項目自動部署、更新群暉的ssl證書。 部署 簽發證書 打開ohttps-證書管理-創建證書-按你實際情況創建證書。創建部署節點 打開Ohttps-部署節點-添加…