chad
2009年4月16日
项目当中要在mysql数据库当中用blob字段保存图片,操作数据库用的是hibernate,但是一保存就报exception:
com.mysql.jdbc.exceptions.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?7??7???_0_¨´???m__ *]????//_?zaN??¨¤?—>???¡ì_?¨º???¨²?‰?_{??[^?¨¨?????v??{¨¬?/_¨¹?y?N|?' at line 1
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:936)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2988)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1631)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:1723)
at com.mysql.jdbc.Connection.execSQL(Connection.java:3283)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1332)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1604)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1519)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1504)
而用jdbc直接连的时候,却没有出错。这时我犯了一个错,还以为是hibernate的问题,花了很多时间查看hiberante数据存储操作。最后却发现,原来是:在用hibernate时,url后面跟上了一个characterEncoding=GBK,JDBC直连时没有指定characterncoding。这就是发生错误的根源。后来再做测试,把characterEncoding设置成utf8时,没有错误。于是去查看原因。
我们都知道,GBK的汉字编码区是,由两个字节组成:
GBK/2:OXBOA1-F7FE, 收录 GB2312 汉字 6763 个,按原序排列;
GBK/3:OX8140-AOFE,收录 CJK 汉字 6080 个;
GBK/4:OXAA40-FEAO,收录 CJK 汉字和增补的汉字 8160 个。
而当我们在sql语句中有’<单引号>时需要用斜杠来做转义。而斜杠”/”的编码是0X5c,它落在了GBK编码第二节范围之内。让我们来想象一下这种情况:图片文件在一个字节,恰好是’<单引号> 这时,我们在去除特殊字符时,本来的0x27就变成了0x5c,0x27,这样子没有问题,但更进一步想一下,如果图片文件的上一个字节也落在了GBK的编码之内,比如说0X82, 这时整个字符串的编码如下:0X82, 0x5c,0x27。这时,由于前两个字节可以组成一个汉字。所以整个字符串变成了“俓'“而不是我们需要的”?/’”。这时去执行sql字符串就会发生错误。解决方法就是,以后如果用到了blob,那就用utf8的编码代码gbk.