为啥“prepareCall”会抛出 NumberFormatException?

Posted

技术标签:

【中文标题】为啥“prepareCall”会抛出 NumberFormatException?【英文标题】:Why does "prepareCall" throw a NumberFormatException?为什么“prepareCall”会抛出 NumberFormatException? 【发布时间】:2021-04-09 10:28:44 【问题描述】:

我正在用 Java 编写一个需要与数据库交互的软件(本地主机上的 mysql Workbench)。在我的 DAO 类中,我检索了一个全局数据库连接,如果它还没有打开,它将被打开。当我的程序调用“prepareCall”时,会抛出 NumberFormatException。这仅在某些(大多数)查询中发生,而在其他查询中不会发生,即使代码没有更改。

我还想指出,查询在工作台中执行良好。

DAO

public static User selectPersonalInfo(Integer id) throws SQLException 
        CallableStatement stmt = null;
        ResultSet res = null;
        User user = null;

        try 
            Connection conn = ConnectionManager.getConnection();
            stmt = conn.prepareCall(RoutinesIdentifier.GET_USER);
            res = RoutinesManager.bindParametersAndExec(stmt, id);
            
            if (res.first())               
                user = new User(res.getString("email"), res.getString("pwd"), res.getString("first_name"), res.getString("last_name"));
                user.setCity(res.getString("city"));
                user.setBirth(res.getDate("birth").toInstant().atZone(ZoneId.systemDefault()).toLocalDate());
            
            
            res.close();          
         catch (SQLException e) 
            throw new SQLException("An error occured while trying to retrieve personal information."); 
        catch(NumberFormatException ne) 
            ne.printStackTrace();
            System.exit(0);
         finally 
            if(stmt != null) 
                stmt.close();
            
        
        
        return user;
    

连接

public static Connection getConnection() throws SQLException
        
        if (conn == null) 
             conn = DriverManager.getConnection(url, user, pass);
        
        
        return conn;
    

例程标识符

public static final String GET_USER = "call wwj_db.retrieve_user(?);";

例程管理器

public static ResultSet bindParametersAndExec(CallableStatement stmt, int ... params) throws SQLException 
        for (int i = 0; i < params.length; i++) 
            stmt.setInt(i+1, params[i]);
        
                
        return executeStmt(stmt);
    

    public static ResultSet executeStmt(CallableStatement stmt) throws SQLException 
        if(stmt.execute()) 
            return stmt.getResultSet();
        else 
            return null;
           
    

MySQL

CREATE PROCEDURE `retrieve_user` (in var_id int)
BEGIN
    SELECT `user`.email, `user`.pwd, `user`.first_name, `user`.last_name, `user`.city, `user`.birth
    FROM `account` join `user` on `account`.user = `user`.email
    WHERE `account`.id = var_id;
END

堆栈跟踪

