1. 程式人生 > >一個jdbc與儲存過程呼叫之間的資料對映問題

一個jdbc與儲存過程呼叫之間的資料對映問題

背景

一個功能,管理員直接新增使用者賬號,儲存過程如下【postgresql資料庫】:


-- 儲存過程 管理員直接新增會員賬號
CREATE OR REPLACE FUNCTION "sp_account_member_reg_by_admin"(
      para_name character varying(45),
      para_email character varying(255),
      para_mobile character(11),
      para_avatar character varying(400),
      para_longitude numeric(10,6),
      para_latitude numeric(10,6),
      para_region_id integer,
      para_address character varying(100),
      para_member_status smallint,
  out record_json varchar
)
  RETURNS  varchar
AS $BODY$

declare tmpId integer;
  declare tmpId_str varchar;
  declare opResult sys_type_operation_outline;
  declare logic_allow boolean;
  declare c_v_name character varying(45);
  declare c_v_email character varying(255);
  declare c_v_mobile character(11);
  declare c_v_avatar character varying(400);
  declare c_v_regist_time timestamp(6) without time zone;
  declare c_v_longitude numeric(10,6);
  declare c_v_latitude numeric(10,6);
  declare c_v_region_id integer;
  declare c_v_address character varying(100);
  declare c_v_member_status smallint;
  declare c_v_data_completed boolean;
  declare no_mobile boolean;
  declare no_email boolean;
begin
  opResult.state:=false;
  opResult."stateCode":=0;
  opResult.message:='';
  -- 正式的引數賦值
  c_v_name:=para_name;
  c_v_email:=para_email;
  c_v_mobile:=para_mobile;
  c_v_avatar:=para_avatar;
  c_v_regist_time:= now();

  c_v_longitude:=para_longitude;
  c_v_latitude:=para_latitude;
  c_v_region_id:=para_region_id;
  c_v_address:=para_address;
  c_v_member_status:=para_member_status;
  c_v_data_completed:=false;
  if para_avatar is not null and char_length(para_avatar)>0 then
    c_v_data_completed:=true;
  end if;

  no_mobile:=false;
  no_email:=false;

  if c_v_mobile is null or char_length(c_v_mobile) <1 then
    no_mobile:=true;
    else
      perform id from member where "mobile"=c_v_mobile limit 1;
      if found then
        opResult.message:=config('errors','mobile_exist','message');
        opResult."stateCode":=config('errors','mobile_exist','code');
        opResult."state":=false;
        select row_to_json(t) into record_json from ( select opResult.state,opResult."stateCode",opResult.message,'' as data  ) t;
        return;
      end if;
  end if;

  if c_v_email is null  or char_length (c_v_email) < 1 then
    no_email:=true;
    else
      perform id from member where "email"=c_v_email limit 1;
      if found then
        opResult.message:=config('errors','email_exist','message');
        opResult."stateCode":=config('errors','email_exist','code');
        opResult."state":=false;
        select row_to_json(t) into record_json from ( select opResult.state,opResult."stateCode",opResult.message  ) t;
        return;
      end if;
  end if ;

  if no_mobile=true and no_email=true then
    opResult.message:='手機號碼或者郵箱地址不能同時為空!';
    opResult."stateCode":=-1;
    opResult."state":=false;
    select row_to_json(t) into record_json from ( select opResult.state,opResult."stateCode",opResult.message  ) t;
    return;
  end if;


  INSERT INTO "member"(
      -- 主鍵不插入記錄。
      "name"
      ,  "email"
      ,  "mobile"
      ,  "avatar"
      ,  "regist_time"
      ,  "longitude"
      ,  "latitude"
      ,  "region_id"
      ,  "address"
      ,  "member_status"
      ,  "data_completed"
      )
  VALUES (
             c_v_name
             ,  c_v_email
             ,  c_v_mobile
             ,  c_v_avatar
             ,  c_v_regist_time
             ,  c_v_longitude
             ,  c_v_latitude
             ,  c_v_region_id
             ,  c_v_address
             ,  c_v_member_status
             ,  c_v_data_completed
             );
  if FOUND then
    opResult.message:='您已經成功建立了一個會員賬號';
    opResult."stateCode":=0;
    opResult."state":=true;
  else
    opResult.message:='會員賬號建立失敗!';
    opResult."stateCode":=-1;
    opResult."state":=false;
  end if;

  if opResult.state=true then
    select row_to_json(t) into record_json from ( select opResult.state,opResult."stateCode",opResult.message,currval(pg_get_serial_sequence('member', 'id')) as data  ) t;
  else
    select row_to_json(t) into record_json from ( select opResult.state,opResult."stateCode",opResult.message  ) t;
  end if;
  return;

end;
$BODY$ LANGUAGE plpgsql volatile;

請留意引數:

在這裡插入圖片描述

