Java 尝试插入包含“”的值时出现MySQLSyntaxErrorException
我知道已经有无数关于mysqlsyntaxerrorexeption错误的条目,但我还没有读到任何解决我问题的帖子,我真的可以用额外的一双眼睛来指出我的错误 我正在创建一个简单的web scraper,将wikipedia页面上列出的啤酒厂名称存储到一个基本的MySQL表中,该表使用WAMP本地存储。我的现有代码似乎工作正常,直到我遇到一个啤酒厂名称,其中包括一个'的名称。这也是我第一次使用JSoup进行HTML解析 以下是我当前的代码:Java 尝试插入包含“”的值时出现MySQLSyntaxErrorException,java,mysql,jdbc,jsoup,Java,Mysql,Jdbc,Jsoup,我知道已经有无数关于mysqlsyntaxerrorexeption错误的条目,但我还没有读到任何解决我问题的帖子,我真的可以用额外的一双眼睛来指出我的错误 我正在创建一个简单的web scraper,将wikipedia页面上列出的啤酒厂名称存储到一个基本的MySQL表中,该表使用WAMP本地存储。我的现有代码似乎工作正常,直到我遇到一个啤酒厂名称,其中包括一个'的名称。这也是我第一次使用JSoup进行HTML解析 以下是我当前的代码: import java.io.IOException;
import java.io.IOException;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
public class Main {
public static DB db = new DB();
public static void main(String[] args) throws SQLException, IOException {
db.runSql2("TRUNCATE Brewery;");
processPage("myBrew");
System.out.println("done parsing");
}
// recursive method to find brewery names by adding db entry for all <li><a>
// values on site. Might not need recursion for this.
public static void processPage(String bName) throws SQLException,
IOException {
// check if the given URL is already in database
String sql = "select * from Brewery where name = '" + bName + "'";
ResultSet rs = db.runSql(sql);
if (rs.next()) {
// do nothing because already exists
} else {
// store the brewery to database to avoid parsing again
sql = "INSERT INTO `Crawler`.`Brewery` " + "(`name`) VALUES "
+ "(?);";
PreparedStatement stmt = db.conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
stmt.setString(1, bName);
//stmt.execute();
stmt.executeUpdate();
// get useful information
//research this further to better understand what it's doing
Document doc = Jsoup.connect("https://en.wikipedia.org/wiki/List_of_microbreweries").get();
//case-senstive
if (doc.text().contains("Brewery")) {
System.out.println(bName);
}
// get all links and recursively call the processPage method
Elements breweries = doc.select("a[href]");
for (Element link : breweries) {
//System.out.println("element class: " + link.nodeName());
//System.out.println("parent class: " + link.parent().nodeName());
System.out.println("element title: " + link.attr("title"));
//assumes that all brewery names will be listed in <li><a> html format
if (link.nodeName() == "a" && link.parent().nodeName() == "li") {
System.out.println("recursive call tripped");
String tmp = link.attr("title");
//String first = tmp.charAt(0) + "";
if(tmp.contains("'")){
String brew = tmp.replaceAll("'", "\\\'");
/*System.out.println("new string: '" + brew +"'");
processPage("'" + brew + "'");*/
System.out.println("new string: " + brew);
processPage(brew);
}
else {
if (tmp.contains(" (page does not exist)")) {
String brew = tmp.replaceAll(" (page does not exist)", "");
System.out.println("shortened string: " + brew);
processPage(brew);
}
else {
//no ' exists in the name
processPage(tmp);
}
}
}
}
}
}
}
使用此代码,包含“”的brewery名称不会存储在my MySQL表中。但是,如果我替换以下行
String brew = tmp.replaceAll("'", "\\\'");
与
然后啤酒厂名称确实被存储到我的MySQL表中,在刮取下一个啤酒厂名称之前,我得到以下错误:
Exception in thread "main" com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry 'Beau\'s All Natural Brewing Company' for key 'brewery_name'
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Unknown Source)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:404)
at com.mysql.jdbc.Util.getInstance(Util.java:387)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:932)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3878)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3814)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2478)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2625)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2551)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1861)
at com.mysql.jdbc.PreparedStatement.executeUpdateInternal(PreparedStatement.java:2073)
at com.mysql.jdbc.PreparedStatement.executeUpdateInternal(PreparedStatement.java:2009)
at com.mysql.jdbc.PreparedStatement.executeLargeUpdate(PreparedStatement.java:5094)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1994)
at Main.processPage(Main.java:67)
at Main.processPage(Main.java:95)
at Main.processPage(Main.java:95)
at Main.processPage(Main.java:105)
at Main.processPage(Main.java:105)
at Main.processPage(Main.java:101)
at Main.processPage(Main.java:105)
at Main.processPage(Main.java:101)
at Main.processPage(Main.java:101)
at Main.processPage(Main.java:105)
at Main.processPage(Main.java:105)
at Main.processPage(Main.java:105)
at Main.processPage(Main.java:105)
at Main.processPage(Main.java:105)
at Main.processPage(Main.java:105)
at Main.processPage(Main.java:105)
at Main.processPage(Main.java:105)
at Main.processPage(Main.java:105)
at Main.processPage(Main.java:101)
at Main.processPage(Main.java:105)
at Main.processPage(Main.java:105)
at Main.processPage(Main.java:105)
at Main.processPage(Main.java:101)
at Main.processPage(Main.java:105)
at Main.processPage(Main.java:105)
at Main.main(Main.java:17)
使用
String brew = tmp.replaceAll("'", "''");
而不是
String brew = tmp.replaceAll("'", "\\\\'");
结果是同样的问题
我的DB类中的runSql方法:
public ResultSet runSql(String sql) throws SQLException {
Statement sta = conn.createStatement();
return sta.executeQuery(sql);
}
如果有人有任何想法,请告诉我。我花了好几个小时尝试转义字符的不同变体,等等,但我找不到任何东西来解决这个问题。另一双眼睛看着我的代码可能正是我所需要的。提前感谢你的帮助
编辑:
我目前没有使用Spring或Hibernate。如果您已经知道如何使用带值标记的PreparedStatement?对于INSERT语句,为什么不在SELECT语句中也使用INSERT语句呢
这将以正确的方式修复错误。对这两个查询都使用PreparedStatement,您不必担心替换引号,您的选择将与插入保持一致。现在,select似乎与刚才插入的brewery不匹配,但由于名称重复,插入失败。这很有效。谢谢你。现在是下一系列问题;多亏了@Andreas,我才能够解决这个问题。如果有人遇到类似的问题,我将Brewery中的字符串sql=select*,其中name='+bName+';ResultSet rs=db.runSqlsql;字符串sql=select*from Brewery,其中name=?;;PreparedStatement ps=db.conn.prepareStatementsql,Statement.RETURN\u生成的\u键;ps.setString1,bName;结果集rs=ps.executeQuery;删除prepareStatement的第二个参数。RETURN_生成的_键只能用于主键自动生成的INSERT语句,例如IDENTITY、SERIAL、auto_INCREMENT、SEQUENCE等。@Andreas驱动程序应忽略语句。select语句的RETURN_生成的_键如中所示:应该可以正常工作。@markrotVeel实际上,驱动程序需要忽略它。然而,我并没有说你不能指定它,我说你不应该这样做。没用,;这对任何代码的读者都是误导性的。@Andreas很抱歉我不准确地使用了“应该”而不是“必须”;
String brew = tmp.replaceAll("'", "\\\\'");
public ResultSet runSql(String sql) throws SQLException {
Statement sta = conn.createStatement();
return sta.executeQuery(sql);
}