溫馨提示×

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

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

如何使用JDBC核心類控制進(jìn)行JDBC處理

發(fā)布時(shí)間:2021-12-22 11:49:59 來源:億速云 閱讀:169 作者:iii 欄目:大數(shù)據(jù)

這篇文章主要介紹“如何使用JDBC核心類控制進(jìn)行JDBC處理”,在日常操作中,相信很多人在如何使用JDBC核心類控制進(jìn)行JDBC處理問題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”如何使用JDBC核心類控制進(jìn)行JDBC處理”的疑惑有所幫助!接下來,請(qǐng)跟著小編一起來學(xué)習(xí)吧!

下表概述的操作序列可能最好地顯示了Spring框架JDBC抽象提供的值。該表顯示了Spring負(fù)責(zé)哪些操作以及哪些操作是你需要做的。

ActionSpringYou
定義連接參數(shù)
X
打開連接X
指定SQL語(yǔ)句。
X
聲明參數(shù)并提供參數(shù)值
X
準(zhǔn)備并運(yùn)行該語(yǔ)句。X
設(shè)置循環(huán)以遍歷結(jié)果(如果有)。X
進(jìn)行每次迭代的工作。
X
處理任何異常。X
處理異常。X
關(guān)閉連接,語(yǔ)句和結(jié)果集。X

Spring框架負(fù)責(zé)處理使JDBC成為如此乏味的API的所有底層細(xì)節(jié)。

3.1 選擇一種用于JDBC數(shù)據(jù)庫(kù)訪問的方法

你可以選擇幾種方法來構(gòu)成JDBC數(shù)據(jù)庫(kù)訪問的基礎(chǔ)。除了JdbcTemplate的三種形式之外,新的SimpleJdbcInsertSimpleJdbcCall方法還優(yōu)化了數(shù)據(jù)庫(kù)元數(shù)據(jù),并且RDBMS Object樣式采用了一種類似于JDO Query設(shè)計(jì)的面向?qū)ο蟮姆椒?。一旦開始使用這些方法之一,你仍然可以混合搭配以包含來自其他方法的功能。所有方法都需要兼容JDBC 2.0的驅(qū)動(dòng)程序,而某些高級(jí)功能則需要JDBC 3.0驅(qū)動(dòng)程序。

  • JdbcTemplate是經(jīng)典且最受歡迎的Spring JDBC方法。這種最低級(jí)別的方法和所有其他方法都在幕后使用JdbcTemplate。

  • NamedParameterJdbcTemplate包裝了一個(gè)JdbcTemplate來提供命名參數(shù),而不是傳統(tǒng)的JDBC ?占位符。當(dāng)你有多個(gè)SQL語(yǔ)句參數(shù)時(shí),此方法可提供更好的文檔編制和易用性。

  • SimpleJdbcInsertSimpleJdbcCall優(yōu)化數(shù)據(jù)庫(kù)元數(shù)據(jù)以限制必要的配置量。這種方法簡(jiǎn)化了編碼,因此你僅需要提供表或過程(存儲(chǔ)過程)的名稱,并提供與列名稱匹配的參數(shù)映射。僅當(dāng)數(shù)據(jù)庫(kù)提供足夠的元數(shù)據(jù)時(shí),此方法才有效。如果數(shù)據(jù)庫(kù)不提供此元數(shù)據(jù),則必須提供參數(shù)的顯式配置。

  • RDBMS對(duì)象(包括MappingSqlQuery、SqlUpdateStoredProcedure)要求你在數(shù)據(jù)訪問層初始化期間創(chuàng)建可重用且線程安全的對(duì)象。此方法以JDO查詢?yōu)槟P停渲卸x查詢字符串、聲明參數(shù)并編譯查詢。完成后,可以使用各種參數(shù)值多次調(diào)用execute(...)update(...)findObject(...)方法。

3.2 包結(jié)構(gòu)

Spring框架的JDBC抽象框架由四個(gè)不同的包組成:

  • core: org.springframework.jdbc.core包含JdbcTemplate類及其各種回調(diào)接口,以及各種相關(guān)類。名為org.springframework.jdbc.core.simple的子包包含SimpleJdbcInsertSimpleJdbcCall類。另一個(gè)名為org.springframework.jdbc.core.namedparam的子包包含NamedParameterJdbcTemplate類和相關(guān)的支持類。請(qǐng)參閱使用JDBC核心類控制基本JDBC處理和錯(cuò)誤處理、JDBC批處理操作和使用SimpleJdbc類簡(jiǎn)化JDBC操作。

  • datasource: org.springframework.jdbc.datasource包含一個(gè)實(shí)用程序類,用于輕松訪問DataSource和各種簡(jiǎn)單DataSource實(shí)現(xiàn),可用于在Java EE容器之外測(cè)試和運(yùn)行未修改的JDBC代碼。名為org.springfamework.jdbc.datasource.embedded的子包提供了對(duì)使用Java數(shù)據(jù)庫(kù)引擎(例如HSQL、H2Derby)創(chuàng)建嵌入式數(shù)據(jù)庫(kù)的支持。請(qǐng)參閱控制數(shù)據(jù)庫(kù)連接和嵌入式數(shù)據(jù)庫(kù)支持。

  • object: org.springframework.jdbc.object包含一些類,這些類將RDBMS查詢、更新和存儲(chǔ)過程表示為線程安全的可重用對(duì)象。請(qǐng)參閱將JDBC操作建模為Java對(duì)象。盡管查詢返回的對(duì)象自然會(huì)與數(shù)據(jù)庫(kù)斷開連接,但是JDO對(duì)此方法進(jìn)行了建模。較高級(jí)別的JDBC抽象依賴于org.springframework.jdbc.core包中的較低級(jí)別的抽象。

  • support: org.springframework.jdbc.support包提供了SQLException轉(zhuǎn)換功能和一些實(shí)用程序類。JDBC處理期間引發(fā)的異常將轉(zhuǎn)換為org.springframework.dao包中定義的異常。這意味著使用Spring JDBC抽象層的代碼不需要實(shí)現(xiàn)JDBCRDBMS特定的錯(cuò)誤處理。所有轉(zhuǎn)換的異常均為uncheck異常,這使你可以選擇捕獲可從中恢復(fù)的異常,同時(shí)將其他異常傳遞到調(diào)用方。請(qǐng)參見使用SQLExceptionTranslator。

