溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

SpringBoot中怎么利用JDBC對(duì)數(shù)據(jù)庫(kù)進(jìn)行操作

發(fā)布時(shí)間:2021-06-15 14:23:23 來(lái)源:億速云 閱讀:270 作者:Leah 欄目:大數(shù)據(jù)

這篇文章將為大家詳細(xì)講解有關(guān)SpringBoot中怎么利用JDBC對(duì)數(shù)據(jù)庫(kù)進(jìn)行操作,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對(duì)相關(guān)知識(shí)有一定的了解。

一、JDBC簡(jiǎn)介

JDBC(Java Data Base Connectivity,Java 數(shù)據(jù)庫(kù)連接),說(shuō)白了 JDBC 就是一套 Java 訪問(wèn)數(shù)據(jù)庫(kù)的 API 規(guī)范;Spring Boot 支持了主流的 ORM 框架:MyBatis、Hibernate 和 Spring JDBC,幾種 ORM 在不同的場(chǎng)景下各有優(yōu)勢(shì),在 Spring Boot 體系內(nèi)都有對(duì)應(yīng)的 Starter 包以方便集成

  • 直接在Java中使用JDBC的步驟,比價(jià)復(fù)雜,需要7步完成:

try {
    // 1、加載數(shù)據(jù)庫(kù)驅(qū)動(dòng)
    Class.forName(driver);
    // 2、獲取數(shù)據(jù)庫(kù)連接
    conn = DriverManager.getConnection(url, username, password);
    // 3、獲取數(shù)據(jù)庫(kù)操作對(duì)象
    stmt = conn.createStatement();
    // 4、定義操作的 SQL 語(yǔ)句
    String sql = "select * from user where id = 6";
    // 5、執(zhí)行數(shù)據(jù)庫(kù)操作
    rs = stmt.executeQuery(sql);
    // 6、獲取并操作結(jié)果集
    while (rs.next()) {
    // 解析結(jié)果集
    }
} catch (Exception e) {
    // 日志信息
} finally {
    // 7、關(guān)閉資源
}

通過(guò)上面的示例可以看出直接使用 JDBC 來(lái)操作數(shù)據(jù)庫(kù)比較復(fù)雜,因此后期在 JDBC 的基礎(chǔ)上又發(fā)展出了很多著名的 ORM 框架,其中最為流行的是 Hibernate、MyBatis 和 Spring JDBC,這里主要了解一下 Spring JDBC 在 Spring Boot 中的使用

二、單數(shù)據(jù)源操作示例

Spring Boot 集成 JDBC 很簡(jiǎn)單,需要引入依賴并做基礎(chǔ)配置即可,在開(kāi)發(fā)項(xiàng)目之前需要先創(chuàng)建表,作為項(xiàng)目演示使用。設(shè)計(jì)一個(gè) User 用戶表,有 id、name、password、age 等字段,對(duì)應(yīng)的 SQL 腳本如下:

DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主鍵id',
  `name` varchar(32) DEFAULT NULL COMMENT '用戶名',
  `password` varchar(32) DEFAULT NULL COMMENT '密碼',
  `age`  int DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
  1. 添加配置

  • 添加依賴包:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>
  • 演示項(xiàng)目中使用 MySQL 作為數(shù)據(jù)庫(kù),因此項(xiàng)目中需要引入 MySQL 驅(qū)動(dòng)包,同時(shí)引入 spring-boot-starter-jdbc。打開(kāi) pom.xml 文件,按下快捷鍵:Ctrl + Alt + SHIFT + U,或者單擊右鍵,選擇 Diagrams | Show Dependencies 選項(xiàng),查看項(xiàng)目依賴類(lèi)圖。

SpringBoot中怎么利用JDBC對(duì)數(shù)據(jù)庫(kù)進(jìn)行操作

  • 彈出“類(lèi)圖”對(duì)話框后,滾動(dòng)鼠標(biāo)放大查看,發(fā)現(xiàn) spring-boot-starter-jdbc 直接依賴于 HikariCP 和 spring-jdbc。

SpringBoot中怎么利用JDBC對(duì)數(shù)據(jù)庫(kù)進(jìn)行操作

  • HikariCP 是 Spring Boot 2.0 默認(rèn)使用的數(shù)據(jù)庫(kù)連接池,也是傳說(shuō)中最快的數(shù)據(jù)庫(kù)連接池。

  • spring-jdbc 是 Spring 封裝對(duì) JDBC 操作的工具包。

  • 數(shù)據(jù)源的配置

spring.datasource.url=jdbc:mysql://localhost:3306/test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

值得注意的是,在 Spring Boot 2.1.0 中,com.mysql.jdbc.Driver 已經(jīng)過(guò)期,推薦使用 com.mysql.cj.jdbc.Driver。

  1. 實(shí)體類(lèi)

  • 創(chuàng)建表對(duì)應(yīng)的實(shí)體類(lèi):

