【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 +
'}';
}
}