java.lang.NumberFormatException: Invalid integer format for value 'PRIMARY'
    at com.mysql.cj.protocol.a.MysqlTextValueDecoder.getLong(MysqlTextValueDecoder.java:223)
    at com.mysql.cj.protocol.a.MysqlTextValueDecoder.getInt(MysqlTextValueDecoder.java:152)
    at com.mysql.cj.protocol.a.MysqlTextValueDecoder.decodeInt2(MysqlTextValueDecoder.java:97)
    at com.mysql.cj.protocol.result.AbstractResultsetRow.decodeAndCreateReturnValue(AbstractResultsetRow.java:153)
    at com.mysql.cj.protocol.result.AbstractResultsetRow.getValueFromBytes(AbstractResultsetRow.java:241)
    at com.mysql.cj.protocol.a.result.ByteArrayRow.getValue(ByteArrayRow.java:91)
    at com.mysql.cj.jdbc.result.ResultSetImpl.getObject(ResultSetImpl.java:1296)
    at com.mysql.cj.jdbc.result.ResultSetImpl.getInt(ResultSetImpl.java:797)
    at com.mysql.cj.jdbc.CallableStatement$CallableStatementParamInfo.addParametersFromDBMD(CallableStatement.java:254)
    at com.mysql.cj.jdbc.CallableStatement$CallableStatementParamInfo.<init>(CallableStatement.java:206)
    at com.mysql.cj.jdbc.CallableStatement.convertGetProcedureColumnsToInternalDescriptors(CallableStatement.java:831)
    at com.mysql.cj.jdbc.CallableStatement.determineParameterTypes(CallableStatement.java:805)
    at com.mysql.cj.jdbc.CallableStatement.<init>(CallableStatement.java:586)
    at com.mysql.cj.jdbc.CallableStatement.getInstance(CallableStatement.java:485)
    at com.mysql.cj.jdbc.ConnectionImpl.parseCallableStatement(ConnectionImpl.java:1516)
    at com.mysql.cj.jdbc.ConnectionImpl.prepareCall(ConnectionImpl.java:1541)
    at com.mysql.cj.jdbc.ConnectionImpl.prepareCall(ConnectionImpl.java:1532)
    at logic.persistence.dao.UserDAO.selectPersonalInfo(UserDAO.java:27)
    at logic.domain.User.getPersonalInfoFromDB(User.java:85)
    at logic.application.control.AccountControl.retrievePersonalInfo(AccountControl.java:72)
    at logic.bean.UserBean.getPersonalInfo(UserBean.java:103)
    at logic.presentation.control.PersonalInfoGraphic.initialize(PersonalInfoGraphic.java:78)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2548)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2441)
    at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2409)
    at logic.presentation.GraphicHandler.switchScreen(GraphicHandler.java:106)
    at logic.presentation.GraphicHandler.openSection(GraphicHandler.java:119)
    at logic.presentation.control.AccountGraphic.openPersonalInfo(AccountGraphic.java:104)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:71)
    at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:275)
    at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1771)
    at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1657)
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
    at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
    at javafx.event.Event.fireEvent(Event.java:198)
    at javafx.scene.Node.fireEvent(Node.java:8411)
    at javafx.scene.control.Button.fire(Button.java:185)
    at com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:182)
    at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:96)
    at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:89)
    at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
    at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
    at javafx.event.Event.fireEvent(Event.java:198)
    at javafx.scene.Scene$MouseHandler.process(Scene.java:3757)
    at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485)
    at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
    at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:394)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:295)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$2(GlassViewEventHandler.java:432)
    at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:410)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:431)
    at com.sun.glass.ui.View.handleMouseEvent(View.java:555)
    at com.sun.glass.ui.View.notifyMouse(View.java:937)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.lambda$null$4(WinApplication.java:187)
    at java.lang.Thread.run(Thread.java:748)

【问题讨论】:

帮助我们帮助您 - 分享此类失败呼叫的代码 您使用的是哪个版本的 MySQL Connector/J 和 MySQL 服务器?乍一看,这似乎是驱动程序中的错误(或者可能是服务器中的错误)。 @MarkRotteveel 我使用的是 8.0.22 版 【参考方案1】:

看起来数据库中的“PRIMARY”数据类型不是 INT 格式。因此,无论数据库中有什么,请在 Java 代码中使用相应的数据类型。

【讨论】:

没那么简单,问题在于 MySQL Connector/J 内部试图读取数据库元数据以准备调用。 @MarkRotteveel 就是这样!太感谢了。我更改了服务器和连接器版本,一切正常。

以上是关于为啥“prepareCall”会抛出 NumberFormatException?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 FileOutputStream 会抛出 FileNotFoundException?

为啥 BluetoothSetLocalServiceInfo 会抛出错误 1314?

为啥geoip会抛出异常?

为啥这个 OdbcConnection 会抛出 System.InvalidOperationException?

为啥 jsonwebtoken 会抛出“无效签名”错误?

为啥 canvas.toDataURL() 会抛出安全异常?