Logo

郎哥编程

在Spring框架中使用SQL存储过程

2018-10-28 1097

Spring框架也支持对SQL存储过程的调用,SQL存储过程是一组预先定义好的SQL语句,并存储到数据库管理系统中,外部程序可以直接调用执行。本课主要讨论在Spring框架中应用程序如何调用MySQL存储过程。通过本课的学习,可以达到如下目标。

●  认识和理解SQL存储过程

●  在Spring框架中调用SQL存储过程


1、 认识SQL存储过程


类似于编程语言中的函数,SQL存储过程是SQL语言中的函数。开发者可以把查询、更新、插入等SQL语句按照一的规范写成存储过程,存储到数据库管理系统中,外部应用程序可以直接调用。

使用SQL存储过程,可以提高SQL语句的执行效率。一是SQL语句都是编译后再执行,而SQL存储过程已经预先在数据库管理系统编译通过,省略了编译环节;二是存储过程执行后,数据库管理系统会对存储过程进行缓存,下次执行该存储过程时,会直接从缓存中调用,执行速度要高于普通的SQL语句。

使用SQL存储过程,提高了SQL代码的可维护性。一般来说,普通SQL代码会分布在系统中各个模块,当需要修改SQL代码时,就需要到各个模块中修改,代码维护工作量大。如果把相同的SQL代码写成一个存储过程,由各个模块统一调用,当需要修改SQL代码时,只需要修改存储过程就可以了。

使用SQL存储过程,也提高了数据库的安全性,可以有效防止SQL注入对数据库的攻击。

下面以课程案例mooc数据库为例,说明SQL存储过程的创建和使用方法。在mooc数据库中创建一个名为get_coursename_number的存储过程,该存储过程使用course表的number字段,查询相对应的课程,并返回课程名称。进入MySQL命令行窗口,输入下面的命令,创建get_coursename_number存储过程。

mysql> use mooc
Database changed
mysql> delimiter $$
mysql> create procedure get_coursename_number(
    -> IN in_number varchar(50),
    -> OUT out_name varchar(50)
    -> )
    -> begin
    -> select name INTO out_name
    -> from course where
    -> number = in_number;
    -> end$$

存储过程创建成功后,在MySQL命令行窗口,可以执行存储过程。在MySQL命令行窗口,输入下面的命令。

mysql> call get_coursename_number('0001',@name);

call为调用存储过程的命令,call后面为存储过程名称。括号内为存储过程要传入和输出的参数。输出的参数@name可以通过select命令查看。如下图所示。

 image.png                                 


2、在Spring框架中调用SQL存储过程


Spring框架提供了JDBC封装类SimpleJdbcCall,SimpleJdbcCall主要用于调用SQL存储过程或存储函数,该类简化了Java调用存储过程的复杂机制,利用SqlParameterSource类管理存储过程传入的参数,利用Map数据类型接收存储过程返回的参数。使用SimpleJdbcCall调用存储过程的代码如下。

public String getCoureName(String number) {
    // TODO Auto-generated method stub
    SqlParameterSource in = new MapSqlParameterSource().addValue("in_number",number);
    Map<String, Object> out = jdbcCall.execute(in);
    String courseName =  (String) out.get("out_name");
    return courseName;
}

getCoureName方法执行已定义的get_coursename_number存储过程,并返回课程名称。get_coursename_number存储过程要求传入课程编号,并根据课程编号查询课程,返回课程名称字段,具体执行的SQL语句已在get_coursename_number存储过程中定义。SqlParameterSource管理存储过程传入的参数,使用其addValue方法将参数添加到SqlParameterSource,并作为SimpleJdbcCall类execute方法的传入参数,execute方法负责执行存储过程,并以Map方式返回存储过程的执行结果。

下面给出具体执行存储过程的案例程序。案例程序的数据源采用mooc数据库,mooc数据库的结构以及本案例中没有列出的代码详见《Spring使用JDBC访问MySQL数据库》一文。

(1)创建数据访问对象(DAO)

在《Spring使用JDBC访问MySQL数据库》一文中,已经创建了基于JdbcTemplate的数据访问DAO类。本文创建基于SimpleJdbcCall过程调用的数据访问DAO类。

package com.milihua.springprogram.jdbc;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
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 com.milihua.springprogram.dao.CourseDao;
import com.milihua.springprogram.entity.Course;
 
