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

mem*_*und 49 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();
Run Code Online (Sandbox Code Playgroud)

为什么我得到这个例外?

org.hibernate.QueryException: Not all named parameters have been set: [username]
Run Code Online (Sandbox Code Playgroud)

Pre*_*ric 83

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

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

所以,使用它

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

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

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

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

  • 我知道这是一个旧线程,但是JPA确实允许命名参数,原始问题的问题是:em.setProperty(“ username”,“ test”); 并且应该像这样q.setParameter(“ username”,“ test”); (2认同)

Ahm*_*lem 11

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


Jef*_*son 9

我使用EclipseLink.此JPA允许以下方式用于本机查询:

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


obe*_*ies 7

你打电话setProperty而不是setParameter.将您的代码更改为

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

它应该工作.


pL4*_*u33 5

使用查询中的set Parameter。

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

  • @ pL4Gu33 Wihle JPA不支持此功能,某些实现支持,例如Hibernate。这就是它适用于OP的原因。我已经用此信息编辑了答案。 (2认同)

lek*_*ant 5

这是版本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);
        }
    });
Run Code Online (Sandbox Code Playgroud)