为什么要使用Hibernate Query的addScalar方法?

3

我有一个本地SQL的查询,类似于:

SQLQuery query = session.createSQLQuery("select emp_id, emp_name, emp_salary from Employee");

查询结果可以用于设置员工对象。类似的,我有一个带有addscalar(entity_colname)的相同查询。

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());

在这里,我们也必须以类似的方式获得结果,那么使用addscalar的优点是什么呢?

祝好, Jay


如果您正在处理大量数据,则它可以提高性能。它们都返回对象数组。 - ganeshvjy
哪个函数可以帮助你将对象转换为指定类型? - Rookie007
1个回答

1

当你不需要使用addScalar

在你的例子中,你实际上不需要使用addScalar

如果你将响应映射到一个DTO,就像下面的EmployeeDTO

public class EmployeeDTO {
    private final Long id;
    private final String name;
    private final Double salary;

    public EmployeeDTO(Long id, String name, Double salary) {
        this.id = id;
        this.name = name;
        this.salary = salary;
    }

    public Long getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public Double getSalary() {
        return salary;
    }
}

那么,接下来的 SQL 查询可以很好地获取 EmployeeDTO

List<EmployeeDTO> employeeDTOs = entityManager.createNativeQuery("""
    SELECT
       emp_id AS id,
       emp_name AS name,
       emp_salary AS salary
    FROM employee
    """)
.getResultList();

请注意,我们使用了列别名,这样Hibernate就可以匹配我们想要设置的DTO属性。
当您需要添加标量时,
假设您有一个具有JSON“属性”属性的“Book”实体:
@Entity(name = "Book")
@Table(name = "book")
@TypeDef(typeClass = JsonNodeBinaryType.class, defaultForType = JsonNode.class)
public static class Book {

    @Id
    @GeneratedValue
    private Long id;

    @NaturalId
    private String isbn;

    @Column(columnDefinition = "jsonb")
    private JsonNode properties;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getIsbn() {
        return isbn;
    }

    public void setIsbn(String isbn) {
        this.isbn = isbn;
    }

    public JsonNode getProperties() {
        return properties;
    }

    public void setProperties(JsonNode properties) {
        this.properties = properties;
    }
}

JsonNodeBinaryType 是由 Hypersistence Utils 开源项目提供的。

现在,当执行一个原生 SQL 查询来获取 JSON properties 列时:

JsonNode properties = (JsonNode) entityManagercreateNativeQuery("""
    SELECT properties
    FROM book
    WHERE isbn = :isbn
    """)
.setParameter("isbn", "978-9730228236")
.getSingleResult();

Hibernate 抛出以下异常:
org.hibernate.MappingException: No Dialect mapping for JDBC type: 1111

这是因为Hibernate不知道如何将jsonb列转换为JsonNode Java对象,因为它缺少Hibernate本地JSON Type

但如果我们调用addScalar并提供Hibernate的Type

JsonNode properties = (JsonNode) entityManager.createNativeQuery("""
    SELECT properties
    FROM book
    WHERE isbn = :isbn
    """)
.setParameter("isbn", "978-9730228236")
.unwrap(org.hibernate.query.NativeQuery.class)
.addScalar("properties", JsonNodeBinaryType.INSTANCE)
.getSingleResult();

然后查询就会正常运行!

这可以使用 addentity 完成,但是 addscalar 提供了什么优势? - jayendra bhatt
只有解析参数类型的微小优势。但实际上,setParameter 的效果同样好,这种优势只是微不足道的。 - Vlad Mihalcea
@VladMihalcea 在迁移到 Hibernate 6 后,.addScalar("properties", JsonNodeBinaryType.INSTANCE) 不再起作用了,我也尝试过 .addScalar("properties", new JsonType(JsonNode.class))。但是我收到错误消息:无法解析方法 addScalar(String, JsonType),我正在使用 hibernate-types-60:2.21.1。是否存在其他解决方案? - Mançaux Pierre-Alexandre
@MançauxPierre-Alexandre 当前库版本为3.4.1,而您正在使用2.2.1。正如此测试用例所示,addScalar方法完全正常。 - Vlad Mihalcea
@MançauxPierre-Alexandre 项目名称已于2022年12月更改,因为该项目的范围远远超出了仅仅是Hibernate Types。 - Vlad Mihalcea
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接