Hibernate 命名查询示例– @NamedQuery
欢迎使用Hibernate命名查询示例教程。
我们了解了如何在Hibernate中使用HQL和本机SQL查询。
如果查询很多,那么它们将导致代码混乱,因为所有查询都将分散在整个项目中。
因此,Hibernate提供了命名查询,我们可以在中央位置定义该命名查询并在代码中的任何位置使用它们。
我们可以为HQL和本机SQL创建命名查询。
Hibernate 命名查询
可以在Hibernate映射文件中定义Hibernate命名查询,也可以使用JPA批注" @NamedQuery"和" @NamedNativeQuery"来定义。
今天,我们将研究它们两者以及如何在简单的应用程序中使用Hibernate 命名查询。
我们将使用与HQL示例中相同的数据库表,因此您可以检查该帖子以获取数据库设置sql脚本。
对于我们的Hibernate 命名查询示例项目,我们将使用注释进行Hibernate 映射。
但是,我们将在映射文件和实体Bean类中创建一些命名查询。
我们的最终项目结构如下图所示,我们将主要关注与Hibernate Named Query相关的组件。
Hibernate 配置XML
hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuration SYSTEM "https://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <property name="hibernate.connection.password">hyman123</property> <property name="hibernate.connection.url">jdbc:mysql://localhost/TestDB</property> <property name="hibernate.connection.username">hyman</property> <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> <property name="hibernate.current_session_context_class">thread</property> <property name="hibernate.show_sql">true</property> <mapping class="com.theitroad.hibernate.model.Employee" <mapping class="com.theitroad.hibernate.model.Address" <mapping resource="named-queries.hbm.xml" </session-factory> </hibernate-configuration>
Hibernate命名查询XML
我们有一个Hibernate 映射文件,其中仅包含HQL命名查询和Native SQL命名查询。
named-queries.hbm.xml
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "https://hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <query name="HQL_GET_ALL_EMPLOYEE">from Employee</query> <query name="HQL_GET_EMPLOYEE_BY_ID"> <![CDATA[from Employee where emp_id = :id]]> </query> <query name="HQL_GET_EMPLOYEE_BY_SALARY"> <![CDATA[from Employee where emp_salary > :salary]]> </query> <sql-query name="SQL_GET_ALL_EMPLOYEE"> <![CDATA[select emp_id, emp_name, emp_salary from Employee]]> </sql-query> <sql-query name="SQL_GET_ALL_EMP_ADDRESS"> <![CDATA[select {e.*}, {a.*} from Employee e join Address a ON e.emp_id=a.emp_id]]> <return alias="e" class="com.theitroad.hibernate.model.Employee" <return-join alias="a" property="e.address"></return-join> </sql-query> </hibernate-mapping>
query元素用于HQL命名查询,而sql-query元素用于本机sql命名查询。
我们可以使用return元素声明将结果集映射到的实体。
当我们有多个表的联接时,使用return-join。
我们应该使用CDATA声明我们的Hibernate 命名查询,以确保将其视为数据,否则<和>单个字母会弄乱我们的映射XML文件。
Hibernate命名查询@NamedQuery注释
我们有两个模型类–雇员和地址。
我们在"地址"类中定义了名称查询,如下所示。
package com.theitroad.hibernate.model; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.NamedNativeQueries; import javax.persistence.NamedNativeQuery; import javax.persistence.NamedQueries; import javax.persistence.NamedQuery; import javax.persistence.OneToOne; import javax.persistence.PrimaryKeyJoinColumn; import javax.persistence.Table; import org.hibernate.annotations.GenericGenerator; import org.hibernate.annotations.Parameter; @Entity @Table(name = "ADDRESS") @NamedQueries({ @NamedQuery(name = "@HQL_GET_ALL_ADDRESS", query = "from Address") }) @NamedNativeQueries({ @NamedNativeQuery(name = "@SQL_GET_ALL_ADDRESS", query = "select emp_id, address_line1, city, zipcode from Address") }) public class Address { @Id @Column(name = "emp_id", unique = true, nullable = false) @GeneratedValue(generator = "gen") @GenericGenerator(name = "gen", strategy = "foreign", parameters = { @Parameter(name = "property", value = "employee") }) private long id; @Column(name = "address_line1") private String addressLine1; @Column(name = "zipcode") private String zipcode; @Column(name = "city") private String city; @OneToOne @PrimaryKeyJoinColumn private Employee employee; public long getId() { return id; } public void setId(long id) { this.id = id; } public String getAddressLine1() { return addressLine1; } public void setAddressLine1(String addressLine1) { this.addressLine1 = addressLine1; } public String getZipcode() { return zipcode; } public void setZipcode(String zipcode) { this.zipcode = zipcode; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } public Employee getEmployee() { return employee; } public void setEmployee(Employee employee) { this.employee = employee; } @Override public String toString() { return "AddressLine1= " + addressLine1 + ", City=" + city + ", Zipcode=" + zipcode; } }
Hibernate 命名查询测试程序
让我们编写一个测试程序,以使用上面定义的所有Hibernate 命名查询。
package com.theitroad.hibernate.main; import java.util.List; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import com.theitroad.hibernate.model.Address; import com.theitroad.hibernate.model.Employee; import com.theitroad.hibernate.util.HibernateUtil; public class HibernateNamedQueryExample { @SuppressWarnings("unchecked") public static void main(String[] args) { //Prep work SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); Session session = sessionFactory.getCurrentSession(); Transaction tx = session.beginTransaction(); //HQL Named Query Example Query query = session.getNamedQuery("HQL_GET_ALL_EMPLOYEE"); List<Employee> empList = query.list(); for (Employee emp : empList) { System.out.println("List of Employees::" + emp.getId() + "," + emp.getAddress().getCity()); } query = session.getNamedQuery("HQL_GET_EMPLOYEE_BY_ID"); query.setInteger("id", 2); Employee emp = (Employee) query.uniqueResult(); System.out.println("Employee Name=" + emp.getName() + ", City=" + emp.getAddress().getCity()); query = session.getNamedQuery("HQL_GET_EMPLOYEE_BY_SALARY"); query.setInteger("salary", 200); empList = query.list(); for (Employee emp1 : empList) { System.out.println("List of Employees::" + emp1.getId() + "," + emp1.getSalary()); } query = session.getNamedQuery("@HQL_GET_ALL_ADDRESS"); List<Address> addressList = query.list(); for (Address addr : addressList) { System.out.println("List of Address::" + addr.getId() + "::" + addr.getZipcode() + "::" + addr.getEmployee().getName()); } //Native SQL Named Query Example query = session.getNamedQuery("@SQL_GET_ALL_ADDRESS"); List<Object[]> addressObjArray = query.list(); for(Object[] row : addressObjArray){ for(Object obj : row){ System.out.print(obj + "::"); } System.out.println("\n"); } query = session.getNamedQuery("SQL_GET_ALL_EMP_ADDRESS"); addressObjArray = query.list(); for(Object[] row : addressObjArray){ Employee e = (Employee) row[0]; System.out.println("Employee Info::"+e); Address a = (Address) row[1]; System.out.println("Address Info::"+a); } //rolling back to save the test data tx.commit(); //closing hibernate resources sessionFactory.close(); } }
当我们使用测试数据执行上述程序时,将产生以下输出。
Hibernate: select employee0_.emp_id as emp_id1_1_, employee0_.emp_name as emp_name2_1_, employee0_.emp_salary as emp_sala3_1_ from EMPLOYEE employee0_ Hibernate: select address0_.emp_id as emp_id1_0_0_, address0_.address_line1 as address_2_0_0_, address0_.city as city3_0_0_, address0_.zipcode as zipcode4_0_0_, employee1_.emp_id as emp_id1_1_1_, employee1_.emp_name as emp_name2_1_1_, employee1_.emp_salary as emp_sala3_1_1_ from ADDRESS address0_ left outer join EMPLOYEE employee1_ on address0_.emp_id=employee1_.emp_id where address0_.emp_id=? Hibernate: select address0_.emp_id as emp_id1_0_0_, address0_.address_line1 as address_2_0_0_, address0_.city as city3_0_0_, address0_.zipcode as zipcode4_0_0_, employee1_.emp_id as emp_id1_1_1_, employee1_.emp_name as emp_name2_1_1_, employee1_.emp_salary as emp_sala3_1_1_ from ADDRESS address0_ left outer join EMPLOYEE employee1_ on address0_.emp_id=employee1_.emp_id where address0_.emp_id=? Hibernate: select address0_.emp_id as emp_id1_0_0_, address0_.address_line1 as address_2_0_0_, address0_.city as city3_0_0_, address0_.zipcode as zipcode4_0_0_, employee1_.emp_id as emp_id1_1_1_, employee1_.emp_name as emp_name2_1_1_, employee1_.emp_salary as emp_sala3_1_1_ from ADDRESS address0_ left outer join EMPLOYEE employee1_ on address0_.emp_id=employee1_.emp_id where address0_.emp_id=? Hibernate: select address0_.emp_id as emp_id1_0_0_, address0_.address_line1 as address_2_0_0_, address0_.city as city3_0_0_, address0_.zipcode as zipcode4_0_0_, employee1_.emp_id as emp_id1_1_1_, employee1_.emp_name as emp_name2_1_1_, employee1_.emp_salary as emp_sala3_1_1_ from ADDRESS address0_ left outer join EMPLOYEE employee1_ on address0_.emp_id=employee1_.emp_id where address0_.emp_id=? List of Employees::1,San Jose List of Employees::2,Santa Clara List of Employees::3,Bangalore List of Employees::4,New Delhi Hibernate: select employee0_.emp_id as emp_id1_1_, employee0_.emp_name as emp_name2_1_, employee0_.emp_salary as emp_sala3_1_ from EMPLOYEE employee0_ where emp_id=? Employee Name=David, City=Santa Clara Hibernate: select employee0_.emp_id as emp_id1_1_, employee0_.emp_name as emp_name2_1_, employee0_.emp_salary as emp_sala3_1_ from EMPLOYEE employee0_ where emp_salary>? List of Employees::3,300.0 List of Employees::4,400.0 Hibernate: select address0_.emp_id as emp_id1_0_, address0_.address_line1 as address_2_0_, address0_.city as city3_0_, address0_.zipcode as zipcode4_0_ from ADDRESS address0_ List of Address::1::95129::hyman List of Address::2::95051::David List of Address::3::560100::Lisa List of Address::4::100100::Hyman Hibernate: select emp_id, address_line1, city, zipcode from Address 1::Albany Dr::San Jose::95129:: 2::Arques Ave::Santa Clara::95051:: 3::BTM 1st Stage::Bangalore::560100:: 4::City Centre::New Delhi::100100:: Hibernate: select e.emp_id as emp_id1_1_0_, e.emp_name as emp_name2_1_0_, e.emp_salary as emp_sala3_1_0_, a.emp_id as emp_id1_0_1_, a.address_line1 as address_2_0_1_, a.city as city3_0_1_, a.zipcode as zipcode4_0_1_ from Employee e join Address a ON e.emp_id=a.emp_id Employee Info::Id= 1, Name= hyman, Salary= 100.0, {Address= AddressLine1= Albany Dr, City=San Jose, Zipcode=95129} Address Info::AddressLine1= Albany Dr, City=San Jose, Zipcode=95129 Employee Info::Id= 2, Name= David, Salary= 200.0, {Address= AddressLine1= Arques Ave, City=Santa Clara, Zipcode=95051} Address Info::AddressLine1= Arques Ave, City=Santa Clara, Zipcode=95051 Employee Info::Id= 3, Name= Lisa, Salary= 300.0, {Address= AddressLine1= BTM 1st Stage, City=Bangalore, Zipcode=560100} Address Info::AddressLine1= BTM 1st Stage, City=Bangalore, Zipcode=560100 Employee Info::Id= 4, Name= Hyman, Salary= 400.0, {Address= AddressLine1= City Centre, City=New Delhi, Zipcode=100100} Address Info::AddressLine1= City Centre, City=New Delhi, Zipcode=100100
Hibernate 命名查询要点
关于Hibernate命名查询的几个要点是:
Hibernate命名查询可帮助我们在中央位置对查询进行分组,而不是让它们分散在整个代码中。
创建Hibernate 会话工厂时,将检查"Hibernate 命名查询"语法,从而使应用程序在命名查询中发生任何错误的情况下快速失败。
Hibernate命名查询是全局的,这意味着一旦定义,它就可以在整个应用程序中使用。
命名查询的主要缺点之一是难以调试,因为我们需要找出定义它的位置。