Java Spring動態生成Mysql儲存過程詳解
阿新 • • 發佈:2020-06-05
一、 背景
由於公司業務需要動態配置一些儲存過程來生成資料,之前嘗試過使用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
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。