带有 HashMap 的准备好的语句,异常

Posted

技术标签:

【中文标题】带有 HashMap 的准备好的语句,异常【英文标题】:Prepared Statement with HashMap, Exception 【发布时间】:2017-08-09 12:44:47 【问题描述】:

需要一点帮助。遇到一些异常问题,我在使用这个库时非常陌生。在此先感谢:)

错误:

com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: 你的 SQL 语法有错误;查看与您的 MySQL 服务器版本相对应的手册,了解在 ''common_translations.name' 作为 nm JOIN ('common_translations.name_id' as nid) 附近使用的正确语法

我的代码:

private DatabaseConnection db;
private final HashMap <String, String> statements;

public DatabaseReader(DatabaseConnection db) 
    statements = new HashMap<String, String>() 
        private static final long serialVersionUID = -1827340576955092045L;
    
        put("odds","vfl::%");
        put("common_translations", "vhc::%");
        put("common_translations","vdr::%");
        put("common_translations", "vto::%");
        put("common_translations","vbl::%");
        put("common_translations", "vf::%");
        put("odds","vsm::%");
        put("odds", "rgs::%");
        put("odds", "srrgs::%");
    ;

    this.db = db;


public void read() 
    try 
        Connection connection = db.connect(db.getUrl_common_translation());
        PreparedStatement ps = (PreparedStatement) connection.prepareStatement("SELECT nm.id, nid.key, nm.name FROM ? as nm JOIN (? as nid)\r\n" + 
                "                 ON (nm.id = nid.id) where nid.key like ? and nm.typeId=8 and nm.sourceId=-1 and nm.languageCode='en'");           
        for(Entry <String,String> e : statements.entrySet()) 
            ps.setString(1, e.getKey() + ".name");
            ps.setString(2, e.getKey() + ".name_id");
            ps.setString(3, e.getValue());
            ResultSet rs = ps.executeQuery();
            while(rs.next()) 
                int id = rs.getInt("id");
                //String tag = rs.getString("tag");
                //String translation = rs.getString("translation");     
                System.out.println(id);
            
        



     catch (SQLException e) 
        e.printStackTrace();
       

【问题讨论】:

您不能使用? 占位符系统来替换表名或列名,它只适用于值。 哦,好的,谢谢。你有什么建议可以明智地做到这一点吗? 好吧,也许您可​​以使用StringBuilder 根据目标表构建您的查询字符串。 【参考方案1】:

您以错误的方式设置列的名称,这是:

ps.setString(1, e.getKey() + ".name");
ps.setString(2, e.getKey() + ".name_id");

将在引号之间输入:

FROM "something.name" as

这是错误的语法。

相反,您必须直接设置名称,而无需像这样准备好的语句:

Connection connection = db.connect(db.getUrl_common_translation());
PreparedStatement ps = (PreparedStatement) connection.prepareStatement();
for (Entry<String, String> e : statements.entrySet()) 
    String query = "SELECT nm.id, nid.key, nm.name FROM " + e.getKey() + ".name" +" as nm "
            //----------------------------------------------^__________________^
            + "JOIN (" + e.getKey() + ".name_id" + " as nid) ON (nm.id = nid.id) "
            //-----------^_____________________^
            + "where nid.key like ? and nm.typeId=8 "
            + "and nm.sourceId=-1 and nm.languageCode='en'";
    ps.setString(1, e.getValue());
    ResultSet rs = ps.executeQuery(query);
    //------------------------------^^

但在此之前,您必须检查名称不应包含感染查询的内容(以避免语法错误和 sql 注入),因此您需要在此之前制作一些控制器

【讨论】:

【参考方案2】:

从数据库的角度来看,您将尝试执行查询:

SELECT nm.id, nid.key, nm.name 
  FROM :param1 as nm 
       JOIN (:param2 as nid) ON (nm.id = nid.id) 
 where nid.key like :param3 and nm.typeId=8 and nm.sourceId=-1 and nm.languageCode='en'

带有一些参数。但是您不能将表或视图作为参数传递。没有意义。

要解决你的问题,你可以使用这个 sn-p:

String sql = "SELECT nm.id, nid.key, nm.name FROM %s as nm JOIN (%s as nid)\r\n" + 
            "                 ON (nm.id = nid.id) where nid.key like ? and nm.typeId=8 and nm.sourceId=-1 and nm.languageCode='en'"
for(Entry <String,String> e : statements.entrySet()) 
    PreparedStatement ps = (PreparedStatement) connection.prepareStatement(
          String.format(sql, e.getKey() + ".name", e.getKey() + ".name_id")
    );           
    ps.setString(1, e.getValue());
        .... your code here ....

【讨论】:

嗯,谢谢,这正是我想要的 :) 但问题是这段代码被数据库拒绝了:/

以上是关于带有 HashMap 的准备好的语句,异常的主要内容,如果未能解决你的问题,请参考以下文章

Google BigQuery,在准备好的语句中为空值引发异常

插入带有准备好的语句的日期时间[重复]

带有位域的 PDO 准备好的语句

带有 IN() 条件的 WordPress 准备好的语句

带有准备好的语句的 PostgreSQL 内部查询

准备好的语句失败(带有错误消息!)