为啥要使用 Hibernate Query addScalar 方法?

Posted

技术标签:

【中文标题】为啥要使用 Hibernate Query addScalar 方法?【英文标题】:Why to use the Hibernate Query addScalar method?为什么要使用 Hibernate Query addScalar 方法? 【发布时间】:2015-06-22 03:19:22 【问题描述】:

我在本机 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有什么好处呢?

问候 周杰伦

【问题讨论】:

如果您正在处理大量数据,它会提高性能。两者都返回 Object 数组。 你帮助你从对象转换为我们指定的类型.. 【参考方案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 properties 属性的 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;
    

JsonNodeBinaryTypehibernate-types 开源项目提供。

现在,当执行获取 JSON properties 列的本机 SQL 查询时:

JsonNode properties = (JsonNode) entityManager
.createNativeQuery(
    "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-native 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有什么优势呢? 解析参数类型只有一点优势。但优势只是微不足道的,因为实际上 setParameter 的效果也一样好。

以上是关于为啥要使用 Hibernate Query addScalar 方法?的主要内容,如果未能解决你的问题,请参考以下文章

为啥要在hibernate中使用关联?

hibernate工作原理及为啥要用

为啥要在缓存中获取 EclipseLink JPA query.getResultList() 结果的正确原因是啥?

hibernate的update及JDBC数据库批量操作

hibernate的update及JDBC数据库批量操作

Hibernate其它API