Spring框架的JDBC模板技術和事務管理

SpringJDBC

  • JDBC模板技術概述
  • JDBC的模板類的使用
  • Spring框架的事務管理
    • 配置文件方式
    • 半注解的方式
    • 純注解的方式

JDBC模板技術概述

什么是 JDBC 模板技術?
JDBC 模板技術是 Spring 框架為簡化持久層(數據庫操作)編程而提供的一種封裝機制,核心類為JdbcTemplate。它基于模板設計模式,將 JDBC 操作中重復、繁瑣的底層代碼進行封裝,讓開發者只需關注核心業務邏輯(如 SQL 語句編寫、結果集處理)。

模板(template)技術的設計思想:
Spring 框架中提供了一系列以XxxTemplate命名的模板類(如JdbcTemplate、HibernateTemplate、RedisTemplate等),其核心思想是:將固定流程的代碼封裝為模板,將可變的業務邏輯通過回調接口暴露給開發者。

對于 JDBC 操作而言,固定流程包括:獲取數據庫連接(Connection)、創建 SQL 執行對象(Statement/PreparedStatement)、執行 SQL 語句、處理異常(如SQLException)、釋放資源(關閉ResultSet、Statement、Connection)
JdbcTemplate將這些固定流程封裝,開發者只需提供 SQL 語句和結果處理邏輯即可。

JDBC的模板類的使用

創建 maven java 工程,引入坐標依賴

    <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>5.1.6</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></dependencies>

new 對象的方式

編寫測試代碼

import org.junit.Test;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;public class Demo {/*** 使用的是 Spring 框架內置的連接池* 使用 new 對象方式完成*/@Testpublic void run1(){// 創建連接池對象,Spring 框架內置了連接池對象DriverManagerDataSource dataSource = new DriverManagerDataSource();// 設置 4 個參數dataSource.setDriverClassName("com.mysql.jdbc.Driver");dataSource.setUrl("jdbc:mysql:///ssm");dataSource.setUsername("root");dataSource.setPassword("root");// 提供模板,創建對象JdbcTemplate template = new JdbcTemplate(dataSource);// 完成數據的增刪改查template.update("insert into account values (null,?,?)","熊大 ",1000);}
}

在這里插入圖片描述

使用 Spring 框架管理模板類

applicationContext_jdbc.xml

    <!--配置連接池--><bean id="dataSource"class="org.springframework.jdbc.datasource.DriverManagerDataSource"><property name="driverClassName" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql:///ssm" /><property name="username" value="root" /><property name="password" value="root" /></bean><!--配置 jdbc 模板--><bean id="jdbcTemplate"class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource" /></bean>
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;@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value = "classpath:applicationContext_jdbc.xml")
public class Demo1 {@Autowiredprivate JdbcTemplate jdbcTemplate;/*** 測試的方式* 使用開源連接池*/@Testpublic void run1(){jdbcTemplate.update("insert into account values (null,?,?)"," 小麗",500);}
}

在這里插入圖片描述

Spring 框架管理開源的連接池

配置開源的連接池,使用 Druid 開源的連接池,引入坐標依賴

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

將數據庫連接的信息配置到屬性文件中

在這里插入圖片描述

配置數據庫訪問相關的組件

    <!--加載屬性文件--><bean id="placeholderConfigurer"class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"><!-- 指定屬性文件路徑:classpath表示從類路徑下查找 --><property name="location" value="classpath:jdbc.properties" /></bean><!--加載屬性文件第二種寫法:使用提供標簽的方式--><!--<context:property-placeholderlocation="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>
  • 加載外部屬性文件(數據庫配置信息)
    <bean id="placeholderConfigurer"> 定義了PropertyPlaceholderConfigurer組件,作用是加載類路徑(classpath)下的jdbc.properties屬性文件,通過這種方式,數據庫連接信息可以寫在外部的jdbc.properties文件中,而非硬編碼在 XML 里,便于后期修改和維護。<context:property-placeholder> 是另一種更簡潔的加載屬性文件的方式,功能完全一致。
  • 配置數據庫連接池(Druid)
    <bean id="dataSource"> 定義了阿里巴巴的DruidDataSource(德魯伊連接池),其中的driverClassName、url、username、password屬性值使用 ${key} 格式的占位符,這些占位符會被前面加載的jdbc.properties文件中對應的鍵值對替換,通過配置連接池,應用可以高效地管理數據庫連接,避免頻繁創建 / 關閉連接的性能損耗。
  • 配置 Spring JDBC 模板
    <bean id="jdbcTemplate"> 定義了 Spring 提供的JdbcTemplate組件,這是一個簡化 JDBC 操作的模板類,通過dataSource屬性引用了前面定義的dataSource(數據庫連接池),從而關聯到數據庫。

