当你不需要使用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();
然后查询就会正常运行!