原生查询产生MySQL语法错误和意外结果

问题描述:

在我的应用程序中,当User删除Message时,我需要删除2个实体之间的关系,同时保持它们完好无损。因此,我试图从关系表,可以使用以下方式直接删除行:原生查询产生MySQL语法错误和意外结果

1.

Query q = em.createNativeQuery("DELETE FROM User_Inbox WHERE User_USERNAME = :username AND Message_ID = :messageID"); 
q.setParameter("username", username); 
q.setParameter("messageID", messageID); 
q.executeUpdate(); 

2.

Query q = em.createNativeQuery("DELETE FROM User_Inbox WHERE User_USERNAME = :username AND Message_ID = :messageID"); 
q.setParameter("username", "'" + username + "'"); 
q.setParameter("messageID", "'" + messageID + "'"); 
q.executeUpdate(); 

的第一和第二方法产生的以下例外:

Internal Exception: 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 ':username AND 
Message_ID = :messageID' at line 1 
Error Code: 1064 

Query q = em.createNativeQuery("DELETE FROM User_Inbox WHERE User_USERNAME = ':username' AND Message_ID = ':messageID'"); 
q.setParameter("username", username); 
q.setParameter("messageID", messageID); 
q.executeUpdate(); 

第三届做法并没有产生任何异常。它正常通过。但是,User_Inbox表中没有任何内容被删除。

4.

Query q = em.createNativeQuery("DELETE FROM User_Inbox WHERE User_USERNAME = '" + username + "' AND Message_ID = '" + messageID + "'"); 
q.executeUpdate(); 

第四届方法完美。查询顺利进行,记录被正确删除。

最后一种方法奏效,但代码看起来并不整齐。如果有人能告诉我我在前三种方法中做错了什么,我将非常感激。

UPDATE:

基础上answer从D·穆尔,我刚刚发现,命名参数不能与本机查询使用。这在Pascal Thivent的answer中已经提到。

命名参数遵循 中定义的标识符的规则4.4.1。命名参数的使用适用于Java持久性查询语言,并且未针对本机查询定义。 只有 位置参数绑定可以可移植地用于本机 查询。

+0

查询使用模式中的表和列,它是如何映射到java对象的? – 2013-10-08 17:05:52

+0

@nikpon:有两个实体叫'User'和'Message',它们之间有'@ ManyToMany'关系。但是,我并没有从这两个实体的表格中删除任何东西。我需要从'@ ManyToMany'关系创建的'@ JoinTable'中删除记录。 –

+0

实体删除您可以发现一个连接表的简单情况,只包含您使用本机查询而不是从实体管理器中删除的引用。 – 2013-10-08 17:22:13

我同意(4.)当然不是正确的做事方式。这是乏味和不安全的。

(3.)正在工作,但由于它们有额外的引号而没有产生预期的结果。至于为什么(1.)不起作用,你会想看看正在生成的SQL(我相信这些设置是特定于你正在使用的JPA系统的)。你似乎有正确的代码,但错误意味着参数不被替换。

位置参数是否有不同的作用?

Query q = em.createNativeQuery("DELETE FROM User_Inbox WHERE User_USERNAME = ?1 AND Message_ID = ?2"); 
q.setParameter(1, username); 
q.setParameter(2, messageID); 
q.executeUpdate(); 
+0

这是使用什么样的参数?为什么不在JPA中使用命名参数? – 2013-10-08 17:25:17