具有命名参数的本机查询失败并显示 "Not all named parameters have been set"

Native query with named parameter fails with "Not all named parameters have been set"

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

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

使用查询中的设置参数。

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

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

Named parameters follow the rules for identifiers defined in Section 4.4.1. The use of named parameters applies to the Java Persistence query language, and is not defined for native queries. Only positional parameter binding may be portably used for native queries.

所以,使用这个

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

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

Native SQL queries support positional as well as named parameters

但是,这会将您的应用程序耦合到特定的 JPA 实现,因此使其不可移植。

这是版本 4.3.11 中修复的错误 https://hibernate.atlassian.net/browse/HHH-2851

编辑: 执行本机查询的最佳方法仍然是使用 NamedParameterJdbcTemplate 它允许您需要检索一个不是托管实体的结果;您可以使用 RowMapper 甚至 Map 命名参数 !

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);
        }
    });

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

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

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

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

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

它应该可以工作。