MySQL开启RewriteBatchedStatements后PreparedStatement的一个异常
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了MySQL开启RewriteBatchedStatements后PreparedStatement的一个异常,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含5013字,纯文字阅读大概需要8分钟。
内容图文
![MySQL开启RewriteBatchedStatements后PreparedStatement的一个异常](/upload/InfoBanner/zyjiaocheng/456/617aa833e6c84d858d8637c0b282154d.jpg)
MySQL 开启 RewriteBatchedStatements 属性后,PreparedStatement在解析一种Insert形式的SQL时发生异常,测试代码如下,使用的MySQL驱动为mysql-connector-java-5.1.36-bin.jar:
import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; public class Demo { public static final String DBDRIVER = "com.mysql.jdbc.Driver"; public static final String DBURL = "jdbc:mysql://127.0.0.1:3306/S10?rewriteBatchedStatements=true"; public static final String DBUSER = "root"; public static final String DBPASS = "123456"; public static void main(String[] args) { try { Class.forName(DBDRIVER); try (Connection conn = DriverManager.getConnection(DBURL, DBUSER, DBPASS); PreparedStatement pstmt = conn.prepareStatement( "INSERT INTO _1033 SET F01 = ?, F02 =? ON DUPLICATE KEY UPDATE F02 = VALUES(F02)")) { pstmt.setLong(1, 1); pstmt.setString(2, "2"); pstmt.executeUpdate(); } catch (Exception e) { e.printStackTrace(); } } catch (ClassNotFoundException e) { e.printStackTrace(); } } }
异常信息为
java.sql.SQLException: java.lang.StringIndexOutOfBoundsException: String index out of range: -36 at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:998) at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:937) at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:926) at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:872) at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:904) at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:894) at com.mysql.jdbc.Util.handleNewInstance(Util.java:418) at com.mysql.jdbc.PreparedStatement.getInstance(PreparedStatement.java:762) at com.mysql.jdbc.ConnectionImpl.clientPrepareStatement(ConnectionImpl.java:1455) at com.mysql.jdbc.ConnectionImpl.prepareStatement(ConnectionImpl.java:4205) at com.mysql.jdbc.ConnectionImpl.prepareStatement(ConnectionImpl.java:4109) at org.querydemo.QueryDemo.main(QueryDemo.java:22) Caused by: java.lang.StringIndexOutOfBoundsException: String index out of range: -36 at java.lang.String.substring(String.java:1911) at com.mysql.jdbc.PreparedStatement$ParseInfo.extractValuesClause(PreparedStatement.java:442) at com.mysql.jdbc.PreparedStatement$ParseInfo.buildRewriteBatchedParams(PreparedStatement.java:371) at com.mysql.jdbc.PreparedStatement$ParseInfo.<init>(PreparedStatement.java:358) at com.mysql.jdbc.PreparedStatement$ParseInfo.<init>(PreparedStatement.java:175) at com.mysql.jdbc.PreparedStatement.<init>(PreparedStatement.java:836) at com.mysql.jdbc.JDBC4PreparedStatement.<init>(JDBC4PreparedStatement.java:45) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:526) at com.mysql.jdbc.Util.handleNewInstance(Util.java:400) ... 5 more
跟踪代码,发现MySQL的驱动程序在开启 RewriteBatchedStatements 属性后,会对满足如下条件的SQL进行重写
protected static boolean canRewrite(String sql, boolean isOnDuplicateKeyUpdate, int locationOfOnDuplicateKeyUpdate, int statementStartPos) { boolean rewritableOdku = true; if (isOnDuplicateKeyUpdate) { int updateClausePos = StringUtils.indexOfIgnoreCase(locationOfOnDuplicateKeyUpdate, sql, " UPDATE "); if (updateClausePos != -1) { rewritableOdku = StringUtils.indexOfIgnoreCase(updateClausePos, sql, "LAST_INSERT_ID", "\"‘`", "\"‘`", StringUtils.SEARCH_MODE__MRK_COM_WS) == -1; } } return (StringUtils.startsWithIgnoreCaseAndWs(sql, "INSERT", statementStartPos)) && (StringUtils.indexOfIgnoreCase(statementStartPos, sql, "SELECT", "\"‘`", "\"‘`", StringUtils.SEARCH_MODE__MRK_COM_WS) == -1) && (rewritableOdku); }
重写的方法可以参考com.mysql.jdbc.PreparedStatement类的下面两个方法
private void buildRewriteBatchedParams(String sql, MySQLConnection conn, DatabaseMetaData metadata, String encoding, SingleByteCharsetConverter converter) private String extractValuesClause(String sql, String quoteCharStr) throws SQLException
【问题解决】:
修正的措施是将
PreparedStatement pstmt = conn.prepareStatement("INSERT INTO _1033 SET F01 = ?, F02 =? ON DUPLICATE KEY UPDATE F02 = VALUES(F02)")
改为
PreparedStatement pstmt = conn.prepareStatement("INSERT INTO _1033 (F01, F02 ) VALUES (?, ?) ON DUPLICATE KEY UPDATE F02 = VALUES(F02)")
本文出自 “技术点滴” 博客,请务必保留此出处http://wangzhichao.blog.51cto.com/2643325/1687940
MySQL开启RewriteBatchedStatements后PreparedStatement的一个异常
标签:string index out of range: -36
本文系统来源:http://wangzhichao.blog.51cto.com/2643325/1687940
内容总结
以上是互联网集市为您收集整理的MySQL开启RewriteBatchedStatements后PreparedStatement的一个异常全部内容,希望文章能够帮你解决MySQL开启RewriteBatchedStatements后PreparedStatement的一个异常所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。