💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
# 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") **祝您学习愉快!**