3.3 使用JDBC核心類控制JDBC處理和錯(cuò)誤處理

本節(jié)介紹如何使用JDBC核心類控制JDBC處理,包括錯(cuò)誤處理。它包括以下主題:

  • 使用JdbcTemplate

  • 使用NamedParameterJdbcTemplate

  • 使用SQLExceptionTranslator

  • 執(zhí)行語(yǔ)句

  • 執(zhí)行查詢

  • 更新數(shù)據(jù)庫(kù)

  • 獲取自動(dòng)生成主鍵

3.3.1 使用JdbcTemplate

JdbcTemplateJDBCcore包中的核心類。它處理資源的創(chuàng)建和釋放,這有助于你避免常見的錯(cuò)誤,例如忘記關(guān)閉連接。它執(zhí)行核心JDBC工作流程的基本任務(wù)(例如,語(yǔ)句創(chuàng)建和執(zhí)行),而使應(yīng)用程序代碼提供SQL并提取結(jié)果。JdbcTemplate類:

  • 運(yùn)行SQL查詢

  • 更新語(yǔ)句和存儲(chǔ)過程調(diào)用

  • 對(duì)ResultSet實(shí)例執(zhí)行迭代并提取返回的參數(shù)值。

  • 捕獲JDBC異常并將其轉(zhuǎn)換為org.springframework.dao包中定義的通用、信息量更大的異常層次結(jié)構(gòu)。 (請(qǐng)參見一致的異常層次結(jié)構(gòu))

當(dāng)將JdbcTemplate用于代碼時(shí),只需實(shí)現(xiàn)回調(diào)接口,即可為它們提供明確定義的約定。給定JdbcTemplate類提供的Connection、PreparedStatementCreator回調(diào)接口將創(chuàng)建一條準(zhǔn)備好的語(yǔ)句,提供SQL和任何必要的參數(shù)。對(duì)于CallableStatementCreator接口(創(chuàng)建可調(diào)用語(yǔ)句)也是如此。 RowCallbackHandler接口從ResultSet的每一行提取值。

你可以通過直接實(shí)例化DataSource引用在DAO實(shí)現(xiàn)中使用JdbcTemplate,也可以在Spring IoC容器中對(duì)其進(jìn)行配置,并將其作為Bean引用提供給DAO。

應(yīng)該始終在Spring IoC容器中將DataSource配置為Bean。在第一種情況下,bean被直接提供給服務(wù)。在第二種情況下,將其提供給準(zhǔn)備好的模板。

此類發(fā)出的所有SQL都在DEBUG級(jí)別下記錄,該類別對(duì)應(yīng)于模板實(shí)例的全限定類名稱(通常為JdbcTemplate,但如果使用JdbcTemplate類的自定義子類,則可能有所不同)。

以下各節(jié)提供了JdbcTemplate用法的一些示例。這些示例不是JdbcTemplate暴露的所有功能的詳盡列表。請(qǐng)參考附帶的javadoc。

查詢(SELECT)

以下查詢獲取關(guān)聯(lián)中的行數(shù):

int rowCount = this.jdbcTemplate.queryForObject("select count(*) from t_actor", Integer.class);

以下查詢使用綁定變量:

int countOfActorsNamedJoe = this.jdbcTemplate.queryForObject(
        "select count(*) from t_actor where first_name = ?", Integer.class, "Joe");

以下查詢查找字符串:

String lastName = this.jdbcTemplate.queryForObject(
        "select last_name from t_actor where id = ?",
        String.class, 1212L);

以下查詢查找并填充單個(gè)領(lǐng)域?qū)ο螅?/p>

Actor actor = jdbcTemplate.queryForObject(
        "select first_name, last_name from t_actor where id = ?",
        (resultSet, rowNum) -> {
            Actor newActor = new Actor();
            newActor.setFirstName(resultSet.getString("first_name"));
            newActor.setLastName(resultSet.getString("last_name"));
            return newActor;
        },
        1212L);

以下查詢查找并填充領(lǐng)域?qū)ο罅斜恚?/p>

List<Actor> actors = this.jdbcTemplate.query(
        "select first_name, last_name from t_actor",
        (resultSet, rowNum) -> {
            Actor actor = new Actor();
            actor.setFirstName(resultSet.getString("first_name"));
            actor.setLastName(resultSet.getString("last_name"));
            return actor;
        });

如果最后兩個(gè)代碼段確實(shí)存在于同一應(yīng)用程序中,則刪除兩個(gè)RowMapper lambda表達(dá)式中存在的重復(fù)項(xiàng)并將它們提取到單個(gè)字段中,然后可以根據(jù)需要由DAO方法引用,這是有意義的。

例如,使用前面編寫的代碼段,如下所示:

private final RowMapper<Actor> actorRowMapper = (resultSet, rowNum) -> {
    Actor actor = new Actor();
    actor.setFirstName(resultSet.getString("first_name"));
    actor.setLastName(resultSet.getString("last_name"));
    return actor;
};

public List<Actor> findAllActors() {
    return this.jdbcTemplate.query( "select first_name, last_name from t_actor", actorRowMapper);
}

使用JdbcTemplate更新(INSERT,UPDATE和DELETE)

您可以使用update(..)方法執(zhí)行插入,更新和刪除操作。參數(shù)值通常作為變量參數(shù)提供,或者作為對(duì)象數(shù)組提供。

下面的示例插入一個(gè)新數(shù)據(jù):

this.jdbcTemplate.update(
        "insert into t_actor (first_name, last_name) values (?, ?)",
        "Leonor", "Watling");

以下示例更新現(xiàn)有數(shù)據(jù):

this.jdbcTemplate.update(
        "update t_actor set last_name = ? where id = ?",
        "Banjo", 5276L);

下面的示例刪除一條數(shù)據(jù):

this.jdbcTemplate.update(
        "delete from t_actor where id = ?",
        Long.valueOf(actorId));

