spring boot JAP调用mysql存储过程

    因为要对接项目的mysql数据库,部分语句要使用到mysql的存储过程,保证调用的一致性。

    在网上查找了好多种方式,都很复杂,而且我试验了好多种,都没有成功。最后使用了

EntityManager的createNamedStoredProcedureQuery调用,成功执行mysql的存储过程。

      现将方式记录,以便后面查阅。

1.mysql的存储过程很复杂,主要是用户注册,需要向两个表中插入数据

CREATE DEFINER=`demodb`@`%` PROCEDURE `user_register`(
            in_password VARCHAR(50),
            in_device_os VARCHAR(20),
            in_device_os_version VARCHAR(30),
            in_device_support_tele INT,
            in_device_manufactory VARCHAR(40),
            in_device_model VARCHAR(30),
            in_app_mobile_version VARCHAR(20),
            in_gmail VARCHAR(30),
            in_verified TINYINT,
            in_cc VARCHAR(20),
            in_account VARCHAR(128),
            in_mn VARCHAR(20),
            OUT ret_passwd VARCHAR(50),
            OUT ret_userid VARCHAR(30),
            OUT ret_flag INT)
BEGIN
DECLARE var_get_userid VARCHAR(30);
DECLARE start_pos INT;
DECLARE var_mn VARCHAR(30);
DECLARE EXIT HANDLER FOR SQLEXCEPTION 
BEGIN
SET ret_flag=-1;
ROLLBACK;
END;
START TRANSACTION;     
SET @dt = NOW();
SET @dtunix=UNIX_TIMESTAMP(@dt);
SET @sid = REPLACE(UUID(),'-','');
SET start_pos=CEIL(RAND()*1000);
SELECT id INTO var_get_userid
FROM useridtable
LIMIT start_pos,1;
DELETE FROM useridtable 
WHERE id=var_get_userid;
IF in_mn='' THEN
   SET var_mn=CONCAT('+',in_cc,var_get_userid);
ELSE
   SET var_mn = in_mn;
END IF;
IF ROW_COUNT()=1 THEN
INSERT INTO friends(
        NAME,
        username, 
        secret,
        context,
        accountcode)
VALUES( var_get_userid,
        NULL,
        in_password,
        'ppcall-intercom',
        var_get_userid);
INSERT INTO UserTable(NAME,
        reg_date,
        truemail,
        truemobile,
        true_mobile_country_code,
        device_os,
        device_os_version,
        device_support_tele,
        device_manufactory,
        device_model,
        app_mobile_version,
        register_time,
        verified,
        capability,
        account ) 
VALUES( var_get_userid,
        @dt,
        in_gmail,
        var_mn,
        in_cc,
        in_device_os,
        in_device_os_version ,
        in_device_support_tele ,
        in_device_manufactory ,
        in_device_model,
        in_app_mobile_version ,
        @dt,
        in_verified,
        in_account);
           
SET ret_passwd=in_password;
SET ret_userid=var_get_userid;
SET ret_flag=1;        
ELSE
SET ret_flag=-2;        
END IF;
COMMIT;
END

2.代码调用首先要声明一个Entity,注明存储过程的名称和对应的输入参数和输出参数

代码如下:

package com.example.demo.entity;

import org.springframework.boot.autoconfigure.domain.EntityScan;

import javax.persistence.*;
import java.io.Serializable;

@Entity
@NamedStoredProcedureQuery(
    name = "user_register", //存储过程名称,可以自己命名,但一般和mysql的存储过程保持一致
    procedureName = "user_register", //mysql中定义的存储过程名称,这个必须和mysql数据库中的保持一致
    //声明存储过程的输入和输出参数,ParameterMode.IN 对应输入参数,ParameterMode.OUT 对应输出参数
    // name必须和mysql存储过程语句的输入参数保持一样,名字不能错误,type为参数的对应的类型
    parameters = {
        @StoredProcedureParameter(mode = ParameterMode.IN, name = "in_password", type = String.class),
        @StoredProcedureParameter(mode = ParameterMode.IN, name = "in_device_os", type = String.class),
        @StoredProcedureParameter(mode = ParameterMode.IN, name = "in_device_os_version", type = String.class),
        @StoredProcedureParameter(mode = ParameterMode.IN, name = "in_device_support_tele", type = Integer.class),
        @StoredProcedureParameter(mode = ParameterMode.IN, name = "in_device_manufactory", type = String.class),
        @StoredProcedureParameter(mode = ParameterMode.IN, name = "in_device_model", type = String.class),
        @StoredProcedureParameter(mode = ParameterMode.IN, name = "in_app_mobile_version", type = String.class),
        @StoredProcedureParameter(mode = ParameterMode.IN, name = "in_gmail", type = String.class),
        @StoredProcedureParameter(mode = ParameterMode.IN, name = "in_verified", type = Integer.class),
        @StoredProcedureParameter(mode = ParameterMode.IN, name = "in_cc", type = String.class),
        @StoredProcedureParameter(mode = ParameterMode.IN, name = "in_account", type = String.class),
        @StoredProcedureParameter(mode = ParameterMode.IN, name = "in_mn", type = String.class),
        @StoredProcedureParameter(mode = ParameterMode.OUT, name = "ret_passwd", type = String.class),
        @StoredProcedureParameter(mode = ParameterMode.OUT, name = "ret_userid", type = String.class),
        @StoredProcedureParameter(mode = ParameterMode.OUT, name = "ret_flag", type = Integer.class)
     }
)
public class Regist {
     //必要要有这个id声明,否则执行会出错,无法是否这个id有用。
     @Id
     @GeneratedValue(strategy = GenerationType.IDENTITY)
     private Integer id;
}

注意:网上有些示例,有说要@Table的注解,用这种方式调用,其实不用的@Table注解。

           而且这Entity自己随便命名,只要声明的@NamedStoredProcedureQuery存储过程这mysql保持一致就行。另外创建的class Regist必须要有一个id,并且注解是@Id和@GeneratedValue(strategy = GenerationType.IDENTITY),否则执行会出错。

3.创建好Entity后,就可以调用语句了。


package com.example.demo;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.StoredProcedureQuery;

@RestController
public class demoController {
    @RequestMapping("/regist")
    public boolean regist(HttpServletRequest request, HttpServletResponse res) {
        Map params = Util.getRequestParams(request);
        String account = params.get("account");
        String password = params.get("password");
        //执行存储过程
        StoredProcedureQuery query = entityManager.createNamedStoredProcedureQuery("user_register");
        //设置存储过程输入参数值
        query.setParameter("in_password",pwd); 
        query.setParameter("in_device_os",""); 
        query.setParameter("in_device_os_version","");
        query.setParameter("in_device_support_tele",0);
        query.setParameter("in_device_manufactory","");
        query.setParameter("in_device_model","");
        query.setParameter("in_app_mobile_version","");
        query.setParameter("in_gmail","");
        query.setParameter("in_verified",4);
        query.setParameter("in_cc","");
        query.setParameter("in_account",account);
        query.setParameter("in_mn","");
        query.execute();
        //获取输出参数值
        String passwd =(String) query.getOutputParameterValue("ret_passwd");
        String userid =(String) query.getOutputParameterValue("ret_userid");
        int flag=(int) query.getOutputParameterValue("ret_flag");
    
        return true;
    }      
}

        

只要上面的步骤就可以执行mysql的存储过程,并获取多个返回值。

你可能感兴趣的:(Java)