如何使用命名参数创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();