java.sql.SQLException: Userdoes not have access to metadata required to determine stored procedurepa

来源:互联网 发布:知势而后可以加兵的加 编辑:程序博客网 时间:2024/04/30 13:08


存储过程不能调用的解决方案:

出错的提示:

error:"Userdoes not have access to metadata required to determine stored procedureparameter types. If rights can not be granted, configure connection with"noAccessToProcedureBodies=true" to have driver generateparameters that represent INOUT strings irregardless of actual parametertypes."

 

 

 

引用:

最近使用root用户编写了几个存储过程,但是使用普通用户通过JDBC连接执行却报错:

java.lang.NullPointerException......

java.sql.SQLException: Userdoes not have access to metadata required to determine stored procedureparameter types. If rights can not be granted, configure connection with"noAccessToProcedureBodies=true" to have driver generate parametersthat represent INOUT strings irregardless of actual parameter types.

报哪个错要看你使用的Connector/J版本了。

这是因为JDBC调用存储过程时需要有showcreate procudure权限或是有表mysql.procselect权限。通过在JDBC连接属性中设置noAccessToProcedureBodies=true(默认false)解决或是授予普通用户相应的权限或者是按http://lists.mysql.com/commits/17817中的patch修改。

noAccessToProcedureBodies=true的影响:
1.
调用存储过程时,将没有类型检查,设为字符串类型,并且所有的参数设为in类型,但是在调用registerOutParameter时,不抛出异常。
2.
存储过程的查询结果无法使用getXXX(StringparameterName)的形式获取,只能通过getXXX(intparameterIndex)的方式获取。

使用在URL中添加noAccessToProcedureBodies=true的影响是正式的,就是因为我添加了这个句话,导致我数据库的访问出现了问题。。。而且我使用的getXXX(String parameterName)的方式。。。

 

最后的解决方案:

  1.以后建议大家不要使用mysql数据库的root用户来创建数据库表、存储过程等等。。。因为这样的话,你创建的存储过程就会有很多的权限,而在虚拟空间上面,只会分配给我们一些普通用户的权限,而不会有高级用户的权限。。。

来看原理吧:

查看本地mysql数据库的的Mysql数据库。。。

 

我们可以看到user表。。。其中user表是用户的基本表,上面有用户的密码和权限的信息:

所以你可以改变本地的权限或者联系虚拟空间的管理帮你修改权限(一般这个比较麻烦的)。。

解决办法:

1,INSERT INTO user
    VALUES('localhost','username',PASSWORD('xxxxxxx'),
   'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y',
   'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y',
   '','','','',0,0,0,0);

2,grant   select,insert,update,delete,execute   on   every.*   to   username   identified   by  "xxxxxxxx";  

 

 

第二种方式:

查看你到到处的mysqlsql文件的话,在存储过程上面。里面有root@localhost等等的权限。。。

查看存储过程:
方法一:
       select`name` from mysql.proc where db = 'your_db_name' and `type` = 'PROCEDURE'
方法二:
         showprocedure status;
1.修改mysql存储过程的definer
修改mysql.procdefiner字段
Sql
代码
update mysql.proc set definer='author@%'
update mysql.proc set security_type='INVOKER' where db='MC';
UPDATE `mysql`.`proc` SET `definer`='author%' WHERE `db`='test' AND`name`='proc_name' AND `type`='PROCEDURE';

UPDATE `mysql`.`proc` SET `definer`='xuzhijing@%' WHERE `db`='myDB'
AND `type`='PROCEDURE';

update mysql.proc set definer='root@%' wheredb='myDb';
UPDATE `mysql`.`proc` SET `definer`='root00@%' WHERE `db`='test'AND `name`='jjjj' AND `type`='PROCEDURE';

UPDATE `mysql`.`proc` SET `definer`='wtc_678869@%' WHERE`db`='myDB' AND `type`='PROCEDURE';

2.修改security_type

Sql代码
update mysql.proc set security_type='INVOKER' where db='myDB';


1MySQL存储过程是通过指定SQL SECURITY子句指定执行存储过程的实际用户;

2)如果SQL SECURITY子句指定为DEFINER,存储过程将使用存储过程的DEFINER执行存储过程,验证调用存储过程的用户是否具有存储过程的execute权限和DEFINER用户是否具有存储过程引用的相关对象的权限;

3)如果SQL SECURITY子句指定为INVOKER,那么MySQL将使用当前调用存储过程的用户执行此过程,并验证用户是否具有存储过程的execute权限和存储过程引用的相关对象的权限;

4)如果不显示的指定SQL SECURITY子句,MySQL默认将以DEFINER执行存储过程。

3.执行存储过程授权
Sql
代码
GRANT EXECUTE ON test.* TO 'xuzhijing'@'%'

GRANT CREATE ROUTINE,ALTERROUTINE, SELECT,CREATE, INSERT, UPDATE, DELETE, EXECUTE ON test.* TO'xuzhijing'@'%' IDENTIFIEDBY '111111'

GRANT EXECUTE ON test.* TO 'xuzhijing'@'%'

GRANT CREATE ROUTINE,ALTERROUTINE, SELECT,CREATE, INSERT, UPDATE, DELETE, EXECUTE ON test.* TO'xuzhijing'@'%' IDENTIFIEDBY '111111'

CREATE ROUTINE创建存储过程的权限
ALTER ROUTINE
修改存储过程的权限

4.删除用户

REVOKE all ON test.* FROM xuzhijing@'%'


DELETE FROM user WHERE User='user_name' and Host='host_name';

FLUSH PRIVILEGES;

 

 

在远处数据库上面使用建立存储过程,只要不要有红色的就可以了。。。。

Create Procedure

CREATE DEFINER=`ourwishing1`@`localhost` PROCEDURE `proc_judge_mywish`(in name varchar(20))
     SQL SECURITY INVOKER


原创粉丝点击