public class CourseJDBCCallProcedure implements CourseDao {
private DataSource dataSource;
private SimpleJdbcCall jdbcCall;
 
@Override
public void setDataSource(DataSource ds) {
    // TODO Auto-generated method stub
    this.dataSource = ds;
    this.jdbcCall = new SimpleJdbcCall(ds).withProcedureName("get_coursename_number");
 
}
 
@Override
public void insertCourse(Course inCourse) {
    // TODO Auto-generated method stub
 
}
 
@Override
public Course getCourse(String number) {
    // TODO Auto-generated method stub
    return null;
}
 
@Override
public List<Course> listCourse() {
    // TODO Auto-generated method stub
    JdbcTemplate jdbcTemplateObject = new JdbcTemplate(dataSource);
    String SQL = "select * from course";
    List<Course> students = jdbcTemplateObject.query(SQL, new CourseMapper());
    return students;
}
 
@Override
public void delete(String number) {
    // TODO Auto-generated method stub
 
}
 
@Override
public void update(Course inCourse) {
    // TODO Auto-generated method stub
 
}
 
@Override
public String getCoureName(String number) {
    // TODO Auto-generated method stub
    SqlParameterSource in = new MapSqlParameterSource().addValue("in_number",number);
    Map<String, Object> out = jdbcCall.execute(in);
    String courseName =  (String) out.get("out_name");
    return courseName;
}
 
}

(2)创建Spring配置文件

创建procedure.xml配置文件,配置文件定义了数据源和DAO类。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd ">
 
   <!-- 配置数据源 -->
   <bean id="dataSource"
      class="org.springframework.jdbc.datasource.DriverManagerDataSource">
      <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
      <property name="url" value="jdbc:mysql://localhost:3306/mooc?characterEncoding=utf8"/>
      <property name="username" value="root"/>
      <property name="password" value="~123456q"/>
   </bean>
 
   <!-- Definition for courseJDBCTemplate bean -->
   <bean id="courseJDBCCallProcedure"
      class="com.milihua.springprogram.jdbc.CourseJDBCCallProcedure">
      <property name="dataSource"  ref="dataSource" />   
   </bean>
</beans>

(3)编写测试程序

测试程序首先读取procedure.xml配置文件,初始化配置文件中定义的DAO类和数据源,并返回上下文环境context。然后,调用context的getBean方法获取DAO类的实例,获得DAO实例后,再调用DAO实例的listCourse()方法查询所有记录,最后迭代listCourse()返回的结果集,在迭代过程中,调用DAO实例的getCoureName方法执行已定义的存储过程,获取课程名称。

package test;
import java.util.List;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.milihua.springprogram.entity.Course;
import com.milihua.springprogram.jdbc.CourseJDBCCallProcedure;
 
public class proceduretest {
 
public static void main(String[] args) {
    // TODO Auto-generated method stub
    ApplicationContext context = new ClassPathXmlApplicationContext("config/procedure.xml");
    CourseJDBCCallProcedure courseJDBCCall =
            (CourseJDBCCallProcedure) context.getBean("courseJDBCCallProcedure");
    List<Course> courses = courseJDBCCall.listCourse();
    for (Course record : courses) {
        System.out.print("课程名称 : "
    + courseJDBCCall.getCoureName(record.getNumber()));
    }
}
}

课程小结

(1)SQL存储过程是将一些频繁调用的SQL语句按照一定规则编写,并存储到服务器端的数据库管理系统中,外部应用程序可以直接调用存储过程并接收存储过程返回的结果集。

(2)Spring框架提供了JDBC封装类SimpleJdbcCall,用于开发者便捷调用SQL存储过程或存储函数,SimpleJdbcCall类execute方法负责调用存储过程,该方法需要传入SqlParameterSource类型的参数。SqlParameterSource管理存储过程传入的参数,使用其addValue方法将参数添加到SqlParameterSource,execute方法以Map方式返回存储过程的执行结果。


代码在线纠错(通义千问 qwen-max)

支持粘贴多个代码文件,提交后由阿里云通义千问自动分析代码漏洞、语法错误、逻辑问题并给出修改建议。
您已解锁 AI 代码纠错功能,可正常使用!

评论区

登录 后发表评论
暂无评论