如何使用命名参数创build本机查询?

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

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

为什么我得到这个exception?

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

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

命名参数遵循4.4.1节定义的标识符的规则。 命名参数的使用适用于Java持久性查询语言,而不是为本地查询定义的。 只有定位参数绑定可以被移植用于本地查询。

所以,使用这个

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

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

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

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

经过多次尝试,我发现你应该使用createNativeQuery ,你可以使用#replace发送参数

在我的例子中

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

使用查询中的set参数。

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

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

编辑:执行本机查询的最佳方法仍然是使用NamedParameterJdbcTemplate它允许您需要检索不是托pipe实体的结果; 你可以使用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); } }); 

我使用EclipseLink。 这个JPA允许以下方式进行本地查询:

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