2017-08-09 24 views
0

需要一点帮助。在Exception中有一些问题,我在使用这个库时很新颖。感谢提前:)用HashMap编写语句,异常

错误:

com.mysql.jdbc.exceptions.jdbc4.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 ''common_translations.name' as 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(); 
    } 
} 
+3

您不能使用''占位符系统来代替表名或列名,它仅适用于价值。 – Berger

+0

哦,好的,谢谢。你有没有任何建议可以聪明地做到这一点? –

+2

也许你可以使用'StringBuilder'来根据目标表建立你的查询字符串。 – Berger

回答

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注入),所以你需要前

0

但从DB点,使某些控制器,你会试图执行一个查询:

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' 

一些parame TER值。但是你不能传递表或视图作为参数。这个不成立。

来解决你的问题,你可以使用这个片段:

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 .... 
} 
+0

好的,谢谢你,这正是我正在寻找的:)但问题是这段代码被数据库拒绝:/ –