对于一些复杂的业务逻辑,使用存储过程可以提高数据库操作的效率和安全性。本文将详细介绍如何在SpringBoot项目中使用 JdbcTemplate
工具操作存储过程,方便地与数据库进行交互,调用存储过程。
本文目录
- 一、存储过程创建
- 二、配置数据库连接
- 三、存储过程返回单条数据
- 四、存储过程返回多条数据
一、存储过程创建
新建一个商品表存放商品数据,并创建一个获取商品信息的存储过程。
-- 商品表
CREATE TABLE products (id INT AUTO_INCREMENT PRIMARY KEY,name VARCHAR(255) NOT NULL,price DECIMAL(10, 2) NOT NULL,stock INT NOT NULL
);-- 创建存储过程
DELIMITER //CREATE PROCEDURE GetProductById(IN productId INT, OUT productName VARCHAR(255), OUT productPrice DECIMAL(10, 2), OUT productStock INT)
BEGINSELECT name, price, stock INTO productName, productPrice, productStockFROM productsWHERE id = productId;
END //DELIMITER ;
参数使用
IN、OUT
区分输入和输出
二、配置数据库连接
操作存储过程之前需要在 application.properties
中配置数据库连接信息:
spring.datasource.url=jdbc:mysql://localhost:3306/ecommerce
spring.datasource.username=root
spring.datasource.password=
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
三、存储过程返回单条数据
接下来使用 JdbcTemplate
来调用存储过程。首先,需要创建一个 ProductRepository
类来封装数据库操作进行MVC分层,之后创建对应的Service以及Controller编写一个接口进行测试。
ProductRepository :
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;import java.sql.Types;
import java.util.HashMap;
import java.util.Map;@Repository
public class ProductRepository {@Autowiredprivate JdbcTemplate jdbcTemplate;public Map<String, Object> getProductById(int productId) {// 输入参数Map<String, Object> inParams = new HashMap<>();inParams.put("productId", productId);// 输出参数Map<String, Integer> outParams = new HashMap<>();outParams.put("productName", Types.VARCHAR);outParams.put("productPrice", Types.DECIMAL);outParams.put("productStock", Types.INTEGER);// 调用return jdbcTemplate.call(new java.util.function.Function<Connection, CallableStatement>() {@Overridepublic CallableStatement apply(Connection con) {try {// 准备存储过程调用String callString = "{call GetProductById(?, ?, ?, ?)}";CallableStatement cs = con.prepareCall(callString);// 设置输入参数cs.setInt(1, productId);// 注册输出参数cs.registerOutParameter(2, Types.VARCHAR);cs.registerOutParameter(3, Types.DECIMAL);cs.registerOutParameter(4, Types.INTEGER);return cs;} catch (SQLException e) {throw new RuntimeException(e);}}}, inParams, outParams);}
}
ProductService :
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.Map;@Service
public class ProductService {@Autowiredprivate ProductRepository productRepository;public Map<String, Object> getProductById(int productId) {return productRepository.getProductById(productId);}
}
ProductController :
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;import java.util.Map;@RestController
public class ProductController {@Autowiredprivate ProductService productService;@GetMapping("/products/{productId}")public Map<String, Object> getProductById(@PathVariable int productId) {return productService.getProductById(productId);}
}
如上,可以看到上面的操作只能获取单条商品信息数据,如果需要获取多条还需要再优化一下。
四、存储过程返回多条数据
创建一个存储过程,用于返回价格大于某个阈值的所有商品信息。
DELIMITER //CREATE PROCEDURE GetProductsByPriceThreshold(IN priceThreshold DECIMAL(10, 2))
BEGINSELECT id, name, price, stockFROM productsWHERE price > priceThreshold;
END //DELIMITER ;
这个时候会返回多条数据,上面的Map是不适用的,这时我们需要将返回的数据封装成实体类进行操作。
Product:
public class Product {private int id;private String name;private double price;private int stock;public Product(int id, String name, double price, int stock) {this.id = id;this.name = name;this.price = price;this.stock = stock;}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public double getPrice() {return price;}public void setPrice(double price) {this.price = price;}public int getStock() {return stock;}public void setStock(int stock) {this.stock = stock;}@Overridepublic String toString() {return "Product{" +"id=" + id +", name='" + name + '\'' +", price=" + price +", stock=" + stock +'}';}
}
在 ProductRepository
类中,使用 JdbcTemplate
调用存储过程并处理结果集:
ProductRepository :
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;@Repository
public class ProductRepository {@Autowiredprivate JdbcTemplate jdbcTemplate;public List<Product> getProductsByPriceThreshold(double priceThreshold) {String sql = "{call GetProductsByPriceThreshold(?)}";return jdbcTemplate.query(sql, new Object[]{priceThreshold}, new ProductRowMapper());}private static class ProductRowMapper implements RowMapper<Product> {@Overridepublic Product mapRow(ResultSet rs, int rowNum) throws SQLException {int id = rs.getInt("id");String name = rs.getString("name");double price = rs.getDouble("price");int stock = rs.getInt("stock");return new Product(id, name, price, stock);}}
}
ProductService :
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.List;@Service
public class ProductService {@Autowiredprivate ProductRepository productRepository;public List<Product> getProductsByPriceThreshold(double priceThreshold) {return productRepository.getProductsByPriceThreshold(priceThreshold);}
}
ProductController :
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;import java.util.List;@RestController
public class ProductController {@Autowiredprivate ProductService productService;@GetMapping("/products/byPriceThreshold")public List<Product> getProductsByPriceThreshold(@RequestParam double priceThreshold) {return productService.getProductsByPriceThreshold(priceThreshold);}
}
可以看到使用用
JdbcTemplate
的query
方法调用存储过程,并通过RowMapper
可以将结果集映射为Product
对象列表。
← 上一篇 Java进阶——常用类及常用方法详解 | 记得点赞、关注、收藏哦! | 下一篇 Java进阶——数组超详细整理 → |