Hibernate 本机 SQL 查询示例
欢迎来到 Hibernate Native SQL 查询示例教程。我们在之前的文章中研究了Hibernate 查询语言和Hibernate Criteria,今天我们将通过示例研究 Hibernate Native SQL 查询。
Hibernate SQL 查询
Hibernate 提供通过使用SQLQuery对象执行本机 SQL 查询的选项。当我们必须执行 Hibernate API 不支持的数据库供应商特定查询时,Hibernate SQL 查询非常方便。例如,Oracle 数据库中的查询提示或 CONNECT 关键字。对于正常情况,不推荐使用 Hibernate SQL 查询方法,因为我们会失去与 Hibernate 关联和Hibernate 一级缓存相关的好处。我将使用 MySQL 数据库以及与HQL 示例中使用的相同表和数据设置,因此您应该首先查看它以了解表和相应的模型类映射。
Hibernate 本机 SQL 示例
对于 Hibernate Native SQL 查询,我们用来Session.createSQLQuery(String query)
创建 SQLQuery 对象并执行它。例如,如果您想从 Employee 表中读取所有记录,我们可以通过以下代码来实现。
// Prep work
SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
Session session = sessionFactory.getCurrentSession();
// Get All Employees
Transaction tx = session.beginTransaction();
SQLQuery query = session.createSQLQuery("select emp_id, emp_name, emp_salary from Employee");
List<Object[]> rows = query.list();
for(Object[] row : rows){
Employee emp = new Employee();
emp.setId(Long.parseLong(row[0].toString()));
emp.setName(row[1].toString());
emp.setSalary(Double.parseDouble(row[2].toString()));
System.out.println(emp);
}
当我们根据已有的数据设置执行上述代码时,它会产生以下输出。
Hibernate: select emp_id, emp_name, emp_salary from Employee
Id= 1, Name= Pankaj, Salary= 100.0, {Address= null}
Id= 2, Name= David, Salary= 200.0, {Address= null}
Id= 3, Name= Lisa, Salary= 300.0, {Address= null}
Id= 4, Name= Jack, Salary= 400.0, {Address= null}
请注意,该list()
方法返回对象数组列表,我们需要明确将它们解析为 double、long 等。我们的 Employee 和 Address 类具有以下toString()
方法实现。
@Override
public String toString() {
return "Id= " + id + ", Name= " + name + ", Salary= " + salary
+ ", {Address= " + address + "}";
}
@Override
public String toString() {
return "AddressLine1= " + addressLine1 + ", City=" + city
+ ", Zipcode=" + zipcode;
}
请注意,我们的查询没有返回地址数据,而如果我们使用 HQL 查询"from Employee"
,它也会返回关联表数据。
Hibernate SQL 查询 addScalar
Hibernate 使用ResultSetMetadata
推断查询返回的列的类型,从性能角度来看,我们可以使用addScalar()
方法来定义列的数据类型。然而,我们仍然会以 Object 数组的形式获取数据。
//Get All Employees - addScalar example
query = session.createSQLQuery("select emp_id, emp_name, emp_salary from Employee")
.addScalar("emp_id", new LongType())
.addScalar("emp_name", new StringType())
.addScalar("emp_salary", new DoubleType());
rows = query.list();
for(Object[] row : rows){
Employee emp = new Employee();
emp.setId(Long.parseLong(row[0].toString()));
emp.setName(row[1].toString());
emp.setSalary(Double.parseDouble(row[2].toString()));
System.out.println(emp);
}
生成的输出将是相同的,但是当数据量很大时,我们会看到性能略有改善。
Hibernate 本机 SQL 多表
如果我们想从 Employee 和 Address 表中获取数据,我们可以简单地编写 SQL 查询并解析结果集。
query = session.createSQLQuery("select e.emp_id, emp_name, emp_salary,address_line1, city,
zipcode from Employee e, Address a where a.emp_id=e.emp_id");
rows = query.list();
for(Object[] row : rows){
Employee emp = new Employee();
emp.setId(Long.parseLong(row[0].toString()));
emp.setName(row[1].toString());
emp.setSalary(Double.parseDouble(row[2].toString()));
Address address = new Address();
address.setAddressLine1(row[3].toString());
address.setCity(row[4].toString());
address.setZipcode(row[5].toString());
emp.setAddress(address);
System.out.println(emp);
}
对于上述代码,产生的输出将如下所示。
Hibernate: select e.emp_id, emp_name, emp_salary,address_line1, city, zipcode from Employee e, Address a where a.emp_id=e.emp_id
Id= 1, Name= Pankaj, Salary= 100.0, {Address= AddressLine1= Albany Dr, City=San Jose, Zipcode=95129}
Id= 2, Name= David, Salary= 200.0, {Address= AddressLine1= Arques Ave, City=Santa Clara, Zipcode=95051}
Id= 3, Name= Lisa, Salary= 300.0, {Address= AddressLine1= BTM 1st Stage, City=Bangalore, Zipcode=560100}
Id= 4, Name= Jack, Salary= 400.0, {Address= AddressLine1= City Centre, City=New Delhi, Zipcode=100100}
Hibernate 本机 SQL 实体和连接
我们还可以使用addEntity()
和addJoin()
方法通过表连接从关联表中获取数据。例如,上面的数据也可以按如下方式检索。
//Join example with addEntity and addJoin
query = session.createSQLQuery("select {e.*}, {a.*} from Employee e join Address a ON e.emp_id=a.emp_id")
.addEntity("e",Employee.class)
.addJoin("a","e.address");
rows = query.list();
for (Object[] row : rows) {
for(Object obj : row) {
System.out.print(obj + "::");
}
System.out.println("\n");
}
//Above join returns both Employee and Address Objects in the array
for (Object[] row : rows) {
Employee e = (Employee) row[0];
System.out.println("Employee Info::"+e);
Address a = (Address) row[1];
System.out.println("Address Info::"+a);
}
{[aliasname].*}
用于返回实体的所有属性。当我们使用addEntity()
和addJoin()
连接查询(如上所示)时,它会返回两个对象,如上所示。上述代码产生的输出如下所示。
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
Id= 1, Name= Pankaj, Salary= 100.0, {Address= AddressLine1= Albany Dr, City=San Jose, Zipcode=95129}::AddressLine1= Albany Dr, City=San Jose, Zipcode=95129::
Id= 2, Name= David, Salary= 200.0, {Address= AddressLine1= Arques Ave, City=Santa Clara, Zipcode=95051}::AddressLine1= Arques Ave, City=Santa Clara, Zipcode=95051::
Id= 3, Name= Lisa, Salary= 300.0, {Address= AddressLine1= BTM 1st Stage, City=Bangalore, Zipcode=560100}::AddressLine1= BTM 1st Stage, City=Bangalore, Zipcode=560100::
Id= 4, Name= Jack, Salary= 400.0, {Address= AddressLine1= City Centre, City=New Delhi, Zipcode=100100}::AddressLine1= City Centre, City=New Delhi, Zipcode=100100::
Employee Info::Id= 1, Name= Pankaj, 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= Jack, Salary= 400.0, {Address= AddressLine1= City Centre, City=New Delhi, Zipcode=100100}
Address Info::AddressLine1= City Centre, City=New Delhi, Zipcode=100100
您可以在 mysql 客户端中运行这两个查询,并注意到产生的输出是相同的。
mysql> 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;
+--------------+----------------+----------------+--------------+----------------+-------------+---------------+
| emp_id1_1_0_ | emp_name2_1_0_ | emp_sala3_1_0_ | emp_id1_0_1_ | address_2_0_1_ | city3_0_1_ | zipcode4_0_1_ |
+--------------+----------------+----------------+--------------+----------------+-------------+---------------+
| 1 | Pankaj | 100 | 1 | Albany Dr | San Jose | 95129 |
| 2 | David | 200 | 2 | Arques Ave | Santa Clara | 95051 |
| 3 | Lisa | 300 | 3 | BTM 1st Stage | Bangalore | 560100 |
| 4 | Jack | 400 | 4 | City Centre | New Delhi | 100100 |
+--------------+----------------+----------------+--------------+----------------+-------------+---------------+
4 rows in set (0.00 sec)
mysql> select e.emp_id, emp_name, emp_salary,address_line1, city, zipcode from Employee e, Address a where a.emp_id=e.emp_id;
+--------+----------+------------+---------------+-------------+---------+
| emp_id | emp_name | emp_salary | address_line1 | city | zipcode |
+--------+----------+------------+---------------+-------------+---------+
| 1 | Pankaj | 100 | Albany Dr | San Jose | 95129 |
| 2 | David | 200 | Arques Ave | Santa Clara | 95051 |
| 3 | Lisa | 300 | BTM 1st Stage | Bangalore | 560100 |
| 4 | Jack | 400 | City Centre | New Delhi | 100100 |
+--------+----------+------------+---------------+-------------+---------+
4 rows in set (0.00 sec)
mysql>
带参数的 Hibernate 本机 SQL 查询
我们还可以向 Hibernate SQL 查询传递参数,就像JDBC PreparedStatement一样。可以使用名称和索引设置参数,如下例所示。
query = session
.createSQLQuery("select emp_id, emp_name, emp_salary from Employee where emp_id = ?");
List<Object[]> empData = query.setLong(0, 1L).list();
for (Object[] row : empData) {
Employee emp = new Employee();
emp.setId(Long.parseLong(row[0].toString()));
emp.setName(row[1].toString());
emp.setSalary(Double.parseDouble(row[2].toString()));
System.out.println(emp);
}
query = session
.createSQLQuery("select emp_id, emp_name, emp_salary from Employee where emp_id = :id");
empData = query.setLong("id", 2L).list();
for (Object[] row : empData) {
Employee emp = new Employee();
emp.setId(Long.parseLong(row[0].toString()));
emp.setName(row[1].toString());
emp.setSalary(Double.parseDouble(row[2].toString()));
System.out.println(emp);
}
上述代码产生的输出为:
Hibernate: select emp_id, emp_name, emp_salary from Employee where emp_id = ?
Id= 1, Name= Pankaj, Salary= 100.0, {Address= null}
Hibernate: select emp_id, emp_name, emp_salary from Employee where emp_id = ?
Id= 2, Name= David, Salary= 200.0, {Address= null}
以上就是对 Hibernate SQL 查询的简单介绍,除非您想执行任何特定于数据库的查询,否则应该避免使用它。