mysql之存储过程

相信几乎所有的程序猿们都知道数据库,也都知道数据库中有存储过程、函数等等其他的一些基本的知识,今天这里就主要讲一讲存储过程。

说到存储过程,相信很多一部分人都知道存储过程该怎么使用,但是如果真的被问到那么什么是存储过程呢?

楼主今天就碰到这一类问题,一个公司的小白拿来了一些题目过来问题,其中一个问题就是:什么是存储过程?怎么创建?用什么来调用?

当时就我就有点懵了,因为平时都是直接去调用就可以了,但是要真的讲原理,一时间也就真回答不上来,然后我果断的来了一句,这个嘛,你等下啊,我这里还有点事情没做完,等下跟你讲  -.-!!!

等他走开,就偷偷的开始百度。。。╭(╯^╰)╮,然后再结合实际应用,去告诉了他,强行装B,果然是最为致命,不过通过这一问题,也发现我自身存在的很多问题,下面就来介绍介绍存储过程。

 

学习三部曲:什么是...?为什么用...?怎么用...?

1、什么存储过程?

  答:存储过程就是一组为完成特定功能的sql语句集,在数据库中编辑且储存在数据库中,经过首次编译后,就不需要再进行编辑,用户在需要用到时直接指定存储过程的名称来执行即可。

 

2、为什么要用存储过程?

  a)方便维护:例如我们开发一个系统分别有不同的客户端(PC端、手机端),这个时候如果我们要去对一个表进行查询,使用普通sql那么我们就需要写两次sql语句,同时如果在开发过程中对数据库表进行了修改,那么相对应的查询语句也就可能受到影响需要修改,查询数据非常多的话就不利于维护,步骤太过繁琐,但是如果采用存储过程,那么我们仅仅只需要在数据库中修改存储过程中的代码即可。其它的地方都不需要变动,这也正好符合了我们面向对象的思想,利用存储过程将sql语句进行封装,然后外部只需要调用即可。

  b)提高安全性:使用普通的sql语句来操作数据库会存在sql注入的危险,但是如果采用存储过程就可以帮我们解决这一问题,让sql语句与客户端测底的分离。

  c)执行速度快:普通的sql语句都是需要经过编辑然后再执行,但是存储过程在创建后就已经编辑过了,只需要编译一次,后续只要调用就可以运行。

  d)代码的复用,使用简单:使用存储过程非常简单,只需要调用就足够了。

 

3、怎么用存储过程?

  这里我采用几个案例来演示存储过程的无参和有参,体验一下存储过程的强大之处,采用mybatis来完成与数据库的交互。

  存储过程脚本在 3.8

  3.1 准备工作:

    * 准备一张用户表,并向表中添加一些数据,方便后续的查询操作。

    

  3.2 创建mapper代理接口

package com.lxd.mysql.procedure;

import java.util.List;

import org.apache.ibatis.annotations.Param;

/**
 * 使用mybatis来调用procedure存储过程
 * @ClassName:MyBatisProcedureDemo
 * @author lxd
 * @date 2018年11月1日
 * @version
 */
public interface MyBatisProcedureDemo {
    /**
     * 查询所有
     * @Title: findAllUser
     * @return List<User>
     */
    List<User> findAllUser();
    
    /**
     * 根据分页查询
     * @Title: getList
     * @param page 当前页
     * @param total 每页数据数
     * @return List<User>
     */
    List<User> getList(@Param("page")Integer page, @Param("total")Integer total);
}

 

  3.3 编写mapper映射文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
    PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.lxd.mysql.procedure.MyBatisProcedureDemo">
    <resultMap type="User" id="user_mapping">
        <id property="id" column="id"/>
        <result property="username" column="username"/>
        <result property="userpass" column="userpass"/>
    </resultMap>
    
    <select id="findAllUser" resultMap="user_mapping">
        CALL findAll_user()
    </select>
    
    <select id="getList" resultMap="user_mapping">
        call findAll_limit(#{page},#{total});
    </select>
</mapper>

 

  3.4 编写jdbc配置文件

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///procedureDemo?characterEncoding=utf-8
jdbc.username=root
jdbc.password=123456

 

   3.4 编写mybatis核心配置文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
    PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!-- 属性文件
        先加载内部标签,再加载外部文件,属性名称一致时,会替换内容
     -->
    <properties resource="jdbc.properties"></properties>
    
    <!-- 定义别名 -->
    <typeAliases>
        <!-- 别名包扫描器:别名是类的全称,不区分大小写 -->
        <package name="com.lxd.mysql.procedure"/>
    </typeAliases>

    <!-- 和spring整合后 environments配置将废除 -->
    <environments default="development">    <!-- 选择运行环境 -->
        <environment id="development">
            <!-- 使用jdbc事务管理 -->
            <transactionManager type="JDBC" />
            <!-- 数据库连接池 -->
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}" />
                <property name="url" value="${jdbc.url}" />
                <property name="username" value="${jdbc.username}" />
                <property name="password" value="${jdbc.password}" />
            </dataSource>
        </environment>
    </environments>
    
    <!-- 加载映射文件 -->
    <mappers>
        <!-- 映射文件包扫描,推荐方式
            1:接口文件必须与映射文件同一目录下
            2:接口文件的名称必须与映射文件名称一致
         -->
        <package name="com.lxd.mysql.procedure"/>
    </mappers>
