欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Java Spring动态生成Mysql存储过程详解

程序员文章站 2022-03-20 17:55:34
一、 背景  由于公司业务需要动态配置一些存储过程来生成数据,之前尝试过使用jpa来完成,或多或少都存在一些问题,最后使用了spring的jdbctemplate。二、 环境  1.此随笔内容基于sp...

一、 背景

  由于公司业务需要动态配置一些存储过程来生成数据,之前尝试过使用jpa来完成,或多或少都存在一些问题,最后使用了spring的jdbctemplate。

二、 环境

  1.此随笔内容基于spring boot项目

  2.数据库为mysql 5.7.9版本

  3.jdk 版本为1.8

三、 说明

  说明:为方便表示,下列存储过程在代码中的表示我称之为接口配置  

四、 内容

  1、定义接口和接口参数bean;

    1)接口配置bean:

@entity
@table(name="qt_interface")
public class qtinterface {
 @id
 private string id;
 private string name;
 private string content;
 private string info;
 private string status;
//此处省略get、set…
}

2)接口配置参数bean:

@entity
@table(name="qt_interface_parameter")
public class qtinterfaceparameter {
 @id
 private string id;
 @column(name="inter_id")
 private string interid;
 private string name; //参数名称
 private string explain_info; //参数描述
 private string type;// 输入输出类型
 private string paratype; // 参数类型
 private integer paralen;
//此处省略get、set…
}

2、编写页面输入接口配置的信息;

1)html部分代码:

<div class="form-group">
  <label for="name" class="col-sm-2 control-label">接口名称<a style="color:red;">*</a>:</label>
  <div class="col-sm-4">
    <input type="text" id="name" name="name" class="form-control"/>
  </div>
  <label for="status" class="col-sm-2 control-label">接口状态<a style="color:red;">*</a>:</label>
  <div class="col-sm-4" >
    <select id="status" disabled="disabled" class="form-control">
      <option value="0">保存</option>
      <option value="1">已创建</option>
    </select>
 
  </div>
</div>
<div class="form-group">
  <label for="content" class="col-sm-2 control-label">接口内容<a style="color:red;">*</a>:</label>
  <div class="col-sm-10">
    <textarea id="content" name="content" rows="5" class="form-control"></textarea>
  </div>
</div>
<div class="form-group">
  <label for="explain_info" class="col-sm-2 control-label">接口说明:</label>
  <div class="col-sm-10">
    <textarea id="explain_info" name="explain_info" rows="3" class="form-control"></textarea>
  </div>
</div>
<div class="form-group">
  <label for="qtinterlist" class="col-sm-2 control-label">接口参数:</label>
  <div class="col-sm-10">
    <div class="ibox-content" style="width:100%;">
      <table id="qtinterlist" class="easyui-datagrid">
      </table>
    </div>
  </div>
</div>

2)js部分代码太长,就只贴一个提交方法吧

function createproduce(inter_id) {
 var postdata = {
    id: $("#inter_id").val(),
    item_id: $("#item_id").val(),
    name: $("#name").val(),
    content: $("#content").val(),
    explain_info: $("#explain_info").val(),
    jsondata: json.stringify(jsondata)// 参数明细信息,字段就是接口配置参数bean 中的字段信息
};
 
  $.ajax({
    url: url + 'test/createpro',
    type: 'get', //get
    async: false,  //或false,是否异步
    data: json.stringify(postdata),
    timeout: 5000,  //超时时间
    datatype: 'json',  //返回的数据格式:    success:   function (result, textstatus, jqxhr) {
      if (result.result == "1") { // 编辑赋值
        layer.alert("创建成功", {icon: 0});
      } else {
        layer.alert("创建失败,请检查sql语句,注意结尾不能有分号!具体错误信息:"+result.msg, {icon: 5});
      }
    },
    error: function (xhr, textstatus) {
      layer.alert(textstatus);
    }
  });
}

3、将数据上传到后台之后,后台生成存储过程。当然一般情况下,我们还是先把数据接口和接口明细数据持久化保存,再来执行创建操作,可以保证数据不会丢失。此处由于篇幅问题,我就省略了中间这一步。

1)创建一个service 的接口:

