• mysql 存储过程用程序调的问题


    记一下,存储过程加了commit结果用mysql客户端执行不报错,用jdbcTemplate执行就执行了一步,因为加了commit后面的程序都不跑了。另外

    存储过程里面如果用java调的话select赋值也会中断存储过程

    #SELECT @v_bill_cycle:=bill_cycle_id FROM T_BILL_CYCLE WHERE DATE_FORMAT(from_time,'%Y%m') = v_year_month;
        
        set @v_bill_cycle = v_year_month;
    
        set @month_states = (SELECT month_state FROM T_PRODUCT_BILLSTATE_SPEC WHERE bill_state=v_bill_state AND product_spec_id = v_product_spec_id);
    

      要注意赋值的时候select加上括号

     

     最后决定还是用jdbc去调用

    public void callPBillAttrSync(String yearMonth) {
    		jdbcTemplate.execute("CALL P_BILL_SYNC_ALL_ATTR("+yearMonth+")");
    	}
    	public void callPBillSyncJDBC(String yearMonth) {
    		String sql="{CALL P_BILL_SYNC(?)}";
    		Connection con = DataSourceUtils.getConnection(dataSource);
    		try {
    			CallableStatement c=con.prepareCall(sql);
    			c.setString(1, yearMonth);
    			c.execute();
    		} catch (SQLException e) {
    			e.printStackTrace();
    		}  
    	}
    

      还是报错了,

    好吧,给存储过程加个返回值试下,

    public int callMethod(String sql,String yearMonth){
    		Connection con = DataSourceUtils.getConnection(dataSource);
    		//String flag="@flag";
    		try {
    			System.out.println(sql+","+yearMonth);
    			CallableStatement c=con.prepareCall(sql);
    			//if(!yearMonth.equals("0")){
    				System.out.println(yearMonth);
    				c.setString(1, yearMonth);
    				//c.setString(2, flag);
    				c.registerOutParameter(2,Types.VARCHAR);
    			//}
    			c.setQueryTimeout(5);
    			try{
    				c.execute();
    				String rec_cnt=c.getString(2);
    				System.out.println(rec_cnt);
    			}catch(SQLTimeoutException  e){
    				c.close();
    				con.close();
    				return 0;
    			}
    			c.close();
    			con.close();
    			return 0;
    		} catch (SQLException e) {
    			e.printStackTrace();
    			try {
    				con.close();
    			} catch (SQLException e1) {
    				e1.printStackTrace();
    			}
    			return 0;
    		}
    	}
    

      

     结果调用存储过程的时候报Parameter number 2 is not an OUT parameter ,

    查报错源码发现noAccessToProcedureBodies=false就抛异常了,为什么会抛出这个异常呢?

     好吧,百度了下,找到了这么一条有用的信息https://www.aliyun.com/jiaocheng/1117218.html

    解释:这是因为jdbc调用存储过程时需要有show create procudure权限或是有表mysql.proc的select的权限

    解决方法: 
    1.通过在jdbc连接属性中设置noAccessToProcedureBodies=true(默认是false)。但是加该参数会有影响 
    - 调用存储过程时,将没有类型检查,设为字符串类型,并且所有的参数设为in类型,但是在调用registerOutParameter时,不抛出异常 
    - 存储过程的查询结果无法使用getXXX(String parameterName)的形式获取,只能通过getXXX(int parameterIndex)的方式获取

    想想我们的数据库经过了mycat代理,就选择直连的方式,不用mycat代理(因为直连是用的root账号,这个要改下,并且存储过程也要设置为该用户的所有者)

    好的,终于不报错了。坑爹啊,,,,,

    存储过程如下:

    BEGIN
        DECLARE v_first_time DATETIME;
        DECLARE v_start_time DATETIME;  
        SELECT @v_bill_cycle:=bill_cycle_id FROM T_BILL_CYCLE WHERE from_time=CONCAT(v_year_month,'01');
        SET @v_first_day = CONCAT(v_year_month,'01');
        SET v_first_time = NOW();
        SET v_start_time = NOW();
        
        #初始化清空表
        SET @v_sql=CONCAT('TRUNCATE TABLE T_BILL_INFO');
        PREPARE sqltext FROM @v_sql;
        EXECUTE sqltext; 
        #日志
        INSERT INTO T_BILL_LOG(bill_cycle,procs_name,sub_procs_name,flow_path,start_time,end_time,use_time,state) 
        VALUES (v_year_month,'P_BILL_SYNC','P_BILL_SYNC','初始化表',v_start_time,NOW(),UNIX_TIMESTAMP(NOW())-UNIX_TIMESTAMP(v_start_time),0);
        #COMMIT;
        #日志
        INSERT INTO T_BILL_LOG(bill_cycle,procs_name,sub_procs_name,flow_path,start_time,end_time,use_time,state) 
        VALUES (v_year_month,'P_BILL_SYNC','P_BILL_SYNC','初始化表2',v_start_time,NOW(),UNIX_TIMESTAMP(NOW())-UNIX_TIMESTAMP(v_start_time),0);
        #COMMIT;
        
        #同步固网用户
        SET v_start_time = NOW();
        CALL P_BILL_INFO_SYNC(v_year_month);
        #日志
        INSERT INTO T_BILL_LOG(bill_cycle,procs_name,sub_procs_name,flow_path,start_time,end_time,use_time,state) 
        VALUES (v_year_month,'P_BILL_SYNC','P_BILL_INFO_SYNC_ADB','同步业务数据',v_start_time,NOW(),UNIX_TIMESTAMP(NOW())-UNIX_TIMESTAMP(v_start_time),0);
        #COMMIT;
        
        SET v_start_time = NOW();
        ##################特殊处理######################
        #
        UPDATE T_BILL_INFO SET OFFERING_SPEC_ID = PRODUCT_SPEC_ID
        WHERE
        PRODUCT_SPEC_ID IN ('GD9900546','GD9900550','GD9900551','GD9900552','GD9900553','GD9900554',
        'GD9900131','GD9900414','GD9900418','GD9900477','GD9900073','GD2200001','GD9900068','GD9900007');
        
        UPDATE T_BILL_INFO
        SET OFFERING_SPEC_ID = 'GD9999000'
        WHERE product_spec_id = 'GD9900517';
        UPDATE T_BILL_INFO
        SET OFFERING_SPEC_ID = 'GD9900100'
        WHERE product_spec_id IN ('GD9900562','GD9900572','GD9900358','GD9900511');
        ##################特殊处理######################
        
        INSERT INTO T_BILL_LOG(bill_cycle,procs_name,sub_procs_name,flow_path,start_time,end_time,use_time,state) 
        VALUES (v_year_month,'P_BILL_SYNC','P_BILL_SYNC','业务特殊处理',v_start_time,NOW(),UNIX_TIMESTAMP(NOW())-UNIX_TIMESTAMP(v_start_time),0);
        #COMMIT;
        
        #同步固网用户属性
        /****/
        SET v_start_time = NOW();
        CALL P_BILL_SYNC_ALL_ATTR(v_year_month);
        #日志
        INSERT INTO T_BILL_LOG(bill_cycle,procs_name,sub_procs_name,flow_path,start_time,end_time,use_time,state) 
        VALUES (v_year_month,'P_BILL_SYNC_ALL_ATTR','P_BILL_SYNC_ALL_ATTR','业务同步属性结束',v_start_time,NOW(),UNIX_TIMESTAMP(NOW())-UNIX_TIMESTAMP(v_first_time),0);
        #COMMIT;
        INSERT INTO T_BILL_LOG(bill_cycle,procs_name,sub_procs_name,flow_path,start_time,end_time,use_time,state) 
        VALUES (v_year_month,'P_BILL_SYNC','P_BILL_SYNC','同步业务数据完毕',v_first_time,NOW(),UNIX_TIMESTAMP(NOW())-UNIX_TIMESTAMP(v_first_time),0);
        #COMMIT;
        END
    

      

  • 相关阅读:
    连通块问题
    线性数据结构
    NOIP2018总结
    原码反码补码详解
    一些常用的算法技巧总结
    骗分导论
    模板
    模板
    AcWing
    AcWing
  • 原文地址:https://www.cnblogs.com/JAYIT/p/10272645.html
Copyright © 2020-2023  润新知