Spring SimpleJdbcCall调用存储过程和函数

在这个Spring JDBC 教程中,我将与您分享如何使用Spring SimpleJdbcCall类来调用存储过程并在数据库中执行函数。您将看到Spring如何简化您需要编写的代码,而不是使用普通的JDBC代码来调用存储过程。假设我们有一个声明如下的数据源:

DriverManagerDataSource dataSource = new DriverManagerDataSource();;
 
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/dbname");
dataSource.setUsername("root");
dataSource.setPassword("password");

基本上,以下是在Spring 使用SimpleJdbcCall数据库存储过程的步骤:

1. 创建一个新实例 SimpleJdbcCall 并指定过程的名称:

SimpleJdbcCall actor = new SimpleJdbcCall(dataSource).withProcedureName("name");

2. 如果过程需要,请指定一些 IN 参数:

SqlParameterSource params = new MapSqlParameterSource();
params.addValue("in_param_1", "value1")
      .addValue("in_param_2", "value2");

3. 执行该过程并将 OUT 参数的值获取到 Map 中

Map<String, Object> out = actor.execute(params);

4. 读出从过程中返回的值:

String value1 = (String) out.get("out_param_1");
Integer value2 = (Integer) out.get("out_param_2");
请注意,IN 和 OUT 参数的名称必须与存储过程/函数声明的名称匹配。
现在,让我们看一些具体的例子。

1. 使用SimpleJdbcCall具有输入和输出参数的存储过程

假设我们在MySQL数据库中有一个名为contact的表,结构如下:

CREATE TABLE IF NOT EXISTS `contact` (
  `id` int NOT NULL AUTO_INCREMENT,
  `name` varchar(45) COLLATE utf8mb4_unicode_ci NOT NULL,
  `email` varchar(45) COLLATE utf8mb4_unicode_ci NOT NULL,
  `address` varchar(45) COLLATE utf8mb4_unicode_ci NOT NULL,
  `telephone` varchar(45) COLLATE utf8mb4_unicode_ci NOT NULL,
  PRIMARY KEY (`id`) USING BTREE
)

假设我们在MySQL数据库中有一个名为get_contact的存储过程,声明如下:

DELIMITER //
CREATE PROCEDURE `get_contact`(IN contact_id INTEGER,
    OUT _name varchar(45),
    OUT _email varchar(45),
    OUT _address varchar(45),
    OUT _phone varchar(45))
BEGIN
    SELECT name, email, address, telephone
    INTO _name, _email, _address, _phone
    FROM Contact WHERE id = contact_id;
END
//
DELIMITER ;

请注意,此存储过程具有一个 IN 参数 contact_id 和 4 个 OUT 参数_name_email_address_phone。下面的代码段说明了如何使用SimpleJdbcCall来调用该存储过程:

int contactId = 10;
 
SimpleJdbcCall actor = new SimpleJdbcCall(dataSource).withProcedureName("get_contact");
SqlParameterSource inParams = new MapSqlParameterSource().addValue("contact_id", contactId);
 
Map<String, Object> outParams = actor.execute(inParams);
 
String name = (String) outParams.get("_name");
String email = (String) outParams.get("_email");
String address = (String) outParams.get("_address");
String phone = (String) outParams.get("_phone");
 
System.out.println(name + ", " + email + ", " + address + ", " + phone);

如果只有一个 IN 参数,则可以将值直接传递给 execute() 方法,如下所示:

Map<String, Object> out = simpleJdbcCall.execute(10);

2. 使用SimpleJdbcCall返回结果集的存储过程

假设我们有一个存储过程,它从表中返回行,如下所示:

CREATE PROCEDURE `list_contact`()
BEGIN
    SELECT * FROM Contact ORDER BY name ASC;
END
下面的代码示例演示如何调用此存储过程并读取结果:
SimpleJdbcCall procedureActor = new SimpleJdbcCall(dataSource)
        .withProcedureName("list_contact")
        .returningResultSet("contacts", new RowMapper<Contact>() {
 
            @Override
            public Contact mapRow(ResultSet rs, int rowNum) throws SQLException {
                Contact contact = new Contact();
                 
                contact.setId(rs.getInt("id"));
                contact.setName(rs.getString("name"));
                contact.setEmail(rs.getString("email"));
                contact.setAddress(rs.getString("address"));
                contact.setTelephone(rs.getString("telephone"));
                 
                return contact;
            }
        });
 
Map<String, Object> out = procedureActor.execute();
 
List<Contact> listContacts = (List<Contact>) out.get("contacts");
如您所见,我们用两个参数调用 返回ResultSet()方法:第一个参数是返回的Map中键的名称,我们将使用它来读取结果。第二个是 行映射器,用于直接读取结果集。如果您有一个域类,其中包含的字段名称与数据库表中的列名完全匹配,则可以使用  BeanPropertyRowMapper 类来简化代码,如下所示:
SimpleJdbcCall procedureActor = new SimpleJdbcCall(dataSource)
        .withProcedureName("list_contact")
        .returningResultSet("contacts", BeanPropertyRowMapper.newInstance(Contact.class));
 
Map<String, Object> out = procedureActor.execute();
List<Contact> listContacts = (List<Contact>) out.get("contacts");

Contact类的代码如下所示:

public class Contact {
    private Integer id;
    private String name;
    private String email;
    private String address;
    private String telephone;
 
     
    // getters...
    // setters...
     
}

3. 使用SimpleJdbcCall来执行函数

假设我们在数据库中有一个函数,声明如下:

CREATE FUNCTION `calculate_book_rating`(book_title varchar(128)) RETURNS double
    READS SQL DATA
BEGIN
    DECLARE out_value DOUBLE;
    SELECT AVG(r.rating) AS AvgRating FROM Review r JOIN Book b
        ON r.book_id = b.book_id AND b.title = book_title
        INTO out_value;
RETURN out_value;
END

此函数有一个名为 book_title的参数,它返回双精度值。下面的代码示例演示如何在春季使用SimpleJdbcCall来执行此函数:

SimpleJdbcCall procedureActor = new SimpleJdbcCall(dataSource)
        .withFunctionName("calculate_book_rating");
 
String bookTitle = "Effective Java (3rd Edition)";
 
Double rating = procedureActor.executeFunction(Double.class, bookTitle);
这就是如何在春季使用SimpleJdbcCall l类来调用存储过程并执行函数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值