4.1 请求参数
Hibernate 允许您将参数传递给查询。因此,所有与查询和数据库的工作都大大简化了。
很难找到不可变的查询。起初,您似乎只需要从数据库中返回一个商品列表即可。然后事实证明,您需要在特定日期为特定用户提供最新的产品列表。按必填字段排序,但不是整个列表,而是特定页面:例如,从 21 到 30 的产品。
而这正是参数化查询解决的问题。你用 HQL 写一个查询,然后你用“特殊名称”——参数来替换可以改变的值。然后分别在执行请求的时候,可以传递这些参数的值。
让我们编写一个 HQL 查询,它将返回具有特定名称的用户的所有任务:
from EmployeeTask where employee.name = "Ivan Ivanovich"
现在让我们用参数替换名称:
from EmployeeTask where employee.name = :username
这就是我们用于查找任务的 Java 代码的样子:
String hql = "from EmployeeTask where employee.name = :username";
Query<EmployeeTask> query = session.createQuery( hql, EmployeeTask.class);
query.setParameter("username", "Ivan Ivanovich");
List<EmployeeTask> resultLIst = query.list();
此外,您可以只使用一个数字来代替参数名称:
String hql = "from EmployeeTask where employee.name = :1";
Query<EmployeeTask> query = session.createQuery( hql, EmployeeTask.class);
query.setParameter(1, "Ivan Ivanovich");
List<EmployeeTask> resultLIst = query.list();
当然,使用名称当然更好 - 阅读和维护此类代码要容易得多。
4.2 setParameterList()方法。
也有参数值不是一个,而是代表一个对象列表的情况。例如,我们要检查员工的职业是否包含在某个列表中。
这是怎么做到的:
String hql = "from EmployeeTask where occupation IN (:occupation_list)";
Query<EmployeeTask> query = session.createQuery( hql, EmployeeTask.class);
query.setParameterList("occupation_list", new String[] {"Programmer", "Tester"});
List<EmployeeTask> resultLIst = query.list();
4种类型的列表可以作为参数值传递:
- 对象数组:Object[]
- 收藏:收藏
- 类型数组:T[]
- 类型集合:Collection<T>
如果您决定传递类型化集合或数组,则需要将数据类型作为第三个参数传递。例子:
String hql = "from EmployeeTask where occupation IN (:occupation_list)";
Query<EmployeeTask> query = session.createQuery( hql, EmployeeTask.class);
query.setParameterList("occupation_list", new String[] {"Programmer", "Tester"}, String.class);
List<EmployeeTask> resultLIst = query.list();
使用列表参数时,您还可以使用数字代替参数名称。但同样,名称更方便。
4.3 防止SQL注入
这些参数最重要的目的之一是保护数据库免受 SQL 注入。许多新手程序员不使用参数,而是简单地将几个部分的字符串粘合在一起。
而不是这样写:
String hql = "from EmployeeTask where employee.name = :username";
Query<EmployeeTask> query = session.createQuery( hql, EmployeeTask.class);
query.setParameter("username", "Ivan Ivanovich");
List<EmployeeTask> resultLIst = query.list();
会这样写:
String hql = "from EmployeeTask where employee.name = " + "Ivan Ivanovich";
Query<EmployeeTask> query = session.createQuery( hql, EmployeeTask.class);
List<EmployeeTask> resultLIst = query.list();
永远不要那样做!永远不要将来自多个部分的 SQL/HQL 查询粘在一起。因为用户名迟早会从客户端传给你。邪恶的黑客会给你一个字符串""Ivan"; DROP TABLE user;"
然后您对数据库的查询将采用以下形式:
from EmployeeTask where employee.name = "Ivan"; DROP TABLE user;
如果您的数据只是被删除,那仍然很好。你也可以这样写:
from EmployeeTask where employee.name = "Ivan";
UPDATE user SET password = '1' WHERE user.role = 'admin'
或者像这样:
from EmployeeTask where employee.name = "Ivan";
UPDATE user SET role = 'admin' WHERE user.id = 123;
GO TO FULL VERSION