參考代碼:org.liyong.dataaccess.starter.JdbcTemplateTransactionManagerIocContainer

其他JdbcTemplate操作

你可以使用execute(..)方法來運(yùn)行任意SQL。因此,該方法經(jīng)常用于DDL語(yǔ)句。它被接受回調(diào)接口、綁定變量數(shù)組等的變量重載。下面的示例創(chuàng)建了一個(gè)表:

this.jdbcTemplate.execute("create table mytable (id integer, name varchar(100))");

下面的示例調(diào)用一個(gè)存儲(chǔ)過程:

this.jdbcTemplate.update(
        "call SUPPORT.REFRESH_ACTORS_SUMMARY(?)",
        Long.valueOf(unionId));

稍后將介紹更復(fù)雜的存儲(chǔ)過程支持。

JdbcTemplate最佳做法

一旦配置,JdbcTemplate類的實(shí)例是線程安全的。它很重要,因?yàn)檫@意味著你可以配置JdbcTemplate的單個(gè)實(shí)例,然后將該共享引用安全地注入到多個(gè)DAO(或存儲(chǔ)庫(kù))中。JdbcTemplate是有狀態(tài)的,因?yàn)樗S護(hù)對(duì)DataSource的引用,但是此狀態(tài)不是會(huì)話狀態(tài)。

使用JdbcTemplate類(和關(guān)聯(lián)的NamedParameterJdbcTemplate類)的常見做法是在Spring配置文件中配置DataSource,然后將共享的DataSource bean依賴注入到DAO類中。 JdbcTemplate在數(shù)據(jù)源的設(shè)置器中創(chuàng)建。這導(dǎo)致類似于以下內(nèi)容的DAO:

public class JdbcCorporateEventDao implements CorporateEventDao {

    private JdbcTemplate jdbcTemplate;

    public void setDataSource(DataSource dataSource) {
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }

    // JDBC-backed implementations of the methods on the CorporateEventDao follow...
}

以下示例顯示了相應(yīng)的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"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">

    <bean id="corporateEventDao" class="com.example.JdbcCorporateEventDao">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <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>

    <context:property-placeholder location="jdbc.properties"/>

</beans>

顯式配置的替代方法是使用組件掃描和注解支持進(jìn)行依賴項(xiàng)注入。在這種情況下,可以使用@Repository注釋該類(這使其成為組件掃描的候選對(duì)象),并使用@Autowired注解DataSource setter方法。以下示例顯示了如何執(zhí)行此操作:

@Repository //1
public class JdbcCorporateEventDao implements CorporateEventDao {

    private JdbcTemplate jdbcTemplate;

    @Autowired //2
    public void setDataSource(DataSource dataSource) {
        this.jdbcTemplate = new JdbcTemplate(dataSource); //3
    }

    // JDBC-backed implementations of the methods on the CorporateEventDao follow...
}
  1. @Repository注釋類。

  2. @Autowired注釋DataSource setter方法。

  3. 使用DataSource創(chuàng)建一個(gè)新的JdbcTemplate。

以下示例顯示了相應(yīng)的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"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">

    <!-- Scans within the base package of the application for @Component classes to configure as beans -->
    <context:component-scan base-package="org.springframework.docs.test" />

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <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>

    <context:property-placeholder location="jdbc.properties"/>

</beans>

如果你使用Spring的JdbcDaoSupport類,并且從中擴(kuò)展了各種JDBC支持的DAO類,則你的子類將從JdbcDaoSupport類繼承一個(gè)setDataSource(..)方法。你可以選擇是否從此類繼承。提供JdbcDaoSupport類目的只是為了方便。

無論你選擇使用(或不使用)以上哪種模板初始化樣式,都無需在每次要運(yùn)行SQL時(shí)都創(chuàng)建JdbcTemplate類的新實(shí)例。配置完成后,JdbcTemplate實(shí)例是線程安全的。如果你的應(yīng)用程序訪問多個(gè)數(shù)據(jù)庫(kù),你可能需要多個(gè)JdbcTemplate實(shí)例,這需要多個(gè)數(shù)據(jù)源,然后需要多個(gè)不同配置的JdbcTemplate實(shí)例。

參考代碼:org.liyong.dataaccess.starter.JdbcTemplateBestTransactionManagerIocContainer

3.3.2 使用NamedParameterJdbcTemplate

與僅使用經(jīng)典占位符(?)編程的JDBC語(yǔ)句相反,NamedParameterJdbcTemplate類增加了使用命名參數(shù)對(duì)JDBC語(yǔ)句進(jìn)行編程的支持。NamedParameterJdbcTemplate類包裝JdbcTemplate并將其委托給包裝的JdbcTemplate以完成其大部分工作。本節(jié)僅描述NamedParameterJdbcTemplate類的那些與JdbcTemplate本身不同的部分,通過使用命名參數(shù)對(duì)JDBC語(yǔ)句進(jìn)行編程。下面的示例演示如何使用NamedParameterJdbcTemplate

// some JDBC-backed DAO class...
private NamedParameterJdbcTemplate namedParameterJdbcTemplate;

public void setDataSource(DataSource dataSource) {
    this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
}

public int countOfActorsByFirstName(String firstName) {

    String sql = "select count(*) from T_ACTOR where first_name = :first_name";

    SqlParameterSource namedParameters = new MapSqlParameterSource("first_name", firstName);

    return this.namedParameterJdbcTemplate.queryForObject(sql, namedParameters, Integer.class);
}

請(qǐng)注意,在分配給sql變量的值以及插入到namedParameters變量(MapSqlParameterSource類型)中的相應(yīng)值中使用了命名參數(shù)符號(hào)。

或者,你可以使用基于Map的格式將命名參數(shù)及其對(duì)應(yīng)的值傳遞給NamedParameterJdbcTemplate實(shí)例。由NamedParameterJdbcOperations暴露并由NamedParameterJdbcTemplate類實(shí)現(xiàn)的其余方法遵循類似的模式,此處不再贅述。

以下示例說明了基于Map的格式的使用:

// some JDBC-backed DAO class...
private NamedParameterJdbcTemplate namedParameterJdbcTemplate;

