3.1 简介
我想谈的另一个有用的东西是NativeQuery。如您所知,使用 NativeQuery,您可以使用本机 SQL 编写查询。然而,更有趣的是,您不必在获取查询结果时使用类映射。
我宁愿给你看一个例子:
List<Object[]> persons = session.createNativeQuery("SELECT * FROM Person").list();
在这个例子中,我们没有传递匹配查询结果行的类,而是我们只使用一个 Object 对象数组。
如果您只想选择表中的几列,这会很有用。例子:
List<Object[]> persons = session.createNativeQuery("SELECT id, name FROM Person").list();
for(Object[] person : persons) {
Number id = (Number) person[0];
String name = (String) person[1];
}
当您获取 ResultSet 对象并从其行中读取数据时,这有点类似于 JDBC 方法。
然而,Hibernate 提供了不同的方法来使它更可靠。例如,您可以指定要减去的列的类型。例子:
Query<Object[]> query = session.createNativeQuery("SELECT id, name FROM Person");
query.addScalar("id", StandardBasicTypes.LONG);
query.addScalar("name", StandardBasicTypes.STRING);
List<Object[]> persons = query.list();
for(Object[] person : persons) {
Long id = (Long) person[0];
String name = (String) person[1];
}
3.2 实体映射
您还可以显式指定 Hibernate 在解析NativeQuery的结果时应该使用的类。这可以通过不同的方式完成。
Query<Person> query = session.createNativeQuery("SELECT * FROM Person")
.addEntity(Person.class);
.list();
当然,您知道的好旧格式:
Query<Person> query = session.createNativeQuery("SELECT * FROM Person", Person.class).list();
第一种方法是本机 Hibernate 方法,第二种是 JPA 方法。JPA 方法更方便和简洁,因为这个标准是在 Hibernate 存在多年之后发明的。Hibernate 不断发展并被迫支持旧方法以保持与其旧版本的兼容性。
顺便说一句,由于它的方法,Hibernate 允许您将多个类连接到查询结果映射,而不是一个类。例子:
List<Phone> results = session.createNativeQuery(
"SELECT {ph.*}, {pr.*}" +
"FROM Phone ph" +
"JOIN Person pr ON ph.person_id = pr.id")
.addEntity("ph", Phone.class)
.addJoin("pr", "ph.person")
.list();
for (Phone. phone : results) {
assertNotNull( phone.getPerson().getName() );
}
这种使用NativeQuery 的方法可用于加快从数据库中选择数据的速度。如果您知道不需要某些列,则可以在请求中将它们省略。
您还可以一次加载所有子实体,即使 Hibernate 想要使用Cache或LazyLoading机制。此外,您的子实体在数据库中可能有很多列,您只能选择其中的一部分。
3.3 DTO映射
Hibernate 还允许您使用非实体类来映射结果。没有任何注释且未映射到任何表的类。
例子:
public class PersonSummaryDTO {
private Number id;
private String name;
public Number getId() {
return id;
}
public void setId(Number id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
List<PersonSummaryDTO> dtos = session.createNativeQuery(
"SELECT p.id as \"id\", p.name as \"name\" FROM Person p")
.setResultTransformer(Transformers.aliasToBean(PersonSummaryDTO.class) )
.list();
由于 PersonSummaryDTO 类中没有注释,因此 SQL 查询中的列名称必须与 PersonSummaryDTO 类的字段名称完全匹配。
如果您正在从您的应用程序仅以只读模式连接到的外部数据库读取数据,这将非常有用。也就是说,您可以访问包含 50 多个列的表,它们以非规范化形式存储数据以加快选择速度。
或者假设有人决定将类层次结构存储在一张表中,五年后这张表增长得如此之大以至于魔鬼会打断他的腿。您需要从此表中选择几列(Id 和用户名)并将它们提供给客户端。
我想你明白了,但如果你想更深入地研究这个话题,你可以在链接上阅读更多内容:
GO TO FULL VERSION