通過這段配置,Spring 容器會自動讀取外部 jdbc.properties 中的數據庫配置、初始化 Druid 連接池管理數據庫連接、初始化 JdbcTemplate 并關聯連接池。最終,應用可以直接從 Spring 容器中獲取 jdbcTemplate 對象,便捷地進行數據庫操作,同時數據庫配置可通過修改 jdbc.properties 靈活調整,無需改動 XML 配置。

增刪改查代碼編寫

import com.qcby.Model.Account;
import com.qcby.Model.BeanMapper;
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;@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value = "classpath:applicationContext_jdbc.xml")
public class Demo2 {@Autowiredprivate JdbcTemplate jdbcTemplate;/*** 測試的方式* 加載屬性文件的方式*/@Testpublic void run1(){jdbcTemplate.update("insert into account values (null,?,?)"," 熊四",800);}/*** 修改*/@Testpublic void run2(){jdbcTemplate.update("update account set name = ?,money = ? where id = ?","光頭強",100,7);}/*** 刪除*/@Testpublic void run3(){jdbcTemplate.update("delete from account where id = ?",7);}/*** 通過 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);}}
}
public class Account {private int id;private String name;private double money;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 double getMoney() {return money;}public void setMoney(double money) {this.money = money;}@Overridepublic String toString() {return "Account{" +"id=" + id +", name='" + name + '\'' +", money=" + money +'}';}
}

Account類是account數據庫表的映射實體類,屬性對應數據表中的字段,作為數據載體,封裝從數據庫查詢到的記錄,或封裝要插入或更新的數據。

import org.springframework.jdbc.core.RowMapper;import java.sql.ResultSet;
import java.sql.SQLException;/*** 實現類,用來進行數據封裝的*/
public class BeanMapper implements RowMapper<Account>{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;}
}

BeanMapper 類是結果集映射器的實現類,它實現了Spring JDBC的 RowMapper 函數式接口并指定泛型為 Account,核心職責是將數據庫查詢返回的 ResultSet 結果集逐行轉換為 Account 類型對象。
在這里插入圖片描述

RowMapper 接口僅定義抽象方法 mapRow,BeanMapper 通過實現該方法定義具體行映射邏輯:當 JdbcTemplate 執行查詢并遍歷 ResultSet 時,每處理一行數據便調用 mapRow 方法,傳入當前行 ResultSet 實例及行索引;mapRow 從結果集中提取對應字段值,賦值給新創建的 Account 對象并返回。
此實現解決了數據庫結果集與Java對象的映射問題,使 JdbcTemplate 查詢可直接返回 Account 對象或其集合,便于以面向對象方式處理查詢結果。

實現效果:

在這里插入圖片描述

使用JDBC模板操作數據庫實現模擬轉賬開發

Service 層代碼的編寫

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

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);
}
import com.qcby.dao.AccountDao;
import org.springframework.jdbc.core.JdbcTemplate;public class AccountDaoImpl implements AccountDao{// 依賴Spring的JdbcTemplate,通過JdbcTemplate執行具體的SQL語句,操作數據庫private JdbcTemplate jdbcTemplate;//提供setter方法,讓Spring注入JdbcTemplatepublic 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);}
}

配置文件代碼編寫

    <!--加載jdbc.properties文件,使用提供標簽的方式--><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模板類,創建JdbcTemplate對象,并注入dataSource--><bean id="jdbcTemplate"class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource" /></bean><!--配置Service對象,注入Dao--><bean id="accountDao" class="com.qcby.dao.impl.AccountDaoImpl"><property name="jdbcTemplate" ref="jdbcTemplate" /></bean><!--配置Dao對象,注入JdbcTemplate--><bean id="accountService" class="com.qcby.service.impl.AccountServiceImpl"><property name="accountDao" ref="accountDao"/></bean>