public void setDataSource(DataSource dataSource) {
    this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
}

public int countOfActorsByFirstName(String firstName) {

    String sql = "select count(*) from T_ACTOR where first_name = :first_name";

    Map<String, String> namedParameters = Collections.singletonMap("first_name", firstName);

    return this.namedParameterJdbcTemplate.queryForObject(sql, namedParameters,  Integer.class);
}

SqlParameterSource接口是與NamedParameterJdbcTemplate相關(guān)的一個(gè)不錯(cuò)的功能(并且存在于同一Java包中)。你已經(jīng)在前面的代碼片段之一(MapSqlParameterSource類)中看到了此接口的實(shí)現(xiàn)示例。SqlParameterSourceNamedParameterJdbcTemplate的命名參數(shù)值的源。MapSqlParameterSource類是一個(gè)簡(jiǎn)單的實(shí)現(xiàn),它是圍繞java.util.Map的適配器,其中鍵是參數(shù)名稱、值是參數(shù)值。

另一個(gè)SqlParameterSource實(shí)現(xiàn)是BeanPropertySqlParameterSource類。此類包裝一個(gè)任意的JavaBean(即,遵循JavaBean約定的類的實(shí)例),并使用包裝的JavaBean的屬性作為命名參數(shù)值的源。

以下示例顯示了典型的JavaBean:

public class Actor {

    private Long id;
    private String firstName;
    private String lastName;

    public String getFirstName() {
        return this.firstName;
    }

    public String getLastName() {
        return this.lastName;
    }

    public Long getId() {
        return this.id;
    }

    // setters omitted...

}

以下示例使用NamedParameterJdbcTemplate返回上一示例中顯示的類的成員數(shù):

// some JDBC-backed DAO class...
private NamedParameterJdbcTemplate namedParameterJdbcTemplate;

public void setDataSource(DataSource dataSource) {
    this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
}

public int countOfActors(Actor exampleActor) {

    // notice how the named parameters match the properties of the above 'Actor' class
    String sql = "select count(*) from T_ACTOR where first_name = :firstName and last_name = :lastName";

    SqlParameterSource namedParameters = new BeanPropertySqlParameterSource(exampleActor);

    return this.namedParameterJdbcTemplate.queryForObject(sql, namedParameters, Integer.class);
}

記住,NamedParameterJdbcTemplate類包裝了經(jīng)典的JdbcTemplate模板。如果需要訪問包裝的JdbcTemplate實(shí)例以訪問僅在JdbcTemplate類中提供的功能,則可以使用getJdbcOperations()方法通過JdbcOperations接口訪問包裝的JdbcTemplate。

另請(qǐng)參閱JdbcTemplate最佳實(shí)踐,以獲取有關(guān)在應(yīng)用程序上下文中使用NamedParameterJdbcTemplate類的指導(dǎo)。

參考代碼:org.liyong.dataaccess.starter.NamedParameterTransactionManagerIocContainer

標(biāo)記位置

3.3.3 使用SQLExceptionTranslator

SQLExceptionTranslator是由可以在SQLExceptions和Spring自己的org.springframework.dao.DataAccessException之間進(jìn)行轉(zhuǎn)換的類實(shí)現(xiàn)的接口,該類與數(shù)據(jù)訪問策略無關(guān)。為了提高精度,實(shí)現(xiàn)可以是通用的(例如,使用SQLState代碼用于JDBC)或?qū)S械模ɡ?,使用Oracle錯(cuò)誤代碼)。

SQLErrorCodeSQLExceptionTranslator是默認(rèn)使用的SQLExceptionTranslator的實(shí)現(xiàn)。此實(shí)現(xiàn)使用特定的供應(yīng)商代碼。它比SQLState實(shí)現(xiàn)更精確。錯(cuò)誤代碼的轉(zhuǎn)換基于一個(gè)名為SQLErrorCodes的JavaBean類型類中的代碼。此類由SQLErrorCodesFactory創(chuàng)建和填充,SQLErrorCodesFactory是工廠,用于基于名為sql-error-codes.xml的配置文件的內(nèi)容創(chuàng)建SQLErrorCodes。此文件使用供應(yīng)商代碼填充,并基于從DatabaseMetaData中獲取的DatabaseProductName填充。使用你正在使用的實(shí)際數(shù)據(jù)庫(kù)的代碼。

SQLErrorCodeSQLExceptionTranslator按以下順序應(yīng)用匹配規(guī)則:

  1. 子類實(shí)現(xiàn)的任何自定義轉(zhuǎn)換。通常,將使用提供的具體SQLErrorCodeSQLExceptionTranslator,因此此規(guī)則不適用。僅當(dāng)你確實(shí)提供了子類實(shí)現(xiàn)時(shí),它才適用。

  2. 作為SQLErrorCodes類的customSqlExceptionTranslator屬性提供的SQLExceptionTranslator接口的任何自定義實(shí)現(xiàn)。

  3. 搜索CustomSQLErrorCodesTranslation類的實(shí)例列表(為SQLErrorCodes類的customTranslations屬性提供),以查找匹配項(xiàng)。

  4. 錯(cuò)誤代碼匹配被應(yīng)用。

  5. 使用后備轉(zhuǎn)換器。 SQLExceptionSubclassTranslator是默認(rèn)的后備轉(zhuǎn)換器。如果此轉(zhuǎn)換器不可用,則下一個(gè)后備轉(zhuǎn)換器是SQLStateSQLExceptionTranslator。

默認(rèn)情況下,使用SQLErrorCodesFactory定義錯(cuò)誤代碼和自定義異常轉(zhuǎn)換。從類路徑的名為sql-error-codes.xml的文件中查找它們,并根據(jù)使用中數(shù)據(jù)庫(kù)的數(shù)據(jù)庫(kù)元數(shù)據(jù)中的數(shù)據(jù)庫(kù)名稱找到匹配的SQLErrorCodes實(shí)例。

你可以擴(kuò)展SQLErrorCodeSQLExceptionTranslator,如以下示例所示:

public class CustomSQLErrorCodesTranslator extends SQLErrorCodeSQLExceptionTranslator {