public interface testservice {
    resultinfo createpro(map<string,object> map);
}

2)然后创建接口的实现类:

@service
public class testserviceimpl implements testservice {
 
/**
 * 创建存储过程
 *
 * @param map 接口配置和接口参数信息
 * 参数详解: type 输入输出参数,取值为 in,out
 *       paratype 参数类型。取值为:1:int 2:double 3:varchar 4:datetime
 * @return
 */
@override
@transactional
public void createpro(map<string,object> map) {
  resultinfo resultinfo = new resultinfo();
  qtinterface qtinterface=new qtinterface();
  qtinterface =buildinterface(map, qtinterface);// 加载接口配置信息
  list<qtinterfaceparameter> paralist = new arraylist<qtinterfaceparameter>();
  paralist = buildparam(map.get("jsondata"));// 加载接口配置信息
  stringbuffer bf = new stringbuffer(); // 建立生成过程的语句
  bf.append("create procedure \t");
  bf.append(qtinterface.getname());
  bf.append("\n");
  bf.append("(");
  string para_type = "";
  int i = 1;
  for (qtinterfaceparameter qt : paralist) {
    switch (qt.getparatype()) { // 参数类型
      case "1":
        para_type = "int";
        break;
      case "2":
        para_type = "double";
        break;
      case "3":
        para_type = "varchar(" + qt.getparalen() + ")";
        break;
      case "4":
        para_type = "datetime";
        break;
      default:
        para_type = "varchar(255)";
        break;
    }
    if (i == paralist.size()) {
      bf.append("" + qt.gettype() + " " + qt.getname() + " " + para_type + ") ");
    } else {
      bf.append("" + qt.gettype() + " " + qt.getname() + " " + para_type + ", ");
    }
 
    i++;
  }
  bf.append(" comment '"+ qtmonitorwarninterface.getinfo() +"'\n"); // 添加描述信息
  bf.append("begin\n");
  bf.append(qtinterface.getcontent()); // 存储过程内容
  bf.append(";\nend;");
  // 先执行删除操作
  jdbctemplate.execute("drop procedure if exists " + qtinterface.getname() + " ;");
  jdbctemplate.execute(bf.tostring());
 
}
 
/**
 * 初始化接口配置信息
 *
 */
private qtinterface buildinterface(map<string, object> map, qtinterface qtinterface) {
  // 接口配置名称
  if (map.get("name") != null && !"".equals(map.get("name "))) {
    qtinterface.setname((string) map.get("name "));
  }
  //此处省略其他项,其他项的取值方法跟上面的一样 …
  return qtinterface;
}
 
/**
 * 初始化接口配置参数明细
 *
 */
  private list<qtinterfaceparameter> buildparam(string postdata) {
    list<qtinterfaceparameter> list = new arraylist<qtinterfaceparameter>();
    if(postdata!=null &&!"".equals(postdata)){
      list<map<string, object>> listparam = (list<map<string, object>>) jsonmapper.fromjsonstring(postdata, arraylist.class);
      for (map<string, object> map : listparam) {
        qtinterfaceparameter para = new qtinterfaceparameter();
        // 接口配置参数名称
        if (map.get("name") != null && !"".equals(map.get("name "))) {
          para.setname((string) map.get("name "));
        }
        // 此处省略其他项,其他项的取值方法跟上面的一样 …
        list.add(para);
      }
    }
    return list;
  }

3) 添加控制器进行调用:

@controller
@requestmapping(value = "/test")
public class testcontroller {
@autowired
private testservice testservice;
 
@requestmapping(value = "/createpro", method = requestmethod.get)
public resultinfo createpro(@requestbody map<string, object> map
) {
  resultinfo resultinfo = new resultinfo();
  try {
    testservice.createpro(id);
  resultinfo.setresult(1);
    resultinfo.setmsg("创建过程成功");
 
  } catch (exception e) {
    resultinfo.setresult(-1);
    resultinfo.setmsg(e.getmessage());
  }
  return resultinfo;
 }
}

4)最后动态生成的sql就是这个样子:

create procedure `testbase`.`test`(in a_user_id varchar(100))
  comment '测试接口'
begin
select * from userinfo where user_id=a_user_id;
end

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。