測試代碼編寫

import com.qcby.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 Demo3 {@Autowiredprivate AccountService accountService;/*** 測試轉賬的方法*/@Testpublic void testPay(){accountService.pay("熊大","熊二",100);}
}

Dao 層編寫的第二種方式

import com.qcby.dao.AccountDao;
import org.springframework.jdbc.core.support.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);}
}

AccountDaoImpl1 繼承了 Spring 提供的 JdbcDaoSupport 類,該類是 Spring 為簡化 JDBC 操作提供的工具類,內部已封裝了 JdbcTemplate 對象,子類可直接通過 getJdbcTemplate() 方法獲取 JdbcTemplate,無需手動定義和注入,減少重復代碼。

配置文件編寫

    <!--第二種寫法:使用提供標簽的方式--><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><!--配置 service--><bean id="accountServicePx"class="com.qcby.service.impl.AccountServiceImpl"><property name="accountDao" ref="accountDao"/></bean><bean id="accountDao" class="com.qcby.dao.impl.AccountDaoImpl1"><property name="dataSource" ref="dataSource" /></bean>

編寫測試類

import com.qcby.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 Demo4 {@Autowiredprivate AccountService accountService;/*** 測試轉賬的方法*/@Testpublic void testPay(){accountService.pay("熊大","熊二",100);}
}

Spring框架的事務管理

核心接口與實現類
平臺事務管理器:PlatformTransactionManager
PlatformTransactionManager 是 Spring 事務管理的核心接口,定義了事務操作的標準規范,是事務執行器的角色。它屏蔽了不同持久層框架的事務差異,開發者需根據實際使用的持久層技術選擇對應的實現類。Spring 為不同的持久層框架提供了對應的 PlatformTransactionManager 實現
如果使用的 Spring 的 JDBC 模板或者 MyBatis 框架,需要選擇 DataSourceTransactionManager 實現類
如果使用的是 Hibernate 的框架,需要選擇 HibernateTransactionManager 實現類

接口方法如下:
void commit(TransactionStatus status)
void rollback(TransactionStatus status)

事務規則定義:TransactionDefinition
TransactionDefinition 是事務規則描述的接口,定義了事務隔離級別、事務傳播行為,這些屬性決定了事務的運行規則。

配置文件方式

<?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-placeholderlocation="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.service.impl.AccountServiceImpl1.pay(..))" /></aop:config><!--配置 service--><bean id="accountServicePx"class="com.qcby.service.impl.AccountServiceImpl"><property name="accountDao" ref="accountDao"/></bean><!--配置 dao --><bean id="accountDao" class="com.qcby.dao.impl.AccountDaoImpl1"><property name="dataSource" ref="dataSource" /></bean>
</beans>

這段 XML 配置文件是Spring 框架基于 XML 實現聲明式事務管理的核心配置,同時整合了數據庫連接、數據訪問層、業務邏輯層的 Bean 定義,最終實現對AccountServiceImpl類中pay方法的事務增強。
tx:advice 是 Spring 提供的事務通知組件,無需手動編寫切面類和通知方法,是事務規則的載體,transaction-manager=“transactionManager” 關聯配置的事務管理器,通知需通過管理器執行事務操作,tx:attributes 定義哪些方法需要事務及事務的具體規則。

aop:advisor 是 Spring 的通知器,專門用于綁定事務通知(tx:advice)和切入點,區別于普通 AOP 的 aop:aspect,advisor 是 Spring 為事務等系統級通知提供的簡化標簽。advice-ref=“txAdvice” 關聯定義的事務通知,pointcut=“execution(…)” 定義切入點。

測試

import com.qcby.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_tx.xml")
public class Demo5 {@Autowiredprivate AccountService accountService;/*** 測試轉賬的方法*/@Testpublic void testPay(){accountService.pay("熊大","熊二",100);}
}

半注解的方式

