# Hibernate `@NamedQuery`教程

> 原文： [https://howtodoinjava.com/hibernate/hibernate-named-query-tutorial/](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`

```java
@Entity
@Table(name = "DEPARTMENT", uniqueConstraints = {
					@UniqueConstraint(columnNames = "ID"),
					@UniqueConstraint(columnNames = "NAME") })
@NamedQueries
(
	{
		@NamedQuery(name=DepartmentEntity.GET_DEPARTMENT_BY_ID, query=DepartmentEntity.GET_DEPARTMENT_BY_ID_QUERY),
		@NamedQuery(name=DepartmentEntity.UPDATE_DEPARTMENT_BY_ID, query=DepartmentEntity.UPDATE_DEPARTMENT_BY_ID_QUERY)
	}
)
public class DepartmentEntity implements Serializable {

	static final String GET_DEPARTMENT_BY_ID_QUERY = "from DepartmentEntity d where d.id = :id"; 
	public static final String GET_DEPARTMENT_BY_ID = "GET_DEPARTMENT_BY_ID"; 

	static final String UPDATE_DEPARTMENT_BY_ID_QUERY = "UPDATE DepartmentEntity d SET d.name=:name where d.id = :id"; 
	public static final String UPDATE_DEPARTMENT_BY_ID = "UPDATE_DEPARTMENT_BY_ID"; 

	private static final long serialVersionUID = 1L;

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name = "ID", unique = true, nullable = false)
	private Integer id;

	@Column(name = "NAME", unique = true, nullable = false, length = 100)
	private String name;

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}

```

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

#### `TestHibernateNamedQuery.java`

```java
public class TestHibernateNamedQuery 
{
	public static void main(String[] args) 
	{
		//Open the hibernate session
		Session session = HibernateUtil.getSessionFactory().openSession();
		session.beginTransaction();
		try
		{
			//Update record using named query
			Query query = session.getNamedQuery(DepartmentEntity.UPDATE_DEPARTMENT_BY_ID)
										.setInteger("id", 1)
										.setString("name", "Finance");
			query.executeUpdate();

			//Get named query instance
			query = session.getNamedQuery(DepartmentEntity.GET_DEPARTMENT_BY_ID)
										.setInteger("id", 1);
			//Get all departments (instances of DepartmentEntity)
			DepartmentEntity department = (DepartmentEntity) query.uniqueResult();
			System.out.println(department.getName());
		}
		finally
		{
			session.getTransaction().commit();
			HibernateUtil.shutdown();
		}
	}
}

Output in console:

Hibernate: update DEPARTMENT set NAME=? where ID=?
Hibernate: select department0_.ID as ID0_, department0_.NAME as NAME0_ from DEPARTMENT department0_ where department0_.ID=?
Finance

```

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

## 要点：

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

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

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


[源码下载](https://docs.google.com/file/d/0B7yo2HclmjI4T3ZHRldLY0pKc0U/edit?usp=sharing "Hibernate named query tutorial")

**祝您学习愉快！**