</configuration>

 

  3.5 引入mybatis和数据库的jar包

  

 

  3.6 编写工具类

package com.lxd.mysql.procedure;

import java.io.IOException;
import java.io.InputStream;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

/**
 * session工厂工具类
 * @ClassName:SqlSessionFactoryUtils
 * @author lxd
 * @date 2018年11月1日
 * @version
 */
public class SqlSessionFactoryUtils {
    private static SqlSessionFactory sqlSessionFactory;
    
    static{
        try {
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
            InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
            sqlSessionFactory = builder.build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    /**
     * 对外提供获取方法
     * @Title: getSqlSessionFactory
     * @return SqlSessionFactory
     */
    public static SqlSessionFactory getSqlSessionFactory(){
        return sqlSessionFactory;
    }
}

 

  

  3.7 编写测试类

package com.lxd.mysql.procedure;

import java.util.List;

import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

/**
 * 测试
 * @ClassName:MyBatisProcedureTest
 * @author lxd
 * @date 2018年11月1日
 * @version
 */
public class MyBatisProcedureTest {
    @Test
    public void testFindAllUser(){
        // 调用工具类获取session工厂,并打开session
        SqlSession session = SqlSessionFactoryUtils.getSqlSessionFactory().openSession(true);
        // 通过session获取到mapper代理接口
        MyBatisProcedureDemo demo = session.getMapper(MyBatisProcedureDemo.class);
        // 调用接口中的方法,得到结果
        List<User> users = demo.findAllUser();
        // 打印结果
        System.out.println(users);
    }
    
    @Test
    public void testGetList(){
        // 调用工具类获取session工厂,并打开session
        SqlSession session = SqlSessionFactoryUtils.getSqlSessionFactory().openSession(true);
        // 通过session获取到mapper代理接口
        MyBatisProcedureDemo demo = session.getMapper(MyBatisProcedureDemo.class);
        // 调用接口中的方法,得到结果
        List<User> users = demo.getList(2, 5);
        // 打印结果
        for (User user : users) {
            System.out.println(user);
        }
    }
}

 

  3.8 附上存储过程脚本

-- 创建一个普通的查询所有的存储过程
DELIMITER//
CREATE PROCEDURE findAll_user()
BEGIN
    SELECT * FROM users;
END //
DELIMITER ;


-- 创建带参的存储过程
DELIMITER //
CREATE PROCEDURE findAll_limit(page INT, total INT)
BEGIN
    DECLARE beginPage INT;
    DECLARE number INT;
    SET number = page;
    IF page = 0 THEN
        SET number = 1;
    END IF;
    SET beginPage = (number - 1) * total;
    SELECT * FROM users LIMIT beginPage,total;
END //
DELIMITER ;

 

   3.9 查询结果

  

 

 ----------------------------------------------------------------------------------  分隔线  -------------------------------------------------------------------------------------------

结尾:通过这一案例基本上可以大致的了解到存储过程的使用。本文主要就是大致的讲解下存储过程的概念及优点,和基本的使用。最主要就是帮我楼主记录所学知识,以便后续查阅,同时也是希望能够对那些存储过程存在疑问的给与一点薄弱的帮助。

  学无止境,每天学一点,每天也同样的进步一点,不要轻言放弃。滴水穿石,终究是需要时间来积累的。

 

posted @ 2018-11-01 15:16  奇点原生  阅读(1040)  评论(0编辑  收藏  举报