    protected DataAccessException customTranslate(String task, String sql, SQLException sqlEx) {
        if (sqlEx.getErrorCode() == -12345) {
            return new DeadlockLoserDataAccessException(task, sqlEx);
        }
        return null;
    }
}

在前面的示例中,特定的錯(cuò)誤代碼(-12345)被轉(zhuǎn)換,而其他錯(cuò)誤則由默認(rèn)轉(zhuǎn)換器實(shí)現(xiàn)轉(zhuǎn)換。要使用此自定義轉(zhuǎn)換器,必須通過setExceptionTranslator方法將其傳遞給JdbcTemplate,并且必須在需要此轉(zhuǎn)換器的所有數(shù)據(jù)訪問處理中使用此JdbcTemplate。以下示例顯示了如何使用此自定義轉(zhuǎn)換器:

private JdbcTemplate jdbcTemplate;

public void setDataSource(DataSource dataSource) {

    // create a JdbcTemplate and set data source
    this.jdbcTemplate = new JdbcTemplate();
    this.jdbcTemplate.setDataSource(dataSource);

    // create a custom translator and set the DataSource for the default translation lookup
    CustomSQLErrorCodesTranslator tr = new CustomSQLErrorCodesTranslator();
    tr.setDataSource(dataSource);
    this.jdbcTemplate.setExceptionTranslator(tr);

}

public void updateShippingCharge(long orderId, long pct) {
    // use the prepared JdbcTemplate for this update
    this.jdbcTemplate.update("update orders" +
        " set shipping_charge = shipping_charge * ? / 100" +
        " where id = ?", pct, orderId);
}

定制轉(zhuǎn)換器會(huì)傳遞一個(gè)數(shù)據(jù)源,以便在sql-error-codes.xml中查找錯(cuò)誤代碼。

3.3.4 運(yùn)行語(yǔ)句

運(yùn)行SQL語(yǔ)句需要很少的代碼。你需要一個(gè)數(shù)據(jù)源和一個(gè)JdbcTemplate,包括JdbcTemplate提供的便捷方法。下面的示例顯示了創(chuàng)建一個(gè)新表的最小但功能齊全的類需要包含的內(nèi)容:

import javax.sql.DataSource;
import org.springframework.jdbc.core.JdbcTemplate;

public class ExecuteAStatement {

    private JdbcTemplate jdbcTemplate;

    public void setDataSource(DataSource dataSource) {
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }

    public void doExecute() {
        this.jdbcTemplate.execute("create table mytable (id integer, name varchar(100))");
    }
}

3.3.5 運(yùn)行查詢

一些查詢方法返回單個(gè)值。要從一行中檢索計(jì)數(shù)或特定值,請(qǐng)使用queryForObject(..)。后者將返回的JDBC Type轉(zhuǎn)換為作為參數(shù)傳遞的Java類。如果類型轉(zhuǎn)換無效,則拋出InvalidDataAccessApiUsageException。以下示例包含兩種查詢方法,一種用于int,另一種用于查詢String:

import javax.sql.DataSource;
import org.springframework.jdbc.core.JdbcTemplate;

public class RunAQuery {

    private JdbcTemplate jdbcTemplate;

    public void setDataSource(DataSource dataSource) {
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }

    public int getCount() {
        return this.jdbcTemplate.queryForObject("select count(*) from mytable", Integer.class);
    }

    public String getName() {
        return this.jdbcTemplate.queryForObject("select name from mytable", String.class);
    }
}

除了單個(gè)結(jié)果查詢方法外,還有幾種方法返回一個(gè)列表,其中包含查詢返回的每一行的條目。最通用的方法是queryForList(..),它使用列名作為鍵,返回一個(gè)List,其中每個(gè)元素是一個(gè)Map,其中每個(gè)列包含一個(gè)條目。如果在前面的示例中添加一種方法來檢索所有行的列表,則可能如下所示:

private JdbcTemplate jdbcTemplate;

public void setDataSource(DataSource dataSource) {
    this.jdbcTemplate = new JdbcTemplate(dataSource);
}

public List<Map<String, Object>> getList() {
    return this.jdbcTemplate.queryForList("select * from mytable");
}

返回的列表類似于以下內(nèi)容:

[{name=Bob, id=1}, {name=Mary, id=2}]

3.3.6 更新數(shù)據(jù)庫(kù)

下面的示例更新某個(gè)主鍵的列:

import javax.sql.DataSource;
import org.springframework.jdbc.core.JdbcTemplate;

public class ExecuteAnUpdate {

    private JdbcTemplate jdbcTemplate;

    public void setDataSource(DataSource dataSource) {
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }

    public void setName(int id, String name) {
        this.jdbcTemplate.update("update mytable set name = ? where id = ?", name, id);
    }
}

在前面的示例中,SQL語(yǔ)句具有用于行參數(shù)的占位符。你可以將參數(shù)值作為可變參數(shù)或作為對(duì)象數(shù)組傳遞。因此,你應(yīng)該在基本包裝器類中顯式包裝基類型,或者應(yīng)該使用自動(dòng)裝箱。

3.3.7 檢索自動(dòng)生成的主鍵

update()便捷方法支持檢索由數(shù)據(jù)庫(kù)生成的主鍵。此支持是JDBC 3.0標(biāo)準(zhǔn)的一部分。有關(guān)詳細(xì)信息,請(qǐng)參見規(guī)范的第13.6章。該方法將PreparedStatementCreator作為其第一個(gè)參數(shù),這是指定所需插入語(yǔ)句的方式。另一個(gè)參數(shù)是KeyHolder,它包含從更新成功返回時(shí)生成的主鍵。沒有標(biāo)準(zhǔn)的單一方法來創(chuàng)建適當(dāng)?shù)腜reparedStatement(這說明了為什么方法簽名就是這樣)。以下示例在Oracle上有效,但在其他平臺(tái)上可能不適用:

final String INSERT_SQL = "insert into my_test (name) values(?)";
final String name = "Rob";

