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

作者:画笔灬 时间:2024-01-25 10:16:32 

一、 背景

由于公司业务需要动态配置一些存储过程来生成数据,之前尝试过使用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

来源:https://www.cnblogs.com/Aimee-AI/p/10849198.html

标签:Java,Spring,Mysql,存储
0
投稿

猜你喜欢

  • Python中搜索和替换文件中的文本的实现(四种)

    2022-04-23 01:03:39
  • python tornado微信开发入门代码

    2023-11-01 01:04:59
  • python3安装speech语音模块的方法

    2023-03-24 12:09:32
  • python 多线程中子线程和主线程相互通信方法

    2021-05-13 03:56:44
  • Python进阶之列表推导与生成器表达式详解

    2022-01-18 00:07:04
  • pandas数据清洗(缺失值和重复值的处理)

    2021-10-05 10:36:43
  • 浏览器根据什么来判定脚本失控?[译]

    2009-02-20 13:36:00
  • python数组循环处理方法

    2023-08-03 16:36:19
  • python pandas库的安装和创建

    2023-09-25 22:49:02
  • Go语言函数学习教程

    2024-02-22 14:17:41
  • 将Python文件打包成.EXE可执行文件的方法

    2023-05-26 20:25:50
  • PHP简单检测网址是否能够正常打开的方法

    2023-11-17 22:22:56
  • 使用Python Fast API发布API服务的过程详解

    2022-05-19 20:03:44
  • Python缓存方案优化程序性能提高数据访问速度

    2022-04-11 20:36:15
  • Python查询缺失值的4种方法总结

    2023-10-29 13:42:08
  • Pycharm学生免费专业版安装教程的方法步骤

    2022-01-11 14:39:30
  • Pytorch 如何加速Dataloader提升数据读取速度

    2023-11-12 00:00:32
  • Windows下Anaconda2安装NLTK教程

    2022-08-11 04:30:49
  • PHP递归调用数组值并用其执行指定函数的方法

    2023-09-05 15:35:04
  • Python中关键字global和nonlocal的区别详解

    2023-08-02 16:42:33
  • asp之家 网络编程 m.aspxhome.com