2015-03-03 73 views
23

我想執行一個簡單的本地查詢,但它不工作:與命名參數本地查詢失敗,「不是所有命名的參數已經被設置爲」

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

只是一個提示,你爲什麼要使用原生查詢這個查詢?你可以使用Jpa查詢語言來做同樣的事情,而選擇Jpa查詢有很多好處。 – 2015-03-03 11:33:55

+0

@Rafael Zeffa我可以在沒有'@ Entity'類的情況下使用jpa嗎?如果是這樣,你可以請建議如何使用jpa優化它? – membersound 2015-03-03 12:13:20

+0

沒有一個實體你不能做到這一點,但爲什麼你不能映射該表的@entity? – 2015-03-03 12:28:32

回答

45

本機查詢中JPA不支持命名參數,僅用於JPQL。您必須使用位置參數。

命名參數遵循4.4.1節中定義的標識符的規則。命名參數的使用適用於Java持久性查詢語言,並且未針對本機查詢定義。 只有定位參數綁定可以移植用於原生查詢。

因此,使用這種

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

雖然JPA規範不支持本機查詢命名參數,一些JPA實現(如Hibernate)可以支持它

原生查詢支持位置以及命名參數

但是,這會將您的應用程序與特定的JPA實現耦合在一起,從而使其不可移植。

+1

是的,但我忘了它......並在我的例子上測試它。請將此答案標記爲正確。 – pL4Gu33 2015-03-03 10:58:31

3

從查詢中使用set參數。

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

沒有那是正確的導入。但是你應該使用整數參數。 NativeQuery不適用於字符串參數。我編輯我的答案。 – pL4Gu33 2015-03-03 10:55:28

+0

對不起,我剛剛注意到我使用'em'上的setparam,而不是查詢... – membersound 2015-03-03 10:56:48

+1

沒有問題:) .. – pL4Gu33 2015-03-03 10:59:52

2

這是固定在版中的錯誤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

多次嘗試之後,我發現,你應該使用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(); 
+0

它的工作表示感謝 – ismail 2016-05-10 12:46:21

0

我將EclipseLink。這JPA允許本機查詢方式如下:

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

要調用setProperty而不是setParameter。更改您的代碼到

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

它應該工作。