KeyHolder keyHolder = new GeneratedKeyHolder();
jdbcTemplate.update(connection -> {
    PreparedStatement ps = connection.prepareStatement(INSERT_SQL, new String[] { "id" });
    ps.setString(1, name);
    return ps;
}, keyHolder);

// keyHolder.getKey() now contains the generated key
3.4 控制數(shù)據(jù)庫(kù)連接

本節(jié)內(nèi)容包括:

  • 使用 DataSource

  • 使用 DataSourceUtils

  • 實(shí)現(xiàn) SmartDataSource

  • 擴(kuò)張 AbstractDataSource

  • 使用 SingleConnectionDataSource

  • 使用 DriverManagerDataSource

  • 使用 TransactionAwareDataSourceProxy

  • 使用 DataSourceTransactionManager

3.4.1 使用DataSource

Spring通過DataSource獲得與數(shù)據(jù)庫(kù)的連接。DataSource是JDBC規(guī)范的一部分,是通用的連接工廠。它使容器或框架可以從應(yīng)用程序代碼中隱藏連接池和事務(wù)管理問題。作為開發(fā)人員,你無需了解有關(guān)如何連接到數(shù)據(jù)庫(kù)的詳細(xì)信息。這是設(shè)置數(shù)據(jù)源的管理員的責(zé)任。你很可能在開發(fā)和測(cè)試代碼時(shí)同時(shí)擔(dān)當(dāng)這兩個(gè)角色,但是你不必知道如何配置生產(chǎn)數(shù)據(jù)源。

使用Spring的JDBC層時(shí),你可以從JNDI獲取數(shù)據(jù)源,也可以使用第三方提供的連接池實(shí)現(xiàn)來配置自己的數(shù)據(jù)源。傳統(tǒng)的選擇是帶有bean樣式的DataSource類的Apache Commons DBCP和C3P0。對(duì)于現(xiàn)代JDBC連接池,請(qǐng)考慮使用具有其生成器樣式的API的HikariCP。

你僅應(yīng)將DriverManagerDataSource和SimpleDriverDataSource類(包含在Spring發(fā)行版中)用于測(cè)試!當(dāng)發(fā)出多個(gè)連接請(qǐng)求時(shí),這些變體不提供緩沖池,并且性能不佳。

以下部分使用Spring的DriverManagerDataSource實(shí)現(xiàn)。稍后將介紹其他幾種DataSource變體。

要配置DriverManagerDataSource:

  1. 通常與JDBC連接一樣,獲得與DriverManagerDataSource的連接。

  2. 指定JDBC驅(qū)動(dòng)程序的標(biāo)準(zhǔn)類名,以便DriverManager可以加載驅(qū)動(dòng)程序類。

  3. 提供不同JDBC驅(qū)動(dòng)程序的URL。(請(qǐng)參閱驅(qū)動(dòng)程序的文檔以獲得正確的值。)

  4. 提供用戶名和密碼以連接到數(shù)據(jù)庫(kù)。

以下示例顯示了如何在Java中配置DriverManagerDataSource:

DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("org.hsqldb.jdbcDriver");
dataSource.setUrl("jdbc:hsqldb:hsql://localhost:");
dataSource.setUsername("sa");
dataSource.setPassword("");

以下示例顯示了相應(yīng)的XML配置:

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <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>

<context:property-placeholder location="jdbc.properties"/>

接下來的兩個(gè)示例顯示了DBCP和C3P0的基本連接和配置。要了解更多有助于控制池功能的選項(xiàng),請(qǐng)參閱相應(yīng)連接池實(shí)現(xiàn)的產(chǎn)品文檔。

以下示例顯示了DBCP配置:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <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>

<context:property-placeholder location="jdbc.properties"/>

以下示例顯示了C3P0配置:

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
    <property name="driverClass" value="${jdbc.driverClassName}"/>
    <property name="jdbcUrl" value="${jdbc.url}"/>
    <property name="user" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
</bean>

<context:property-placeholder location="jdbc.properties"/>

3.4.2 使用DataSourceUtils

SmartDataSource接口應(yīng)該由可以提供與關(guān)系數(shù)據(jù)庫(kù)的連接的類來實(shí)現(xiàn)。它擴(kuò)展了DataSource接口,以允許使用它的類查詢?cè)诮o定操作后是否應(yīng)關(guān)閉連接。當(dāng)你知道需要重用連接時(shí),這種用法非常有效。

3.4.4 擴(kuò)張AbstractDataSource

AbstractDataSource是Spring的DataSource實(shí)現(xiàn)的抽象基類。它實(shí)現(xiàn)了所有DataSource實(shí)現(xiàn)通用的代碼。如果編寫自己的DataSource實(shí)現(xiàn),則應(yīng)該擴(kuò)展AbstractDataSource類。

3.4.5 使用SingleConnectionDataSource

SingleConnectionDataSource類是SmartDataSource接口的實(shí)現(xiàn),該接口包裝了每次使用后都未關(guān)閉的單個(gè)Connection。這不是多線程功能。

如果任何客戶端代碼在假定建立池連接的情況下調(diào)用close(如使用持久性工具時(shí)),則應(yīng)將preventClose屬性設(shè)置為true。此設(shè)置返回一個(gè)封閉物理包裝的代理。請(qǐng)注意,你不能再將此對(duì)象轉(zhuǎn)換為本地Oracle Connection或類似對(duì)象。

SingleConnectionDataSource主要是一個(gè)測(cè)試類。SingleConnectionDataSource主要是一個(gè)測(cè)試類。例如,它結(jié)合簡(jiǎn)單的JNDI環(huán)境,可以在應(yīng)用服務(wù)器外部輕松測(cè)試代碼。與DriverManagerDataSource相比,它始終重用同一連接,避免了過多的物理連接創(chuàng)建。

3.4.6 使用DriverManagerDataSource

DriverManagerDataSource類是標(biāo)準(zhǔn)DataSource接口的實(shí)現(xiàn),該接口通過bean屬性配置純JDBC驅(qū)動(dòng)程序,并每次返回新的Connection。

