1. 程式人生 > 程式設計 >Java Spring動態生成Mysql儲存過程詳解

Java Spring動態生成Mysql儲存過程詳解

一、 背景

  由於公司業務需要動態配置一些儲存過程來生成資料,之前嘗試過使用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

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。