public class User  {
    private Long id;
    private String name;
    private String password;
    private int age;

    public User(String name, String password, int age) {
        this.name = name;
        this.password = password;
        this.age = age;
    }
    // 省略 getter setter
}
  1. 封裝 Repository

  • 創(chuàng)建 UserRepository 定義我們常用的增刪改查接口;

public interface UserRepository  {
    int save(User user);
    int update(User user);
    int delete(long id);
    List<User> findALL();
    User findById(long id);
}
  • 創(chuàng)建 UserRepositoryImpl 類(lèi)實(shí)現(xiàn) UserRepository 類(lèi)接口;類(lèi)上使用 @Repository 注解用于標(biāo)注數(shù)據(jù)訪問(wèn)組件,同時(shí)在類(lèi)中注入 JdbcTemplate,其是 Spring 操作 JDBC 提供的工具類(lèi)。

@Repository
public class UserRepositoryImpl implements UserRepository {
    @Autowired
    private JdbcTemplate jdbcTemplate;
}
  • 接下來(lái)封裝保存用戶/更新用戶信息/刪除用戶信息/用戶id查詢/獲取用戶列表的方法

@Override
public int save(User user) {
    return jdbcTemplate.update("INSERT INTO users(name, password, age) values(?, ?, ?)",
          user.getName(), user.getPassword(), user.getAge());
}

@Override
public int update(User user) {
    return jdbcTemplate.update("UPDATE users SET name = ? , password = ? , age = ? WHERE id=?",
           user.getName(), user.getPassword(), user.getAge(), user.getId());
}

@Override
public int delete(long id) {
    return jdbcTemplate.update("DELETE FROM users where id = ? ",id);
}

@Override
public User findById(long id) {
    return jdbcTemplate.queryForObject("SELECT * FROM users WHERE id=?", new Object[] { id }, new BeanPropertyRowMapper<User>(User.class));
}

@Override
public List<User> findALL() {
    return jdbcTemplate.query("SELECT * FROM users", new UserRowMapper());
    // return jdbcTemplate.query("SELECT * FROM users", new BeanPropertyRowMapper(User.class));
}

這里使用了 new BeanPropertyRowMapper<User>(User.class) 對(duì)返回的數(shù)據(jù)進(jìn)行封裝,它可自動(dòng)將一行數(shù)據(jù)映射到指定類(lèi)的實(shí)例中,首先將這個(gè)類(lèi)實(shí)例化,然后通過(guò)名稱匹配的方式,映射到屬性中去。

findALL() 使用了一個(gè)新的方式來(lái)封裝結(jié)果集的返回,創(chuàng)建一個(gè)內(nèi)部類(lèi) UserRowMapper。 UserRowMapper 繼承了 RowMapper,RowMapper 可以將數(shù)據(jù)中的每一行數(shù)據(jù)封裝成用戶定義的類(lèi),實(shí)現(xiàn) RowMapper 接口覆蓋 mapRow 方法,在 mapRow 方法封裝對(duì)數(shù)據(jù)的返回處理。通過(guò)上面代碼可以看出 UserRowMapper 循環(huán)遍歷了查詢返回的結(jié)果集,遍歷的同時(shí)按照屬性進(jìn)行賦值。這樣在查詢使用時(shí)只需要傳入 new UserRowMapper() 即可自動(dòng)解析返回?cái)?shù)據(jù)。

class UserRowMapper implements RowMapper<User> {
    @Override
    public User mapRow(ResultSet rs, int rowNum) throws SQLException {
        User user = new User();
        user.setId(rs.getLong("id"));
        user.setName(rs.getString("name"));
        user.setPassword(rs.getString("password"));
        user.setAge(rs.getInt("age"));
    }
}
  1. 測(cè)試

  • 接下里我們對(duì)封裝好的 UserRepository 進(jìn)行測(cè)試,測(cè)試 UserRepository 中的各個(gè)方法是否正確。創(chuàng)建 UserRepositoryTests 類(lèi),將 userRepository 注入到類(lèi)中。

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserRepositoryTests {
    @Autowired
    private UserRepository userRepository;
}

//測(cè)試插入數(shù)據(jù),直接調(diào)用 userRepository 對(duì)應(yīng)的 save 方法
@Test
public void testSave() {
    User user =new User("neo","123456",30);
    userRepository.save(user);
}

//按照上面方式分別測(cè)試其他方法...

三、多數(shù)據(jù)源的使用