<?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: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/txhttp://www.springframework.org/schema/tx/spring-tx.xsd"><!--開啟注解的掃描--><context:component-scan base-package="com.qcby" /><!--第二種寫法:使用提供標簽的方式--><context:property-placeholderlocation="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>

Dao 層代碼

@Repository("accountDao_1")
public class AccountDaoImpl_1 implements AccountDao {// 依賴Spring的JdbcTemplate,通過JdbcTemplate執行具體的SQL語句,操作數據庫private JdbcTemplate jdbcTemplate;//提供setter方法,讓Spring注入JdbcTemplate@Autowiredpublic 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);}
}

Service 層代碼

import com.qcby.dao.AccountDao;
import com.qcby.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
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_1 implements AccountService{@Autowired@Qualifier("accountDao_1")private AccountDao accountDao;/*** 轉賬方法* @param out 付款人* @param in 收款人* @param money 金額*/public void pay(String out, String in, double money) {// 調用 dao 方法accountDao.outMoney(out,money);// 模擬異常//int a = 1/0;accountDao.inMoney(in,money);}
}

測試

import com.qcby.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_tx1.xml")
public class Demo6 {@Autowiredprivate AccountService accountService;/*** 測試轉賬的方法*/@Testpublic void testPay(){accountService.pay("熊大","熊二",100);}
}

純注解的方式

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")
@EnableTransactionManagement // 開啟事務注解
public class SpringConfig {@Bean(name = "dataSource")public DataSource createDataSource() throws Exception {// 創建連接池對象,Spring 框架內置了連接池對象DriverManagerDataSource dataSource = new DriverManagerDataSource();// 設置 4 個參數dataSource.setDriverClassName("com.mysql.jdbc.Driver");dataSource.setUrl("jdbc:mysql:///ssm");dataSource.setUsername("root");dataSource.setPassword("root");return dataSource;}/*** 創建模板對象*/@Resource(name = "dataSource") // 不僅可以作用在屬性上,也可以作用方法上。@Bean(name = "jdbcTemplate") // 把 JdbcTemplate 保存到 IOC容器中public JdbcTemplate createJdbcTemplate(DataSource dataSource) {JdbcTemplate template = new JdbcTemplate(dataSource);return template;}/*** 創建平臺事務管理器對象*/@Resource(name = "dataSource")@Bean(name = "transactionManager")public PlatformTransactionManagercreateTransactionManager(DataSource dataSource) {DataSourceTransactionManager manager = new DataSourceTransactionManager(dataSource);return manager;}
}

@Configuration:標識當前類是一個 Spring 配置類,Spring 會掃描并解析其中的配置;
@ComponentScan(basePackages=“com.qcby”):開啟組件掃描,掃描指定包及其子包下的類,被@Component等注解標記的類會被自動注冊到 Spring 容器中;
@EnableTransactionManagement:半注解和純注解形式需要開啟 Spring 的注解式事務管理支持,與 XML 配置中的<tx:annotation-driven/> 作用相同;
創建并配置數據源DataSource,用于建立與數據庫的連接;創建JdbcTemplate實例,并注冊到 Spring 容器中,@Resource(name = “dataSource”) 用于指定注入名為 dataSource 的 Bean 到方法參數 dataSource 中,該注解不僅可以作用在屬性上,也可以以作用方法上;創建平臺事務管理器PlatformTransactionManager,是 Spring 事務管理的核心組件。使用DataSourceTransactionManager(基于數據源的事務管理器),同樣依賴dataSource,因為事務需要綁定數據庫連接。

測試

import com.qcby.config.SpringConfig;
import com.qcby.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(classes = SpringConfig.class)
public class Demo7 {// 注入要測試的Service@Autowiredprivate AccountService accountService;@Testpublic void testNormalPay() {accountService.pay("熊大", "熊二", 100);System.out.println("正常轉賬測試完成");}
}

在這里插入圖片描述

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

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

相關文章

將文件部署到受管主機

目錄 1.ansible.builtin中用于創建、更新或刪除多行文本塊的模塊是什么 2.copy模塊的作用 3.fetch模塊的作用 4.file模塊的作用 5.lineinfile模塊的作用 6.stat模塊的作用 7.要確保受管主機上存在文件&#xff0c;類似touch命令功能&#xff0c;還能設置權限等的模塊及操作是怎…

Dell PowerEdge R620 服務器內存和硬盤罷工了

文章目錄前言調查原因查找解決方案硬盤問題內存問題總結前言 月黑風高夜&#xff0c;服務宕機時。做服務端技術的&#xff0c;誰還沒半夜遇到個服務掛掉的情況&#xff0c;而像我這種半兼職網管的工作&#xff0c;遇到機器問題的概率也就更大了&#xff0c;本來周五晚上寫完總…

2025:SourceTree 啟用/禁用Mercurial 或 Git,像素級細節

最近使用Git管理工具的時候&#xff0c;發現還是SourceTree好用些&#xff0c;但是使用SourceTree帶來一個問題&#xff1a;就是每次在重新打開SourceTree的時候&#xff0c;都會重新下載Mercurial.zip文件&#xff0c;查了一下&#xff0c;一般情況下我們是不需要使用Mercuria…

安卓 Google Maps 的使用和開發步驟

文章目錄1. main2. Android 谷歌地圖3. 源碼Reference1. main 在國內選擇的SDK可以是高德、百度、騰訊、xxxx等&#xff0c;但在國外&#xff0c;你首選是谷歌&#xff0c;因此要進行Google地圖的開發你首先要解決下面三個問題 VPN Google賬號 信用卡American Express&#x…

Linux -- 應用層協議Http

1.HTTP背景知識 HTTP協議&#xff1a;HTTP&#xff08;HyperText Transfer Protocol&#xff0c;超文本傳輸協議&#xff09;的本質是運行在 TCP/IP 協議族之上的 “應用層協議”&#xff0c;核心作用是定義客戶端&#xff08;如瀏覽器、APP&#xff09;與服務器之間的 “數據…

R 語言本身并不直接支持 Python 中 f“{series_matrix}.txt“ 這樣的字符串字面量格式化(f-string)語法 glue函數

R 語言本身并不直接支持 Python 中 f"{series_matrix}.txt" 這樣的字符串字面量格式化&#xff08;f-string&#xff09;語法。 在 R 中&#xff0c;要實現字符串拼接或格式化&#xff0c;你需要使用其他方法。下表對比了 Python f-string 和 R 中常見對應方法的主要…

【AI智能體】亮數據MCP Server × Dify:AI智能體獲取實時影音數據就是這么簡單

文章目錄一、引言&#xff1a;AI 應用與實時影音數據的融合價值1、傳統采集方式的痛點2、MCP Server 的創新價值二、亮數據 MCP Server 概覽1、什么是 MCP Server&#xff1f;2、支持的影音平臺和API接口3、產品特色亮點三、業務場景示例設計1、選定場景&#xff1a;競品分析與…

從《Attention Is All You Need》深入理解Transformer

2017年的《Attention Is All You Need》論文提出的Transformer架構&#xff0c;不僅徹底改變了自然語言處理的格局&#xff0c;更為現代人工智能的發展奠定了堅實基礎。本文將帶你深入解析這一劃時代模型的核心思想、技術細節及其深遠影響。&#x1f504; 一、背景與動機&#…

【08】AI輔助編程完整的安卓二次商業實戰-修改消息聊天框背景色-觸發聊天讓程序異常終止bug牽涉更多聊天消息發送優化處理-優雅草卓伊凡

【08】AI輔助編程完整的安卓二次商業實戰-修改消息聊天框背景色-觸發聊天讓程序異常終止bug牽涉更多聊天消息發送優化處理-優雅草卓伊凡引言本次二開布局沒有變&#xff0c;但是下一次整體布局會有變&#xff0c;不過本次開發發現朋友圈跳轉功能的流程步驟也做了一定的變化。原…

心理調適與情緒管理實訓室:支撐康養旅游人才心理能力培養

在康養休閑旅游服務專業的教學體系中&#xff0c;心理調適與情緒管理實訓室作為關鍵教學場所&#xff0c;承擔著培養學生心理服務能力、情緒疏導技能和人際溝通素養的重要任務。隨著社會對康養旅游服務質量要求的提升&#xff0c;具備心理調適與情緒管理能力的專業人才日益受到…

Oracle sql tuning guide 翻譯 Part 6 --- 優化器控制

第五部分優化器控制你可以用提示信息和初始化參數來影響優化器的判斷和運作方式。Influencing the Optimizer Optimizer defaults are adequate for most operations, but not all.In some cases you may have information unknown to the optimizer, or need to tune the opti…

pthread_mutex_lock函數深度解析

摘要 pthread_mutex_lock是POSIX線程庫中用于實現線程同步的核心函數&#xff0c;它通過對互斥鎖的加鎖操作來確保多個線程對共享資源的安全訪問。本文從互斥鎖的歷史背景和發展脈絡入手&#xff0c;詳細解析了pthread_mutex_lock函數的設計理念、實現機制和使用場景。通過生產…

qt QBoxSet詳解

1、概述QBoxSet 類代表箱形圖中的一個條目。箱形條目是范圍和由五個不同值構成的三個中值的圖形表示。這五個值分別是&#xff1a;下極值、下四分位數、中位數、上四分位數和上極值。QBoxSet 提供了多種方法來設置和獲取這些值&#xff0c;并且可以與 QBoxPlotSeries 和 QChart…

機器學習勢函數(MLPF)入門:用DeePMD-kit加速億級原子模擬

點擊 “AladdinEdu&#xff0c;同學們用得起的【H卡】算力平臺”&#xff0c;注冊即送-H卡級別算力&#xff0c;80G大顯存&#xff0c;按量計費&#xff0c;靈活彈性&#xff0c;頂級配置&#xff0c;學生更享專屬優惠。 引言&#xff1a;從傳統分子模擬到機器學習勢函數的革命…

制作uniapp需要的storyboard全屏ios啟動圖

//鎖定豎屏 plus.screen.lockOrientation("portrait-primary") // #endif首先準備啟動圖兩個dc_launchscreen_portrait_background2x.png(750*1624)dc_launchscreen_portrait_background3x.png(1125*2436)LaunchScreen.storyboard文件內容如下<?xml version"…

OpenCV:答題卡識別

目錄 一、項目原理 二、環境準備 三、核心代碼實現 1. 導入必要庫 2. 定義關鍵函數 坐標點排序函數 透視變換函數 輪廓排序函數 圖像顯示函數 3. 主程序實現 圖像預處理 輪廓檢測與答題卡定位 透視變換矯正 答案識別與評分 四、實現效果 本文將介紹如何使用 Ope…

機器寵物(以四足寵物為主)四肢與關節的系統化設計指南

1. 目標與約束先行 目標&#xff1a;自然步態&#xff08;走/小跑/小跳&#xff09;、安全親和、低噪、跌倒不致損&#xff1b;支持地毯/木地板/瓷磚等家庭地面。約束&#xff1a;體重 1–6 kg&#xff1b;單次續航 ≥ 30–60 min&#xff1b;整機成本與可維護性&#xff1b;室…

spark hive presto doris 對substr函數的差異

Spark、Hive、Presto&#xff08;現更名為 Trino&#xff09;和 Doris&#xff08;原百度 Palo&#xff09;的 substr 函數在功能上都是用于截取字符串的子串&#xff0c;但在起始索引規則和參數含義上存在差異&#xff0c;這是導致結果不同的主要原因。以下是它們的具體區別&a…

開題報告之基于AI Agent智能問答的旅游網站

課題題目&#xff1a; 基于AI Agent智能問答的旅游網站 學生姓名&#xff1a; 學 號&#xff1a; 學 院&#xff1a; 專業年級&#xff1a; 指導教師&#xff1a; 開題報告word版&#xff1a; 開題報告word版 一、課題的研究目的和意義&#xff08;本…

HTB打靶復個小盤

文章目錄jerrySauGoodGamesdevvotexpaper最近打了不少靶場&#xff0c;雖然難度都不算高&#xff0c;但也學到不少東西&#xff0c;中間去打了一周的實網滲透&#xff0c;打完后聯系了一家企業準備面試&#xff0c;感覺面試準備的差不多了&#xff0c;回來繼續打靶&#xff0c;…