4.1 Tham số cho truy vấn

Hibernate cho phép bạn truyền tham số cho truy vấn. Như vậy, mọi công việc với truy vấn và cơ sở dữ liệu được đơn giản hóa rất nhiều.

Rất hiếm khi tìm thấy các truy vấn bất biến. Lúc đầu, có vẻ như bạn chỉ cần trả về một danh sách hàng hóa từ cơ sở dữ liệu. Và sau đó, hóa ra bạn cần một danh sách cập nhật các sản phẩm cho một người dùng cụ thể vào một ngày cụ thể. Được sắp xếp theo trường bắt buộc và chưa phải là toàn bộ danh sách mà là một trang cụ thể: ví dụ: các sản phẩm từ 21 đến 30.

Và đây chính xác là điều mà các truy vấn được tham số hóa giải quyết. Bạn viết một truy vấn trong HQL, sau đó bạn thay thế các giá trị có thể thay đổi bằng “tên đặc biệt” - tham số. Và sau đó riêng biệt khi thực hiện yêu cầu, bạn có thể chuyển các giá trị của các tham số này.

Hãy viết một truy vấn HQL sẽ trả về tất cả các tác vụ cho người dùng có tên cụ thể:

from EmployeeTask where employee.name = "Ivan Ivanovich"

Bây giờ hãy thay thế tên bằng một tham số:

from EmployeeTask where employee.name = :username

Và đây là cách mã Java của chúng tôi để tìm các tác vụ sẽ như sau:


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

Ngoài ra, thay vì tên tham số, bạn có thể chỉ sử dụng một số:


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

Tất nhiên, mặc dù tốt hơn là sử dụng tên - việc đọc và duy trì mã như vậy sẽ dễ dàng hơn nhiều.

4.2 Phương thức setParameterList().

Cũng có những trường hợp khi giá trị tham số không phải là một mà đại diện cho một danh sách các đối tượng. Ví dụ: chúng tôi muốn kiểm tra xem các ngành nghề của nhân viên có được chứa trong một danh sách nhất định hay không.

Làm thế nào điều này có thể được thực hiện:


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 loại danh sách có thể được truyền dưới dạng giá trị tham số:

  • mảng đối tượng: Object[]
  • bộ sưu tập: Bộ sưu tập
  • mảng đã nhập: T[]
  • bộ sưu tập đã nhập: Bộ sưu tập <T>

Nếu bạn quyết định chuyển một tập hợp hoặc mảng đã nhập, thì bạn cần chuyển kiểu dữ liệu làm tham số thứ ba. Ví dụ:


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

Khi làm việc với các tham số danh sách, bạn cũng có thể sử dụng một số thay cho tên tham số. Nhưng một lần nữa, tên là thuận tiện hơn.

4.3 Bảo vệ chống SQL injection

Một trong những mục đích quan trọng nhất của các tham số là bảo vệ cơ sở dữ liệu khỏi các lần tiêm SQL. Nhiều lập trình viên mới làm quen, thay vì sử dụng các tham số, chỉ cần dán một chuỗi gồm nhiều phần lại với nhau.

Thay vì viết như thế này:


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

Sẽ viết như thế này:


String hql = "from EmployeeTask where employee.name = " + "Ivan Ivanovich";
Query<EmployeeTask> query = session.createQuery( hql, EmployeeTask.class);
List<EmployeeTask> resultLIst = query.list();

Không bao giờ làm điều đó!Không bao giờ ghép một truy vấn SQL/HQL từ nhiều phần lại với nhau. Bởi vì sớm hay muộn tên người dùng sẽ đến với bạn từ khách hàng. Và tên hacker độc ác sẽ cung cấp cho bạn một chuỗi như""Ivan"; DROP TABLE user;"

Và sau đó truy vấn của bạn tới cơ sở dữ liệu sẽ có dạng:


from EmployeeTask where employee.name = "Ivan"; DROP TABLE user;

Và nó vẫn tốt nếu dữ liệu của bạn chỉ bị xóa. Bạn cũng có thể viết như thế này:


from EmployeeTask where employee.name = "Ivan";
UPDATE user SET password = '1' WHERE user.role = 'admin'

Hoặc như thế này:


from EmployeeTask where employee.name = "Ivan";
UPDATE user SET role = 'admin' WHERE user.id = 123;