1. Overview
1.概述
In this quick tutorial, we’ll discuss the addScalar() method used in Hibernate with the help of an example. We’ll learn how to use the method and the benefits of using it.
在这个快速教程中,我们将借助一个例子讨论Hibernate中使用的addScalar()方法。我们将学习如何使用该方法以及使用该方法的好处。
2. What Problem Does addScalar() Solve?
2.addScalar()解决的是什么问题?
Normally, when fetching results in Hibernate using native SQL query, we use the createNativeQuery() method, followed by the list() method:
通常,在Hibernate中使用本地SQL查询获取结果时,我们使用createNativeQuery() 方法,然后是 list() 方法。
session.createNativeQuery("SELECT * FROM Student student")
.list();
In this case, Hibernate uses ResultSetMetadata to find column details and returns the list of Object arrays.
在这种情况下,Hibernate使用ResultSetMetadata来查找列的详细信息,并返回Object数组的列表。
But, excessive use of ResultSetMetadata may result in poor performance, and this is where the addScalar() method is useful.
但是,过度使用ResultSetMetadata可能会导致性能不佳,而这正是addScalar()方法的作用所在。
By using addScalar() method, we can prevent Hibernate from using ResultSetMetadata.
通过使用addScalar()方法,我们可以防止Hibernate使用ResultSetMetadata。
3. How to Use addScalar()?
3.如何使用addScalar()?
Let’s create a new method to fetch a list of students using the addScalar() method:
让我们创建一个新的方法,使用 addScalar()方法获取一个学生列表。
public List<Object[]> fetchColumnWithScalar() {
return session.createNativeQuery("SELECT * FROM Student student")
.addScalar("studentId", StandardBasicTypes.LONG)
.addScalar("name", StandardBasicTypes.STRING)
.addScalar("age", StandardBasicTypes.INTEGER)
.list();
}
Here, we need to specify the column name and its data type as arguments to the addScalar() method.
这里,我们需要指定列名和它的数据类型作为addScalar()方法的参数。
Now, Hibernate won’t use ResultSetMetadata to get column details as we’re defining it upfront in addScalar(). Therefore, we’ll get better performance as compared to the previous approach.
现在,Hibernate将不会使用ResultSetMetadata来获取列的详细信息,因为我们在addScalar()中预先定义了它。因此,与之前的方法相比,我们将获得更好的性能。
4. Other Advantages
4.其他优势
Let’s see a few more use-cases where we can use the addScalar() method.
让我们再来看看我们可以使用 addScalar()方法的几个用例。
4.1. Limit Number of Columns
4.1.列数限制
We can also use the addScalar() method to limit the number of columns returned by our query.
我们还可以使用 addScalar()方法来限制我们的查询所返回的列的数量。
Let’s write another method fetchLimitedColumnWithScalar() to fetch only student name column:
让我们再写一个方法fetchLimitedColumnWithScalar(),只获取学生姓名列。
public List<String> fetchLimitedColumnWithScalar() {
return session.createNativeQuery("SELECT * FROM Student student")
.addScalar("name", StandardBasicTypes.STRING)
.list();
}
Here, we’ve used an asterisk in our query to fetch a List of students:
在这里,我们在查询中使用星号来获取一个List的学生。
SELECT * FROM Student student
But, it will not fetch all the columns and only returns a single column name in the List because we’ve only specified a single column in the addScalar() method.
但是,它不会获取所有的列,只在List 中返回一个单列name,因为我们在addScalar()方法中只指定了一个单列。
Let’s create a JUnit method to verify the column returned by the fetchLimitedColumnWithScalar() method:
让我们创建一个JUnit方法来验证由fetchLimitedColumnWithScalar()方法返回的列。
List<String> list = scalarExample.fetchLimitedColumnWithScalar();
for (String colValue : list) {
assertTrue(colValue.startsWith("John"));
}
As we can see, this will return the List of strings instead of the Object arrays. Also, in our sample data, we’ve kept all student names starting with “John” and that’s why we are asserting columns value against it in the unit test above.
我们可以看到,这将返回字符串的List,而不是Object数组。另外,在我们的样本数据中,我们保留了所有以 “John “开头的学生名字,这就是为什么我们在上面的单元测试中对它进行列值断言。
This makes our code more explicit in terms of what it’s returning.
这使得我们的代码在返回内容方面更加明确。
4.2. Return Single Scalar Value
4.2.返回单一标量值
We can also use the addScalar() method to return directly a single scalar value instead of lists.
我们还可以使用addScalar()方法来直接返回一个单一的标量值,而不是列表。
Let’s create a method that returns the average age of all students:
让我们创建一个方法,返回所有学生的平均年龄。
public Integer fetchAvgAgeWithScalar() {
return (Integer) session.createNativeQuery("SELECT AVG(age) as avgAge FROM Student student")
.addScalar("avgAge")
.uniqueResult();
}
Now, let’s verify the same with a unit-test method:
现在,让我们用单元测试的方法来验证一下:
Integer avgAge = scalarExample.fetchAvgAgeWithScalar();
assertEquals(true, (avgAge >= 5 && avgAge <= 24));
As we can see, the fetchAvgAgeScalar() method directly returns the Integer value, and we are asserting it.
我们可以看到,fetchAvgAgeScalar()方法直接返回Integer值,并且我们正在断言它。
In our sample data, we’ve provided random ages of students between 5 to 24 age. Hence, during assertion, we are expecting the average to be between 5 and 24.
在我们的样本数据中,我们已经提供了5至24岁之间的随机学生年龄。因此,在断言期间,我们预计平均年龄在5至24岁之间。
Similarly, we can use any other aggregate functions in SQL to directly get count, max, min, sum, or any other single scalar values directly using the addScalar() method.
同样,我们可以使用SQL中的任何其他聚合函数,直接使用count、max、min、sum或任何其他单标量值,直接使用addScalar()方法。
5. Overloaded addScalar() Method
5.重载的addScalar() 方法
We also have an overloaded addScalar() method, and it accepts only a column name as its single argument.
我们还有一个重载的addScalar()方法,它只接受一个列名作为其单一参数。
Let’s create a new method and use the overloaded addScalar() method, which fetches the “age“ column without specifying its type:
让我们创建一个新的方法,并使用重载的addScalar()方法,该方法获取“age“列而不指定其类型。
public List<Object[]> fetchWithOverloadedScalar() {
return session.createNativeQuery("SELECT * FROM Student student")
.addScalar("name", StandardBasicTypes.STRING)
.addScalar("age")
.list();
}
Now, let’s write another JUnit method to verify if our method is returning two or more columns:
现在,让我们再写一个JUnit方法来验证我们的方法是否返回两列或多列。
List<Object[]> list = scalarExample.fetchColumnWithOverloadedScalar();
for (Object[] colArray : list) {
assertEquals(2, colArray.length);
}
As we can see, this returns a List of Object arrays, and the size of the array is two, which represents the name and age columns in the list.
我们可以看到,这将返回一个List的Object数组,数组的大小为2,代表列表中的姓名和年龄列。
6. Conclusion
6.结语
In this article, we’ve seen the uses of the addScalar() method in Hibernate, how to use it and when to use it, along with an example.
在这篇文章中,我们已经看到了Hibernate中addScalar()方法的用途,如何使用它,何时使用它,并附有一个例子。
As always, the code for these examples is available over on GitHub.
像往常一样,这些例子的代码可以在GitHub上找到over。