原文: https://howtodoinjava.com/hibernate/hibernate-named-query-tutorial/

Hiberate 中的命名查询是一种技术,用于将 HQL 语句分组在单个位置中,并在以后需要使用它们时以某种名称对其进行引用。 它在很大程度上有助于代码清除,因为这些 HQL 语句不再分散在整个代码中。

除了上面的内容,以下是命名查询的一些次要优势

  1. 快速失败:创建会话工厂时会检查其语法,从而在发生错误时使应用快速失败。
  2. 可重用:可以从多个位置访问和使用它们,从而提高了可重用性。

但是,您必须知道,命名查询确实会使代码的可读性降低,并且有时调试变得更困难,因为您必须找到正在执行的实际查询定义,并且也必须对此有所了解。

性能明智的命名查询并没有多大区别,也不会增加任何开销。

  1. 与实际执行查询的成本相比,将 HQL 查询转换为 SQL 的成本可忽略不计
  2. 缓存查询的内存开销确实很小。 请记住,Hibernate 无论如何都需要在内存中存储所有实体元数据。

在本教程中,我将提供一个使用注解配置的命名查询的示例。

我有一个DepartmentEntity.java类,它映射到数据库中的Department表。 我编写了两个命名查询,一个用于通过其 ID 更新部门名称,第二个用于通过其 ID 选择部门。

命名查询定义具有两个重要属性:

  • name :使用 Hiberate 会话定位名称查询的名称。
  • query:在这里,您将给出 HQL 语句以在数据库中执行。

DepartmentEntity.java

  1. @Entity
  2. @Table(name = "DEPARTMENT", uniqueConstraints = {
  3. @UniqueConstraint(columnNames = "ID"),
  4. @UniqueConstraint(columnNames = "NAME") })
  5. @NamedQueries
  6. (
  7. {
  8. @NamedQuery(name=DepartmentEntity.GET_DEPARTMENT_BY_ID, query=DepartmentEntity.GET_DEPARTMENT_BY_ID_QUERY),
  9. @NamedQuery(name=DepartmentEntity.UPDATE_DEPARTMENT_BY_ID, query=DepartmentEntity.UPDATE_DEPARTMENT_BY_ID_QUERY)
  10. }
  11. )
  12. public class DepartmentEntity implements Serializable {
  13. static final String GET_DEPARTMENT_BY_ID_QUERY = "from DepartmentEntity d where d.id = :id";
  14. public static final String GET_DEPARTMENT_BY_ID = "GET_DEPARTMENT_BY_ID";
  15. static final String UPDATE_DEPARTMENT_BY_ID_QUERY = "UPDATE DepartmentEntity d SET d.name=:name where d.id = :id";
  16. public static final String UPDATE_DEPARTMENT_BY_ID = "UPDATE_DEPARTMENT_BY_ID";
  17. private static final long serialVersionUID = 1L;
  18. @Id
  19. @GeneratedValue(strategy = GenerationType.IDENTITY)
  20. @Column(name = "ID", unique = true, nullable = false)
  21. private Integer id;
  22. @Column(name = "NAME", unique = true, nullable = false, length = 100)
  23. private String name;
  24. public Integer getId() {
  25. return id;
  26. }
  27. public void setId(Integer id) {
  28. this.id = id;
  29. }
  30. public String getName() {
  31. return name;
  32. }
  33. public void setName(String name) {
  34. this.name = name;
  35. }
  36. }

为了测试,在上面的命名查询中,我编写了以下代码并执行了两个命名查询。

TestHibernateNamedQuery.java

  1. public class TestHibernateNamedQuery
  2. {
  3. public static void main(String[] args)
  4. {
  5. //Open the hibernate session
  6. Session session = HibernateUtil.getSessionFactory().openSession();
  7. session.beginTransaction();
  8. try
  9. {
  10. //Update record using named query
  11. Query query = session.getNamedQuery(DepartmentEntity.UPDATE_DEPARTMENT_BY_ID)
  12. .setInteger("id", 1)
  13. .setString("name", "Finance");
  14. query.executeUpdate();
  15. //Get named query instance
  16. query = session.getNamedQuery(DepartmentEntity.GET_DEPARTMENT_BY_ID)
  17. .setInteger("id", 1);
  18. //Get all departments (instances of DepartmentEntity)
  19. DepartmentEntity department = (DepartmentEntity) query.uniqueResult();
  20. System.out.println(department.getName());
  21. }
  22. finally
  23. {
  24. session.getTransaction().commit();
  25. HibernateUtil.shutdown();
  26. }
  27. }
  28. }
  29. Output in console:
  30. Hibernate: update DEPARTMENT set NAME=? where ID=?
  31. Hibernate: select department0_.ID as ID0_, department0_.NAME as NAME0_ from DEPARTMENT department0_ where department0_.ID=?
  32. Finance

其余支持代码可以在教程最后随附的源代码中找到。

要点:

  1. 使用 JPA 样式查询语言。 例如,使用实体名代替表名。
  2. 优选将命名查询仅用于基于复杂条件选择记录。 不要过多地使用它们,否则就不会在简单的 JDBC 上使用 ORM。
  3. 请记住,命名查询的结果不会缓存在辅助缓存中,只有查询对象本身会被缓存。
  4. 每当在代码中添加任何命名查询时,都要养成添加几个单元测试用例的习惯。 并立即运行那些单元测试用例。
  5. Hiberate 中不能有两个具有相同名称的命名查询。 Hibernate 在这方面显示出快速失败的行为,并且将显示应用启动本身中的错误。

到目前为止,所有这些都与 Hiberate 中的命名查询有关。

让我知道您的想法和建议。

源码下载

祝您学习愉快!