然後,jdbc下面的呼叫為:

    /***
     * 管理員直接添會員賬號
     ***/
    public OpResult RegByAdmin(MemberRegByAdmin model)
    {
        int totalParaCount=9+1 ;//--儲存過程引數總個數。
        String procName="sp_account_member_reg_by_admin";
        final HashMap<String,Integer> map_out_paras=new HashMap<>();
        int theParamIndex=0;
        OpResult opResult=new OpResult();
        StringBuilder paraStr=new StringBuilder();
        String callable_para_str="";
        for(int i=0;i<totalParaCount;i++){
            paraStr.append('?');
            paraStr.append(',');
        }
        if(totalParaCount>0){
            paraStr.append(',');
            callable_para_str=(paraStr.toString().replaceFirst(",,",""));
        }
        final String sql="{ call \""+procName+"\"("+callable_para_str+")}";

        CallableStatementCreator stCreator=new CallableStatementCreator() {
            @Override
            public CallableStatement createCallableStatement(Connection con) throws SQLException {
                CallableStatement st=con.prepareCall(sql);
                int paraIndex=0;






                paraIndex++; st.setString(paraIndex,model.name);
                paraIndex++; st.setString(paraIndex,model.email);
                paraIndex++; st.setString(paraIndex,model.mobile);
                paraIndex++; st.setString(paraIndex,model.avatar);
                paraIndex++; st.setDouble(paraIndex,model.longitude);
                paraIndex++; st.setDouble(paraIndex,model.latitude);
                paraIndex++; st.setInt(paraIndex,model.region_id);
                paraIndex++; st.setString(paraIndex,model.address);
                paraIndex++; st.setShort(paraIndex,model.member_status);
                paraIndex++;st.registerOutParameter(paraIndex, Types.VARCHAR);map_out_paras.put("op_result",paraIndex);
                return st;
            }
        };

        CallableStatementCallback<OpResult> stCallback=new CallableStatementCallback<OpResult>(){
            @Override
            public OpResult doInCallableStatement(CallableStatement cs) throws SQLException, DataAccessException {
                OpResult op_result=new OpResult();
                cs.execute();
                ResultSet rs=(ResultSet)cs.getResultSet();
                String json_op_result=cs.getString(map_out_paras.get("op_result"));
                op_result= JSONObject.parseObject(json_op_result,OpResult.class);
                if(rs!=null){
                    rs.close();
                }
                cs.getConnection().setAutoCommit(true);
                return op_result;
            }
        };
        opResult=jdbcTemplate.execute(stCreator,stCallback);
        return opResult;
    }

用到的模型為:

public class MemberRegByAdmin {

    public MemberRegByAdmin(){
        this.setNULL();
    }

    public   String  name="";
    public void setName(String name){
        this.name=name;
    }
    public String getName(){
        return this.name;
    }
    public   String  email="";
    public void setEmail(String email){
        this.email=email;
    }
    public String getEmail(){
        return this.email;
    }
    public   String  mobile="";
    public void setMobile(String mobile){
        this.mobile=mobile;
    }
    public String getMobile(){
        return this.mobile;
    }

    public   String  avatar="";
    public void setAvatar(String avatar){
        this.avatar=avatar;
    }
    public String getAvatar(){
        return this.avatar;
    }

    public   Double  longitude=0.0;
    public void setLongitude(Double longitude){
        this.longitude=longitude;
    }
    public Double getLongitude(){
        return this.longitude;
    }
    public   Double  latitude=0.0;
    public void setLatitude(Double latitude){
        this.latitude=latitude;
    }
    public Double getLatitude(){
        return this.latitude;
    }

    public   Integer  region_id=0;
    public void setRegion_id(Integer region_id){
        this.region_id=region_id;
    }
    public Integer getRegion_id(){
        return this.region_id;
    }
    public   String  address="";
    public void setAddress(String address){
        this.address=address;
    }
    public String getAddress(){
        return this.address;
    }
    public   Short  member_status=0;
    public void setMember_status(Short member_status){
        this.member_status=member_status;
    }
    public Short getMember_status(){
        return this.member_status;
    }

    public void setNULL(){
        this.name=null;
        this.email=null;
        this.mobile=null;
        this.avatar=null;
        this.longitude=null;
        this.latitude=null;
        this.region_id=null;
        this.address=null;
        this.member_status=null;
    }

    public void resetDefaultVal(){
        this.name="";
        this.email="";
        this.mobile="";
        this.avatar="";
        this.longitude=0.0;
        this.latitude=0.0;
        this.region_id=0;
        this.address="";
        this.member_status=0;
    }


}

測試程式碼為:

    @Test
    public void testMemberRegByAdmin(){
        MemberRegByAdmin model=new MemberRegByAdmin();
        model.resetDefaultVal();
        model.setName("dfdfdf");
        model.setMobile("");
        model.setEmail("");
        OpResult opResult=memberBiz.RegByAdmin(model);
        System.out.println(JSONObject.toJSONString(opResult));

    }

測試結果為:
在這裡插入圖片描述

Caused by: org.postgresql.util.PSQLException: ERROR: function
 sp_account_member_reg_by_admin(character varying, character varying, character varying, character varying, double precision, double precision, integer, character varying, smallint) does not exist
  建議:No function matches the given name and argument types. You might need to add explicit type casts.
  位置:15

注意到:
兩個座標的資料型別
在這裡插入圖片描述

與:
在這裡插入圖片描述

方法定義裡面的引數不一樣,所以,java中的double與numeric是不一樣的,
只有一種解決方案,就是直接指定引數型別:

在這裡插入圖片描述

然後你會發現:

在這裡插入圖片描述

done.