| 方式 | API | 適用場景 | 類型安全 | 可讀性 |
|---|---|---|---|---|
| 命名參數 | setParameter(name, value)setParameterList(name, list) | HQL/JPQL、參數多、複雜查詢 | 高(運行時檢查) | ★★★★★ |
| 位置參數 | setParameter(pos, value)setParameters(values[], types[]) | 原生SQL、簡單查詢、JDBC風格 | 中(需手動匹配類型) | ★★★☆☆ |
| 實體參數 | setEntity(name, entity) | 關聯實體查詢、主鍵為復合類型 | 高 | ★★★★☆ |
// 單值參數
String hql = "from User u where u.name = :name and u.age > :age";
Query q = session.createQuery(hql);
q.setParameter("name", "ZhangSan");
q.setParameter("age", 25);
// 集合參數(IN子句專用)
List<Integer> ids = Arrays.asList(1, 2, 3);
String hql2 = "from User u where u.id in (:ids)";
Query q2 = session.createQuery(hql2);
q2.setParameterList("ids", ids); // 自動展開為 (?, ?, ?)
// 原生SQL同理支持
String sql = "select * from users where name = :name";
SQLQuery sq = session.createSQLQuery(sql);
sq.setParameter("name", "LiSi");
優勢:參數順序無關、名稱自文檔、重複參數無需多次設置、集合參數自動處理IN子句展開。
// 單值
String hql = "from User u where u.name = ? and u.age > ?";
Query q = session.createQuery(hql);
q.setParameter(0, "WangWu"); // 索引從0開始
q.setParameter(1, 30);
// 批量設置(需手動指定Type)
Object[] values = { "ZhaoLiu", 28 };
Type[] types = { StandardBasicTypes.STRING, StandardBasicTypes.INTEGER };
q.setParameters(values, types);
// 原生SQL位置參數
String sql = "select * from users where name = ? and age > ?";
SQLQuery sq = session.createSQLQuery(sql);
sq.setParameter(0, "SunQi");
sq.setParameter(1, 35);
注意:HQL位置參數索引從0開始;JDBC原生PreparedStatement索引從1開始,切勿混淆。
// 假設Order關聯Customer,Customer主鍵為Long
Order order = ...;
String hql = "from Order o where o.customer = :cust";
Query q = session.createQuery(hql);
q.setEntity("cust", order.getCustomer()); // 自動提取主鍵值綁定
// 復合主鍵實體同理適用
CompositeKeyEntity entity = ...;
q.setEntity("entity", entity);
適用於關聯屬性為實體類型的查詢條件,Hibernate自動解析實體標識符(單一或復合主鍵)生成SQL,避免手動拼裝主鍵字段。
參數綁定後,結果映射常用模式:
// 映射到實體
SQLQuery sq = session.createSQLQuery("select * from users where id = ?")
.addEntity(User.class)
.setParameter(0, 1L);
User u = (User) sq.uniqueResult();
// 映射到VO (AliasToBean)
SQLQuery sq2 = session.createSQLQuery(
"select id as \"id\", name as \"name\" from users where id = ?")
.addScalar("id", StandardBasicTypes.LONG)
.addScalar("name", StandardBasicTypes.STRING)
.setResultTransformer(Transformers.aliasToBean(UserVO.class))
.setParameter(0, 1L);
UserVO vo = (UserVO) sq2.uniqueResult();
Type[],維護成本高,僅用於動態構建SQL的極少數場景。setParameter("name", null, StandardBasicTypes.STRING)指定類型,否則Hibernate無法推斷類型報錯。