Spring JDBC
傳統的JDBC在操作數據庫時,需要先打開數據庫連接,執行SQL語句,然后封裝結果,最后關閉數據庫連接等資源。頻繁的數據庫操作會產生大量的重復代碼,造成代碼冗余,Spring的JDBC模塊負責數據庫資源管理和錯誤處理,大大簡化了開發人員對數據庫的操作,使開發人員可以從頻繁的數據庫操作中解脫出來,從而將更多的精力投入編寫業務邏輯中。
JdbcTemplate
針對數據庫操作,Spring框架提供了JdbcTemplate類,JdbcTemplate是一個模板類,Spring JDBC中的更高層次的抽象類均在JdbcTemplate模板類的基礎上創建。
JdbcTemplate類提供了操作數據庫的基本方法,包括添加、刪除、查詢和更新。在操作數據庫時,JdbcTemplate類簡化了傳統JDBC中的復雜步驟,這可以讓開發人員將更多精力投入到業務邏輯中。
JdbcTemplate類繼承自抽象類JdbcAccessor,同時實現了JdbcTemplate接口。抽象類JdbcAccessor提供了一些訪問數據庫時使用的公共屬性,具體如下:
- DataSource:DataSource主要功能是獲取數據庫連接。在具體的數據操作中,它還提供對數據庫連接的緩沖池和分布式事務的支持。
- SQLExceptionTranslator:SQLExceptionTranslator是一個接口,它負責對SQLException異常進行轉譯工作。
Spring JDBC的配置
Spring JDBC中的4個包說明:
包名 | 說明 |
---|---|
core(核心包) | 包含了JDBC的核心功能,包括JdbcTemplate類、SimpleJdbcInsert類、SimpleJdbcCall類以及NamedParameterJdbcTemplate類。 |
dataSource(數據源包) | 包含訪問數據源的實用工具類,它有多種數據源的實現,可以在Java EE容器外部測試JDBC代碼。 |
object(對象包) | 以面向對象的方式訪問數據庫,它可以執行查詢、修改和更新操作并將返回結果作為業務對象,并且在數據表的列和業務對象的屬性之間映射查詢結果。 |
support(支持包) | 包含了core和object包的支持類,如提供異常轉換功能的SQLException類。 |
Spring對數據庫的操作都封裝在了core、dataSource、object和support這4個包中,想要使用Spring JDBC,就需要對這些包進行配置。在Spring中,JDBC的配置是在配置文件applicationContext.xml中完成的。
配置數據源:包括數據庫驅動??、連接數據庫url??、連接數據庫用戶名??、連接數據庫密碼??。
<bean id="dataSource" class=
"org.springframework.jdbc.datasource.DriverManagerDataSource"><!-- 數據庫驅動 --><property name="driverClassName" value="com.mysql.jdbc.Driver"/><!-- 連接數據庫url --><property name="url" value="jdbc:mysql://localhost:3306/spring"/><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>
配置注入類
<bean id="xxx" class="Xxx"><property name="JdbcTemplate" ref="JdbcTemplate"/>
</bean>
dataSource配置的4個屬性:
屬性名 | 含義 |
---|---|
driverClassName | 所使用的驅動名稱,對應驅動JAR包中的Driver類 |
url | 數據源地址 |
username | 訪問數據庫的用戶名 |
password | 訪問數據庫的密碼 |
dataSource屬性值的設定要求
在dataSource的4個屬性中,需要根據數據庫類型或者系統配置設置相應的屬性值。例如,如果數據庫類型不同,需要更改驅動名稱;如果數據庫不在本地,則需要將地址中的localhost替換成相應的主機IP;默認情況下,數據庫端口號可以省略,但如果修改過MySQL數據庫的端口號,則需要加上修改后的端口號。此外,連接數據庫的用戶名和密碼需要與數據庫創建時設置的用戶名和密碼保持一致。
接下來,我們通過JDBCTemplate的實現數據庫的增刪改查操作
首先實現數據庫的配置如下:
<!-- 數據源 --><bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"><property name="driverClassName" value="com.mysql.jdbc.Driver"/><property name="url"value="jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai"/><property name="username" value="root"/><property name="password" value="root"/></bean><!-- 配置jdbc模板 JdbcTemplate --><bean id="JdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource"/></bean><!-- 配置注入類 --><bean id="user" class="com.lq.entities.User"><property name="JdbcTemplate" ref="JdbcTemplate"/></bean>
創建項目,目錄如下:
?
在pom文件里添加maven依賴,我們特意引入了spring-jdbc和mysql-connector-java依賴,為了實現jdbc操作。
<dependency><groupId>org.springframework</groupId><artifactId>spring-aop</artifactId><version>6.1.16</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-beans</artifactId><version>6.1.16</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>6.1.16</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>6.1.16</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-expression</artifactId><version>6.1.16</version></dependency><dependency><groupId>commons-logging</groupId><artifactId>commons-logging</artifactId><version>1.2</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.1</version><scope>test</scope></dependency><!-- jdbc包依賴--><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.3.7</version></dependency><!-- 事務管理依賴--><dependency><groupId>org.springframework</groupId><artifactId>spring-tx</artifactId><version>5.3.7</version></dependency><!-- 數據庫驅動依賴--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.25</version></dependency>
創建實體類Account
package com.lq.entities;/*** @Author: Luqing Teacher* @CreateTime: 2025-02-27* @Description: Account* @Version: 1.0*/public class Account {private int id;private String username;private Double balance;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public Double getBalance() {return balance;}public void setBalance(Double balance) {this.balance = balance;}@Overridepublic String toString() {return "Account{" +"id=" + id +", username='" + username + '\'' +", balance=" + balance +'}';}
}
創建接口AccountDao?
package com.lq.dao;import com.lq.entities.Account;import java.util.List;/*** @Author: lzq* @CreateTime: 2025-02-27* @Description: AccountDao* @Version: 1.0*/public interface AccountDao {public int addAccount(Account account);public int updateAccount(Account account);public int deleteAccount(int id);public Account findAccountById(int id);public List<Account> findAllAccount();
}
增刪改查的接口實現:
package com.lq.dao.impl;import com.lq.dao.AccountDao;
import com.lq.entities.Account;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;import java.util.List;/*** @Author: Luqing Teacher* @CreateTime: 2025-02-27* @Description: 實現類* @Version: 1.0*/public class AccountDaoImpl implements AccountDao {private JdbcTemplate jdbcTemplate;public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {this.jdbcTemplate = jdbcTemplate;}@Overridepublic int addAccount(Account acc) {String sql = "INSERT INTO account (username, balance) VALUES (?, ?)";Object[] obj = new Object[]{acc.getUsername(),acc.getBalance()};int result = this.jdbcTemplate.update(sql, obj);return result;}@Overridepublic int updateAccount(Account account) {String sql = "update account set username=?,balance=? where id=?";Object[] obj = new Object[]{account.getUsername(),account.getBalance(),account.getId()};int result = jdbcTemplate.update(sql, obj);return result;}@Overridepublic int deleteAccount(int id) {String sql = "delete from account where id=?";int result = jdbcTemplate.update(sql, id);return result;}@Overridepublic Account findAccountById(int id) {String sql = "select * from account where id=?";//創建一個新的BeanPropertyRowMapper對象RowMapper<Account> rowMapper = new BeanPropertyRowMapper<>(Account.class);//將id綁定到sql中,并且將查詢結果封裝到Account對象中Account account = this.jdbcTemplate.queryForObject(sql, rowMapper, id);return account;}@Overridepublic List<Account> findAllAccount() {String sql = "select * from account";RowMapper<Account> rowMapper = new BeanPropertyRowMapper<>(Account.class);List<Account> accounts = this.jdbcTemplate.query(sql, rowMapper);return accounts;}
}
本案例的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"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><!-- 數據源 --><bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"><property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/><property name="url"value="jdbc:mysql://localhost:3306/springjdbc?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai"/><property name="username" value="root"/><property name="password" value="root"/></bean><!-- 配置jdbc模板 JdbcTemplate --><bean id="JdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource"/></bean><bean id="accountDao" class="com.lq.dao.impl.AccountDaoImpl"><property name="jdbcTemplate" ref="JdbcTemplate"/></bean></beans>
接下來進行測試:
package com.lq.test;import com.lq.dao.AccountDao;
import com.lq.entities.Account;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;import java.lang.annotation.Target;
import java.util.List;/*** @Author: Luqing Teacher* @CreateTime: 2025-02-27* @Description: jdbcTest* @Version: 1.0*/public class JdbcTest {@Testpublic void test1(){ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");JdbcTemplate jdbcTemplate = (JdbcTemplate) app.getBean("JdbcTemplate");jdbcTemplate.execute("" +"create table account("+ "id int primary key auto_increment,"+"username varchar(50),"+"balance double)");System.out.println("創建成功");}@Testpublic void test2(){ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");AccountDao accountDao = (AccountDao) app.getBean("accountDao");Account account = new Account();account.setUsername("肖炎");account.setBalance(1000.0);int res = accountDao.addAccount(account);if(res>0){System.out.println("成功添加了"+res+"條數據");}else{System.out.println("添加失敗");}}@Testpublic void test3(){ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");AccountDao accountDao = (AccountDao) app.getBean("accountDao");Account account = new Account();account.setId(1);account.setUsername("小醫仙");account.setBalance(1500.0);int res = accountDao.updateAccount(account);if(res>0){System.out.println("成功修改了"+res+"條數據");}else{System.out.println("修改失敗");}}@Testpublic void test4(){ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");AccountDao accountDao = (AccountDao) app.getBean("accountDao");int res = accountDao.deleteAccount(1);if(res>0){System.out.println("成功刪除了"+res+"條數據");}else{System.out.println("刪除失敗");}}@Testpublic void test5(){ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");AccountDao accountDao = (AccountDao) app.getBean("accountDao");Account account = accountDao.findAccountById(2);System.out.println(account);System.out.println("------------------------");List<Account> allAccount = accountDao.findAllAccount();for (Account account1 : allAccount) {System.out.println(account1);}}
}
JdbcTemplate類中常用的查詢方法
方法 | 說明 |
---|---|
List query(Stringsql,RowMapper rowMapper) | 執行String類型參數提供的SQL語句,并通過參數rowMapper返回一個List類型的結果。 |
List query(Stringsql, PreparedStatementSetter pss, RowMapper rowMapper) | 根據String類型參數提供的SQL語句創建PreparedStatement對象,通過參數rowMapper將結果返回到List中。 |
List query(Stringsql, Object[]args, RowMapper rowMapper) | 使用Object[]的值來設置SQL語句中的參數值,rowMapper是個回調方法,直接返回List類型的數據。 |
queryForObject(Stringsql, RowMapper rowMapper, Object…args) | 將args參數綁定到SQL語句中,并通過參數rowMapper返回一個Object類型的單行記錄。 |
queryForList(Stringsql,Object[]args, class<T>elementType) | 該方法可以返回多行數據的結果,但必須返回列表,args參數是sql語句中的參數,elementType參數返回的是List數據類型。 |