在項(xiàng)目中使用多個(gè)數(shù)據(jù)源是很常見(jiàn)的情況,Spring Boot 中多數(shù)據(jù)源的使用需要自行封裝。我們?cè)谏厦媸纠?xiàng)目的基礎(chǔ)上進(jìn)行改造。

  1. 配置文件

  • 添加了兩個(gè)數(shù)據(jù)源,一個(gè)是 test1 庫(kù),一個(gè)是 test2 庫(kù)。

spring.datasource.primary.jdbc-url=jdbc:mysql://localhost:3306/test1?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true
spring.datasource.primary.username=root
spring.datasource.primary.password=root
spring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driver

spring.datasource.secondary.jdbc-url=jdbc:mysql://localhost:3306/test2?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true
spring.datasource.secondary.username=root
spring.datasource.secondary.password=root
spring.datasource.secondary.driver-class-name=com.mysql.cj.jdbc.Driver
  1. 初始化 JDBC

  • 在項(xiàng)目啟動(dòng)的時(shí)候讀取配置文件中的信息,并對(duì) JDBC 初始化。

@Configuration
public class DataSourceConfig {
    @Primary
    @Bean(name = "primaryDataSource")
    @Qualifier("primaryDataSource")
    @ConfigurationProperties(prefix="spring.datasource.primary")
    public DataSource primaryDataSource() {
            return DataSourceBuilder.create().build();
    }

    @Bean(name = "secondaryDataSource")
    @Qualifier("secondaryDataSource")
    @ConfigurationProperties(prefix="spring.datasource.secondary")
    public DataSource secondaryDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name="primaryJdbcTemplate")
    public JdbcTemplate primaryJdbcTemplate (
        @Qualifier("primaryDataSource")  DataSource dataSource ) {
        return new JdbcTemplate(dataSource);
    }

    @Bean(name="secondaryJdbcTemplate")
    public JdbcTemplate  secondaryJdbcTemplate(
            @Qualifier("secondaryDataSource") DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }
}

這段代碼表示在啟動(dòng)的時(shí)候根據(jù)特定的前綴加載不同的數(shù)據(jù)源,根據(jù)構(gòu)建好的數(shù)據(jù)源再創(chuàng)建不同的 JDBC。

  1. UserRepository 改造

  • 我們對(duì) UserRepository 中的所有方法進(jìn)行改造,增加一個(gè)參數(shù)為 JdbcTemplate,如果方法中傳輸了 JdbcTemplate,方法內(nèi)就會(huì)使用傳遞的 JdbcTemplate 進(jìn)行操作,如果傳遞的 JdbcTemplate 為空,使用默認(rèn)的 JdbcTemplate 連接操作。

@Repository
public class UserRepositoryImpl implements UserRepository {
    @Autowired
    private JdbcTemplate primaryJdbcTemplate;

    @Override
    public int save(User user,JdbcTemplate jdbcTemplate) {
        if(jdbcTemplate == null){
            jdbcTemplate= primaryJdbcTemplate;
        }
        return jdbcTemplate.update("INSERT INTO users(name, password, age) values(?, ?, ?)",
              user.getName(), user.getPassword(), user.getAge());
    }

  //其他方法省略,詳細(xì)內(nèi)容可以查看源碼
}
  1. 多數(shù)據(jù)源測(cè)試

  • 測(cè)試類(lèi)中注入了兩個(gè)不同數(shù)據(jù)源的 JdbcTemplate,同時(shí)注入 UserRepository。測(cè)試使用不同的 JdbcTemplate 插入兩條數(shù)據(jù),查看兩個(gè)數(shù)據(jù)庫(kù)中是否都保存成功。測(cè)試前請(qǐng)先創(chuàng)建 test1 和 test2 數(shù)據(jù)庫(kù),以及兩個(gè)數(shù)據(jù)庫(kù)中的用戶表。

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserRepositoryTests {
    @Autowired
    private UserRepository userRepository;
    @Autowired
    private JdbcTemplate primaryJdbcTemplate;
    @Autowired
    private JdbcTemplate secondaryJdbcTemplate;

    @Test
    public void testSave() {
        User user =new User("smile","123456",30);
        userRepository.save(user,primaryJdbcTemplate);
        userRepository.save(user,secondaryJdbcTemplate);
    }
}

執(zhí)行 testSave() 成功后,登錄 test1 和 test 2 數(shù)據(jù)庫(kù)查看 user 表,都存在一條 name 為 smile 的用戶信息,說(shuō)明多數(shù)據(jù)源插入數(shù)據(jù)成功,其他方法的測(cè)試大體相同。這樣在項(xiàng)目中,我們想使用哪個(gè)數(shù)據(jù)源操作數(shù)據(jù)庫(kù)時(shí),只需要傳入數(shù)據(jù)源對(duì)應(yīng)的 JdbcTemplate 實(shí)例即可。

關(guān)于SpringBoot中怎么利用JDBC對(duì)數(shù)據(jù)庫(kù)進(jìn)行操作就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI