带有命名参数的本机查询失败,并且“未设置所有已命名的参数”

时间:2015-03-03 10:47:09

标签: java hibernate jpa

我想执行一个简单的本机查询,但它不起作用:

@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]

6 个答案:

答案 0 :(得分:75)

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

  

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

所以,请使用此

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

虽然JPA规范不支持本机查询中的命名参数,但某些JPA实现(如Hibernate)可能支持它

  

本机SQL查询支持位置和命名参数

但是,这会将您的应用程序与特定的JPA实现相结合,从而使其无法移植。

答案 1 :(得分:10)

经过多次尝试后,我发现您应该使用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();

答案 2 :(得分:8)

我使用EclipseLink。此JPA允许以下方式进行本机查询:

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

答案 3 :(得分:6)

您正在呼叫setProperty而不是setParameter。将您的代码更改为

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

它应该有用。

答案 4 :(得分:5)

这是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 :(得分:4)

使用查询中的set参数。

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