Hibernate’s addScalar() Method – Hibernate的addScalar()方法

最后修改: 2022年 2月 19日

1. Overview


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.


2. What Problem Does addScalar() Solve?


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")

In this case, Hibernate uses ResultSetMetadata to find column details and returns the list of Object arrays.


But, excessive use of ResultSetMetadata may result in poor performance, and this is where the addScalar() method is useful.


By using addScalar() method, we can prevent Hibernate from using ResultSetMetadata.


3. How to Use 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)

Here, we need to specify the column name and its data type as arguments to the addScalar() method.


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.


4. Other Advantages


Let’s see a few more use-cases where we can use the addScalar() method.

让我们再来看看我们可以使用 addScalar()方法的几个用例。

4.1. Limit Number of Columns


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:


public List<String> fetchLimitedColumnWithScalar() {
    return session.createNativeQuery("SELECT * FROM Student student")
      .addScalar("name", StandardBasicTypes.STRING)

Here, we’ve used an asterisk in our query to fetch a List of students:


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:


List<String> list = scalarExample.fetchLimitedColumnWithScalar();
for (String colValue : list) {

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


We can also use the addScalar() method to return directly a single scalar value instead of lists.


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")

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.


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.


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.


5. Overloaded addScalar() Method

5.重载的addScalar() 方法

We also have an overloaded addScalar() method, and it accepts only a column name as its single argument.


Let’s create a new method and use the overloaded addScalar() method, which fetches the age column without specifying its type:


public List<Object[]> fetchWithOverloadedScalar() {
    return session.createNativeQuery("SELECT * FROM Student student")
      .addScalar("name", StandardBasicTypes.STRING)

Now, let’s write another JUnit method to verify if our method is returning two or more columns:


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.


6. Conclusion


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.


As always, the code for these examples is available over on GitHub.