2015-03-03 76 views
23

我想执行一个简单的本地查询,但它不工作:与命名参数本地查询失败,“不是所有命名的参数已经被设置为”

@Autowired 
private EntityManager em; 

Query q = em.createNativeQuery("SELECT count(*) FROM mytable where username = :username"); 
em.setProperty("username", "test"); 
(int) q.getSingleResult(); 

为什么会出现这种异常?

org.hibernate.QueryException: Not all named parameters have been set: [username] 
+0

只是一个提示,你为什么要使用原生查询这个查询?你可以使用Jpa查询语言来做同样的事情,而选择Jpa查询有很多好处。 – 2015-03-03 11:33:55

+0

@Rafael Zeffa我可以在没有'@ Entity'类的情况下使用jpa吗?如果是这样,你可以请建议如何使用jpa优化它? – membersound 2015-03-03 12:13:20

+0

没有一个实体你不能做到这一点,但为什么你不能映射该表的@entity? – 2015-03-03 12:28:32

回答

45

本机查询中JPA不支持命名参数,仅用于JPQL。您必须使用位置参数。

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

因此,使用这种

Query q = em.createNativeQuery("SELECT count(*) FROM mytable where username = ?1"); 
q.setParameter(1, "test"); 

虽然JPA规范不支持本机查询命名参数,一些JPA实现(如Hibernate)可以支持它

原生查询支持位置以及命名参数

但是,这会将您的应用程序与特定的JPA实现耦合在一起,从而使其不可移植。

+1

是的,但我忘了它......并在我的例子上测试它。请将此答案标记为正确。 – pL4Gu33 2015-03-03 10:58:31

3

从查询中使用set参数。

Query q = (Query) em.createNativeQuery("SELECT count(*) FROM mytable where username = ?1"); 
q.setParameter(1, "test"); 
+0

没有那是正确的导入。但是你应该使用整数参数。 NativeQuery不适用于字符串参数。我编辑我的答案。 – pL4Gu33 2015-03-03 10:55:28

+0

对不起,我刚刚注意到我使用'em'上的setparam,而不是查询... – membersound 2015-03-03 10:56:48

+1

没有问题:) .. – pL4Gu33 2015-03-03 10:59:52

2

这是固定在版中的错误4.3.11 https://hibernate.atlassian.net/browse/HHH-2851

编辑:执行原生查询 最好的办法是你仍然需要检索结果,该结果使用是NamedParameterJdbcTemplate 它允许不是管理实体;你可以使用RowMapper甚至命名参数图

private NamedParameterJdbcTemplate namedParameterJdbcTemplate; 

@Autowired 
public void setDataSource(DataSource dataSource) { 
    this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource); 
} 

final List<Long> resultList = namedParameterJdbcTemplate.query(query, 
      mapOfNamedParamters, 
      new RowMapper<Long>() { 
     @Override 
     public Long mapRow(ResultSet rs, int rowNum) throws SQLException { 
      return rs.getLong(1); 
     } 
    }); 
5

多次尝试之后,我发现,你应该使用createNativeQuery你可以使用#更换

发送参数在我的例子

String UPDATE_lOGIN_TABLE_QUERY = "UPDATE OMFX.USER_LOGIN SET LOGOUT_TIME = SYSDATE WHERE LOGIN_ID = #loginId AND USER_ID = #userId"; 


Query query = em.createNativeQuery(logQuery); 

      query.setParameter("userId", logDataDto.getUserId()); 
      query.setParameter("loginId", logDataDto.getLoginId()); 

      query.executeUpdate(); 
+0

它的工作表示感谢 – ismail 2016-05-10 12:46:21

0

我将EclipseLink。这JPA允许本机查询方式如下:

Query q = em.createNativeQuery("SELECT * FROM mytable where username = ?username"); 
q.setParameter("username", "test"); 
q.getResultList(); 
2

要调用setProperty而不是setParameter。更改您的代码到

Query q = em.createNativeQuery("SELECT count(*) FROM mytable where username = :username"); 
em.setParameter("username", "test"); 
(int) q.getSingleResult(); 

它应该工作。