此實(shí)現(xiàn)對(duì)于Java EE容器外部的測(cè)試和獨(dú)立環(huán)境很有用,可以作為Spring IoC容器中的DataSource bean或與簡(jiǎn)單的JNDI環(huán)境結(jié)合使用。假定使用池的Connection.close()調(diào)用將關(guān)閉連接,因此任何可識(shí)別DataSource的持久性代碼都應(yīng)起作用。但是,即使在測(cè)試環(huán)境中,使用JavaBean風(fēng)格的連接池(例如commons-dbcp)也是如此容易,以至于總是在DriverManagerDataSource上使用這樣的連接池。

3.4.7 使用TransactionAwareDataSourceProxy

TransactionAwareDataSourceProxy是目標(biāo)DataSource的代理。代理包裝該目標(biāo)DataSource以增加對(duì)Spring管理的事務(wù)的意識(shí)。在這方面,它類似于Java EE服務(wù)器提供的事務(wù)性JNDI數(shù)據(jù)源。

除非需要調(diào)用已經(jīng)存在的代碼并通過標(biāo)準(zhǔn)的JDBC DataSource接口實(shí)現(xiàn),否則很少需要使用此類。在這種情況下,你仍然可以使該代碼可用,同時(shí)使該代碼參與Spring管理的事務(wù)。通常,最好使用更高級(jí)別的資源管理抽象來編寫自己的新代碼,例如JdbcTemplate或DataSourceUtils。

有關(guān)更多詳細(xì)信息,請(qǐng)參見TransactionAwareDataSourceProxy javadoc。

3.4.8 使用DataSourceTransactionManager

DataSourceTransactionManager類是單個(gè)JDBC數(shù)據(jù)源的PlatformTransactionManager實(shí)現(xiàn)。它將JDBC連接從指定的數(shù)據(jù)源綁定到當(dāng)前正在執(zhí)行的線程,可能允許每個(gè)數(shù)據(jù)源一個(gè)線程連接。

通過DataSourceUtils.getConnection(DataSource)而不是Java EE的標(biāo)準(zhǔn)DataSource.getConnection檢索JDBC連接需要應(yīng)用程序代碼。它拋出未檢查的org.springframework.dao異常,而不是經(jīng)過檢查的SQLException。所有框架類(例如JdbcTemplate)都隱式使用此策略。如果不與該事務(wù)管理器一起使用,則查找策略的行為與普通策略完全相同。因此,可以在任何情況下使用它。

DataSourceTransactionManager類支持自定義隔離級(jí)別和超時(shí),這些隔離級(jí)別和超時(shí)將應(yīng)用于適當(dāng)?shù)腏DBC語(yǔ)句查詢超時(shí)。為了支持后者,應(yīng)用程序代碼必須使用JdbcTemplate或?yàn)槊總€(gè)創(chuàng)建的語(yǔ)句調(diào)用DataSourceUtils.applyTransactionTimeout(..)方法。

在單資源情況下,可以使用此實(shí)現(xiàn)而不是JtaTransactionManager,因?yàn)樗恍枰萜髦С諮TA。只要遵循所需的連接查找模式,就可以在兩者之間進(jìn)行切換只是配置問題。JTA不支持自定義隔離級(jí)別。

3.5 JDBC批量操作

如果將多個(gè)調(diào)用批處理到同一條準(zhǔn)備好的語(yǔ)句,則大多數(shù)JDBC驅(qū)動(dòng)程序都會(huì)提高性能。通過將更新分組成批,可以限制到數(shù)據(jù)庫(kù)的往返次數(shù)。

3.5.3 使用JdbcTemplate的基本批處理操作

通過實(shí)現(xiàn)特殊接口的兩個(gè)方法BatchPreparedStatementSetter并將該實(shí)現(xiàn)作為batchUpdate方法調(diào)用中的第二個(gè)參數(shù)傳入,可以完成JdbcTemplate批處理。你可以使用getBatchSize方法提供當(dāng)前批處理的大小。你可以使用setValues方法設(shè)置語(yǔ)句的參數(shù)值。此方法稱為你在getBatchSize調(diào)用中指定的次數(shù)。以下示例根據(jù)列表中的條目更新t_actor表,并將整個(gè)列表用作批處理:

public class JdbcActorDao implements ActorDao {

    private JdbcTemplate jdbcTemplate;

    public void setDataSource(DataSource dataSource) {
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }

    public int[] batchUpdate(final List<Actor> actors) {
        return this.jdbcTemplate.batchUpdate(
                "update t_actor set first_name = ?, last_name = ? where id = ?",
                new BatchPreparedStatementSetter() {
                    public void setValues(PreparedStatement ps, int i) throws SQLException {
                        Actor actor = actors.get(i);
                        ps.setString(1, actor.getFirstName());
                        ps.setString(2, actor.getLastName());
                        ps.setLong(3, actor.getId().longValue());
                    }
                    public int getBatchSize() {
                        return actors.size();
                    }
                });
    }

    // ... additional methods
}

如果處理更新流或從文件讀取,則可能具有首選的批處理大小,但最后一批可能沒有該數(shù)量的條目(譯者:意思是最后一批數(shù)據(jù)可能沒有分割數(shù)量大)。在這種情況下,可以使用InterruptibleBatchPreparedStatementSetter接口,該接口可在輸入源耗盡后中斷批處理(譯者:意思是數(shù)據(jù)源數(shù)據(jù)消耗完)。isBatchExhausted方法使你可以發(fā)出批處理結(jié)束的信號(hào)。

3.5.2 批處理操作的對(duì)象列表

JdbcTemplate和NamedParameterJdbcTemplate都提供了另一種提供批處理更新的方式。無需實(shí)現(xiàn)特殊的批處理接口,而是將調(diào)用中的所有參數(shù)值作為列表提供??蚣苎h(huán)這些值,并使用一個(gè)內(nèi)部語(yǔ)句setter。API會(huì)有所不同,具體取決于你是否使用命名參數(shù)。對(duì)于命名參數(shù),你提供一個(gè)SqlParameterSource數(shù)組,該批處理的每個(gè)成員都有一個(gè)條目。你可以使用SqlParameterSourceUtils.createBatch便捷方法創(chuàng)建此數(shù)組,傳入一個(gè)bean樣式的對(duì)象數(shù)組(帶有與參數(shù)相對(duì)應(yīng)的getter方法),字符串鍵Map實(shí)例(包含對(duì)應(yīng)的參數(shù)作為值),或者混合使用。

