Hibernate.org社区文档

第 10 章. 本地查询

10.1. 表达结果集
10.2. 使用本地 SQL 查询
10.3. 命名查询

您也可以使用数据库的本地 SQL 方言表达查询。如果您想利用数据库特定的功能,例如查询提示或 Oracle 中的 CONNECT BY 选项,这将很有用。它还提供了一条从直接 SQL/JDBC 应用程序迁移到 Hibernate 的清晰路径。请注意,Hibernate 允许您为所有创建、更新、删除和加载操作指定手写 SQL(包括存储过程)(有关更多信息,请参阅参考指南。)

要使用 SQL 查询,您需要描述 SQL 结果集,此描述将帮助 EntityManager 将您的列映射到实体属性。这是使用 @SqlResultSetMapping 注解完成的。每个 @SqlResultSetMapping 都有一个名称,在 EntityManager 上创建 SQL 查询时使用。

@SqlResultSetMapping(name="GetNightAndArea", entities={

    @EntityResult(name="org.hibernate.test.annotations.query.Night", fields = {
        @FieldResult(name="id", column="nid"),
        @FieldResult(name="duration", column="night_duration"),
        @FieldResult(name="date", column="night_date"),
        @FieldResult(name="area", column="area_id")
    }),
    @EntityResult(name="org.hibernate.test.annotations.query.Area", fields = {
        @FieldResult(name="id", column="aid"),
        @FieldResult(name="name", column="name")
    })
    }
)
//or
@SqlResultSetMapping(name="defaultSpaceShip", entities=@EntityResult(name="org.hibernate.test.annotations.query.SpaceShip"))

您还可以定义标量结果,甚至混合实体结果和标量结果

@SqlResultSetMapping(name="ScalarAndEntities",

    entities={
        @EntityResult(name="org.hibernate.test.annotations.query.Night", fields = {
            @FieldResult(name="id", column="nid"),
            @FieldResult(name="duration", column="night_duration"),
            @FieldResult(name="date", column="night_date"),
            @FieldResult(name="area", column="area_id")
        }),
        @EntityResult(name="org.hibernate.test.annotations.query.Area", fields = {
            @FieldResult(name="id", column="aid"),
            @FieldResult(name="name", column="name")
        })
    },
    columns={
        @ColumnResult(name="durationInSec")
    }
)

然后 SQL 查询必须返回一个名为 durationInSec 的列别名。

有关 @SqlResultSetMapping 的更多信息,请参阅 Hibernate 注解参考指南。

待办事项:这听起来像是重复...

现在结果集已经描述完毕,我们能够执行本地 SQL 查询。 EntityManager 提供了所有必要的 API。第一个方法是使用 SQL 结果集名称进行绑定,第二个方法使用实体默认映射(返回的列必须与元数据中使用的列名称相同)。第三个方法(Hibernate 实体管理器尚不支持)返回纯标量结果。

String sqlQuery = "select night.id nid, night.night_duration, night.night_date, area.id aid, "

    + "night.area_id, area.name from Night night, Area area where night.area_id = area.id "
    + "and night.night_duration >= ?";
Query q = entityManager.createNativeQuery(sqlQuery, "GetNightAndArea");
q.setParameter( 1, expectedDuration );
q.getResultList();

此本地查询基于 GetNightAndArea 结果集返回夜晚和区域。

String sqlQuery = "select * from tbl_spaceship where owner = ?";

Query q = entityManager.createNativeQuery(sqlQuery, SpaceShip.class);
q.setParameter( 1, "Han" );
q.getResultList();

第二种版本在您的 SQL 查询返回一个实体并重用与元数据中映射的列相同的列时很有用。

本地命名查询与 JP-QL 命名查询共享相同的调用 API。您的代码不需要知道两者之间的区别。这对从 SQL 迁移到 JP-QL 非常有用。

Query q = entityManager.createNamedQuery("getSeasonByNativeQuery");

q.setParameter( 1, name );
Season season = (Season) q.getSingleResult();