1. 程式人生 > >【Spring Data Access】SimplJdbcCall呼叫儲存過程

【Spring Data Access】SimplJdbcCall呼叫儲存過程

SimpleJdbcCall 呼叫儲存過程

SimpleJdbcCall主要用來進行呼叫儲存過程,這個方法使用起來也比較簡單,先通過一個比較簡單的示例來熟悉一下api

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.
core.namedparam.MapSqlParameterSource; import org.springframework.jdbc.core.namedparam.SqlParameterSource; import org.springframework.jdbc.core.simple.SimpleJdbcCall; import javax.sql.DataSource; import java.util.Map; /** * @author jiangjian */ public class SimpleJdbcCallSample { public static
void main(String[] args) { ApplicationContext ac = new AnnotationConfigApplicationContext(Config.class); JdbcTemplate jdbcTemplate = ac.getBean(JdbcTemplate.class); //初始化資料庫 jdbcTemplate.execute("drop table if exists user "); jdbcTemplate.execute("create table user(id int auto_increment primary key, name varchar(40), age int)"
); jdbcTemplate.execute("insert into user(name, age) values('jiangjian', 26)"); jdbcTemplate.execute("DROP PROCEDURE IF EXISTS read_user;"); jdbcTemplate.execute("CREATE PROCEDURE read_user (\n" + " IN in_id BIGINT,\n" + " OUT out_id BIGINT,\n" + " OUT out_name VARCHAR(40),\n" + " OUT out_age int)\n" + "BEGIN\n" + " SELECT id, name, age\n" + " INTO out_id, out_name, out_age\n" + " FROM user where id = in_id;\n" + "END"); DataSource dataSource = ac.getBean(DataSource.class); SimpleJdbcCall simpleJdbcCall = new SimpleJdbcCall(dataSource).withProcedureName("read_user"); SqlParameterSource in = new MapSqlParameterSource() .addValue("in_id", "1"); Map<String, Object> result = simpleJdbcCall.execute(in); User user = new User(); user.setId((Long) result.get("out_id")); user.setName((String) result.get("out_name")); user.setAge((Integer) result.get("out_age")); System.out.println(user); //清理環境 jdbcTemplate.execute("drop table user"); } }

上面例子中,我們定義了一個儲存過程:

CREATE PROCEDURE read_user (
    IN in_id BIGINT,
    OUT out_id BIGINT,
    OUT out_name VARCHAR(40),
    OUT out_age int)
BEGIN
    SELECT id, name, age
    INTO out_id, out_name, out_age
    FROM user where id = in_id;
END

從這個定義來看,該儲存過程的入參是: in_id, 輸出的結果是: out_id, out_name, out_age;

在例項化SimpleJdbcCall的時候,我們得配置DataSource以及對應儲存過程名稱,如上面示例:
new SimpleJdbcCall(dataSource).withProcedureName("read_user")

通過SimpleJdbcCall#execute方法可以觸發執行,這個方法接受接受多種形式的入參(通過過載),這裡我們使用SqlParameterSource作為入參型別,這個主要用來配置儲存過程入參的資訊,基本上也是Map的形式。
這個方法的返回型別是Map<String, Object>,map當中的key就是我們儲存過程中定義的輸出值的名稱.

另外一個需要注意的是,不同的資料庫產品可能對儲存過程的輸出的名稱做了不同的處理,有些可能統一轉化成小寫形式,或者大寫形式,所以上面的out_id可能在其他資料產品就是OUT_ID,為了相容這種情況,我們可以使用JdbcTemplate作為SimleJdbcCall的構造引數,具體的方式如下:

SimpleJdbcCall simpleJdbcCall = new SimpleJdbcCall(jdbcTemplate).withProcedureName("read_user");
   jdbcTemplate.setResultsMapCaseInsensitive(false);

對應SimpleJdbcCall我們也可以顯示的配置入參的名稱(通過useInParameterNames方法),你可以配置全部的入參名稱,也可以配置一部分,如果提供的資訊不全的時候,SimpleJdbcCall會去查詢相關的procedure metadata去獲取全部必須的資訊,當然這種方式也是比較浪費效能的,我們在配置好全部的入參名稱後,可以顯示的設定不要通過查詢metadata來獲取全部資訊了(因為資訊我們已經自己給全了<_<), 配置的程式碼如下:

JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
jdbcTemplate.setResultsMapCaseInsensitive(true);
SimpleJdbcCall simpleJdbcCall = new SimpleJdbcCall(jdbcTemplate)
              .withProcedureName("read_user")
              .withoutProcedureColumnMetaDataAccess()
              .useInParameterNames("in_id");

當然你可以配置儲存過程的入參和出參的資訊,主要是通過declareParameters方法來進行設定,對於當前示例,可以使用如下配置:

SimpleJdbcCall simpleJdbcCall = new SimpleJdbcCall(jdbcTemplate)
         .withProcedureName("read_user")
         .useInParameterNames("in_id")
         .declareParameters(new SqlParameter("in_id", Types.BIGINT),
                 new SqlOutParameter("out_id", Types.BIGINT),
                 new SqlOutParameter("out_name", Types.VARCHAR),
                 new SqlOutParameter("out_age", Types.INTEGER));

SqlParameter和SqlOutParameter也比較容易理解其用途,用來指定名稱和型別。

附:
下面是上面示例關聯類的定義:
1 Config.java

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;

import javax.sql.DataSource;

/**
 * @author jiangjian
 */
@Configuration
@ComponentScan
@PropertySource("classpath:jdbc.properties")
public class Config {
    @Autowired
    private Environment env;

    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(env.getProperty("spring.datasource.driver-class-name"));
        dataSource.setUrl(env.getProperty("spring.datasource.url"));
        dataSource.setUsername(env.getProperty("spring.datasource.username"));
        dataSource.setPassword(env.getProperty("spring.datasource.password"));
        return dataSource;
    }

    @Bean
    public JdbcTemplate jdbcTemplate() {
        return new JdbcTemplate(dataSource());
    }
}

2 jdbc.properties

spring.datasource.url=jdbc:mysql://localhost/test?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&autoReconnect=true&failOverReadOnly=false&autoReconnectForPools=true&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

3 User.java

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

    public User() {
    }

    public User(Long id, String name) {
        this.id = id;
        this.name = name;
    }

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}