以下示例顯示使用命名參數(shù)的批處理更新:

public class JdbcActorDao implements ActorDao {

    private NamedParameterTemplate namedParameterJdbcTemplate;

    public void setDataSource(DataSource dataSource) {
        this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
    }

    public int[] batchUpdate(List<Actor> actors) {
        return this.namedParameterJdbcTemplate.batchUpdate(
                "update t_actor set first_name = :firstName, last_name = :lastName where id = :id",
                SqlParameterSourceUtils.createBatch(actors));
    }

    // ... additional methods
}

對(duì)于使用經(jīng)典的SQL語(yǔ)句?占位符,則傳入包含更新值的對(duì)象數(shù)組的列表。該對(duì)象數(shù)組在SQL語(yǔ)句中的每個(gè)占位符必須具有一個(gè)條目,并且它們的順序必須與SQL語(yǔ)句中定義的順序相同。

以下示例與前面的示例相同,不同之處在于它使用經(jīng)典的JDBC?占位符:

public class JdbcActorDao implements ActorDao {

    private JdbcTemplate jdbcTemplate;

    public void setDataSource(DataSource dataSource) {
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }

    public int[] batchUpdate(final List<Actor> actors) {
        List<Object[]> batch = new ArrayList<Object[]>();
        for (Actor actor : actors) {
            Object[] values = new Object[] {
                    actor.getFirstName(), actor.getLastName(), actor.getId()};
            batch.add(values);
        }
        return this.jdbcTemplate.batchUpdate(
                "update t_actor set first_name = ?, last_name = ? where id = ?",
                batch);
    }

    // ... additional methods
}

我們前面介紹的所有批處理更新方法都返回一個(gè)int數(shù)組,其中包含每個(gè)批處理?xiàng)l目的受影響行數(shù)。此計(jì)數(shù)由JDBC驅(qū)動(dòng)程序報(bào)告。如果該計(jì)數(shù)不可用,則JDBC驅(qū)動(dòng)程序?qū)⒎祷刂?2。

在這種情況下,通過在基礎(chǔ)PreparedStatement上自動(dòng)設(shè)置值,需要從給定的Java類型派生每個(gè)值的對(duì)應(yīng)JDBC類型。盡管這通常效果很好,但存在潛在的問題(例如,包含Map的空值)。在這種情況下,Spring默認(rèn)情況下會(huì)調(diào)用ParameterMetaData.getParameterType,這對(duì)于JDBC驅(qū)動(dòng)程序可能會(huì)很昂貴。如果遇到性能問題,則應(yīng)使用最新的驅(qū)動(dòng)程序版本,并考慮將spring.jdbc.getParameterType.ignore屬性設(shè)置為true(作為JVM系統(tǒng)屬性或在類路徑根目錄中的spring.properties文件中)。如關(guān)于Oracle 12c(SPR-16139)的報(bào)道。

或者,你可以考慮通過BatchPreparedStatementSetter(如前所示),通過為基于“List <Object []>的調(diào)用提供的顯式類型數(shù)組,通過在服務(wù)器上的“registerSqlType調(diào)用來顯式指定相應(yīng)的JDBC類型。自定義“MapSqlParameterSource實(shí)例,或者通過BeanPropertySqlParameterSource實(shí)例從Java聲明的屬性類型中獲取SQL類型,即使對(duì)于null值也是如此。

3.5.3 具有多個(gè)批次的批次操作

前面的批處理更新示例處理的批處理太大,以至于你想將它們分解成幾個(gè)較小的批處理。你可以通過多次調(diào)用batchUpdate方法來使用前面提到的方法來執(zhí)行此操作,但是現(xiàn)在有一個(gè)更方便的方法。除了SQL語(yǔ)句外,此方法還包含一個(gè)對(duì)象集合,該對(duì)象包含參數(shù),每個(gè)批處理要進(jìn)行的更新次數(shù)以及一個(gè)ParameterizedPreparedStatementSetter來設(shè)置準(zhǔn)備好的語(yǔ)句的參數(shù)值??蚣鼙闅v提供的值,并將更新調(diào)用分成指定大小的批處理。

以下示例顯示了使用100的批量大小的批量更新:

public class JdbcActorDao implements ActorDao {

    private JdbcTemplate jdbcTemplate;

    public void setDataSource(DataSource dataSource) {
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }

    public int[][] batchUpdate(final Collection<Actor> actors) {
        int[][] updateCounts = jdbcTemplate.batchUpdate(
                "update t_actor set first_name = ?, last_name = ? where id = ?",
                actors,
                100,
                (PreparedStatement ps, Actor actor) -> {
                    ps.setString(1, actor.getFirstName());
                    ps.setString(2, actor.getLastName());
                    ps.setLong(3, actor.getId().longValue());
                });
        return updateCounts;
    }

    // ... additional methods
}

此調(diào)用的批處理更新方法返回一個(gè)int數(shù)組,該數(shù)組包含每個(gè)批處理的數(shù)組條目以及每個(gè)更新受影響的行數(shù)的數(shù)組。頂層數(shù)組的長(zhǎng)度指示運(yùn)行的批處理數(shù)量,第二層樹脂的長(zhǎng)度指示該批處理中的更新數(shù)量。 每個(gè)批次中的更新數(shù)量應(yīng)該是為所有批次提供的批次大?。ㄗ詈笠粋€(gè)可能更少),這取決于所提供的更新對(duì)象的總數(shù)。每個(gè)更新語(yǔ)句的更新計(jì)數(shù)是JDBC驅(qū)動(dòng)程序報(bào)告的更新計(jì)數(shù)。如果該計(jì)數(shù)不可用,則JDBC驅(qū)動(dòng)程序?qū)⒎祷刂?2。

到此,關(guān)于“如何使用JDBC核心類控制進(jìn)行JDBC處理”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!

向AI問一下細(xì)節(jié)
推薦閱讀:
  1. jdbc基本使用詳解
  2. JDBC

免責(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