Hibernate|Hibernate5.4用户指南(十五)之HQL和JPQL

Hibernate5.4官方用户指南

1 架构

……

14 拦截器和事件

15 HQL和JPQL

Hibernate查询语言(HQL)和Java持久化查询语言(JPQL)都是以对象模型为查询对象的语言,与SQL类似。JPQL是HQL的子集。
HQL和JPQL都是非类型安全的方法来执行查询操作。Criteria查询提供了一种类型安全的查询方法。

15.1 领域模型示例

15.2 查询API

Hibernate的Session接口继承了JPA的EntityManager接口。
Hibernate的Query接口继承了JPA的Query接口。

15.2.1 JPA查询API

1 获取JPA的Query或TypedQuery

Query query = entityManager.createQuery(
	"select p " +
	"from Person p " +
	"where p.name like :name"
);

TypedQuery typedQuery = entityManager.createQuery(
	"select p " +
	"from Person p " +
	"where p.name like :name"
	// createQuery第二个参数实体类类型
	, Person.class
);

2 获取命名查询的 JPA的Query或TypedQuery

@NamedQuery(
    name = "get_person_by_name",
    query = "select p from Person p where name = :name"
)

Query query = entityManager.createNamedQuery( "get_person_by_name" );

TypedQuery typedQuery = entityManager.createNamedQuery(
	"get_person_by_name", Person.class
);

3 获取命名查询的 Hibernate的Query或TypedQuery
Hibernate提供了一个@NamedQuery注解,@NamedQuery注解提供了配置各种查询功能的方法,如:刷新模式、可缓存性、超时。

@NamedQueries({
    @NamedQuery(
        name = "get_phone_by_number",
        query = "select p " +
                "from Phone p " +
                "where p.number = :number",
        timeout = 1,
        readOnly = true
    )
})

Phone phone = entityManager
	.createNamedQuery( "get_phone_by_number", Phone.class )
	.setParameter( "number", "123-456-7890" )
	.getSingleResult();

4 基本的JPA的Query用法
Query接口可用于控制查询的执行(类似Hibern提供的@NamedQuery注解的功能),如:指定超时、控制缓存以下:

  • javax.persistence.query.timeout
  • javax.persistence.fetchgraph
  • javax.persistence.loadgraph
  • org.hibernate.cacheMode
  • org.hibernate.cacheable
  • org.hibernate.cacheRegion
  • org.hibernate.comment
  • org.hibernate.fetchSize
  • org.hibernate.flushMode
  • org.hibernate.readOnly
Query query = entityManager.createQuery(
	"select p " +
	"from Person p " +
	"where p.name like :name" )
// timeout - in milliseconds
.setHint( "javax.persistence.query.timeout", 2000 )
// flush only at commit time
.setFlushMode( FlushModeType.COMMIT );

5 执行查询前,最后一步是绑定一定义参数的值。
JPA名称参数绑定:

Query query = entityManager.createQuery(
	"select p " +
	"from Person p " +
	"where p.name like :name" )
.setParameter( "name", "J%" );

// For generic temporal field types (e.g. `java.util.Date`, `java.util.Calendar`)
// we also need to provide the associated `TemporalType`
Query query = entityManager.createQuery(
	"select p " +
	"from Person p " +
	"where p.createdOn > :timestamp" )
.setParameter( "timestamp", timestamp, TemporalType.DATE );

JPA位置参数绑定:

Query query = entityManager.createQuery(
	"select p " +
	"from Person p " +
	"where p.name like ?1" )
.setParameter( 1, "J%" );

6 JPA提供了两种方法检索结果集

  • Query.getResultList() - 执行select查询并返回结果列表。
List persons = entityManager.createQuery(
	"select p " +
	"from Person p " +
	"where p.name like :name" )
.setParameter( "name", "J%" )
.getResultList();
  • Query.getSingleResult() - 执行select查询并返回单个结果。如果有多个结果,则抛出异常。
Person person = (Person) entityManager.createQuery(
	"select p " +
	"from Person p " +
	"where p.name like :name" )
.setParameter( "name", "J%" )
.getSingleResult();

15.2.2 Hibernate查询API

HQL查询表示从Hibernate的Query获得Session。若HQL是命名查询,则使用getNamedQuery获取Session;或者使用createQuery查询。

1 获取Hibernate Query

org.hibernate.query.Query query = session.createQuery(
	"select p " +
	"from Person p " +
	"where p.name like :name"
);

2 获取命名查询的 Hibernate Query

org.hibernate.query.Query query = session.getNamedQuery( "get_person_by_name" );

3 Hibernate基本查询用法

org.hibernate.query.Query query = session.createQuery(
	"select p " +
	"from Person p " +
	"where p.name like :name" )
// timeout - in seconds
.setTimeout( 2 )
// write to L2 caches, but do not read from them
.setCacheMode( CacheMode.REFRESH )
// assuming query cache was enabled for the SessionFactory
.setCacheable( true )
// add a comment to the generated SQL if enabled via the hibernate.use_sql_comments configuration property
.setComment( "+ INDEX(p idx_person_name)" );

4 Hibernate名称参数绑定

org.hibernate.query.Query query = session.createQuery(
	"select p " +
	"from Person p " +
	"where p.name like :name" )
	// StringType.INSTANCE
.setParameter( "name", "J%", StringType.INSTANCE );

5 Hibernate名称参数绑定(推断类型)

org.hibernate.query.Query query = session.createQuery(
	"select p " +
	"from Person p " +
	"where p.name like :name" )
.setParameter( "name", "J%" );

6 Hibernate名称参数绑定(简写形式)

org.hibernate.query.Query query = session.createQuery(
	"select p " +
	"from Person p " +
	"where p.name like :name " +
	"  and p.createdOn > :timestamp" )
.setParameter( "name", "J%" )
.setParameter( "timestamp", timestamp, TemporalType.TIMESTAMP);

7 Hibernate提供两种最常用方法检索结果集

  • Query.list(),执行查询并返回结果列表。
List persons = session.createQuery(
	"select p " +
	"from Person p " +
	"where p.name like :name" )
.setParameter( "name", "J%" )
.list();
  • Query.uniqueResult(),执行查询并返回单一结果,若结果多于一个则抛出异常。
Person person = (Person) session.createQuery(
	"select p " +
	"from Person p " +
	"where p.name like :name" )
.setParameter( "name", "J%" )
.uniqueResult();

15.2.3 滚动查询-Query scroll

hibernate提供了用于使用服务器端游标滚动查询和处理结果。
Query.scroll()返回一个org.hibernate.ScrollableResults,ScrollableResults可以对ResultSet结果集任何方向(前、后)导航滚动。

1 滚动ResultSet包含的实体

try ( ScrollableResults scrollableResults = session.createQuery(
		"select p " +
		"from Person p " +
		"where p.name like :name" )
		.setParameter( "name", "J%" )
		.scroll()
) {
	while(scrollableResults.next()) {
		Person person = (Person) scrollableResults.get()[0];
		process(person);
	}
}

2 Hibernate支持Query.iterate()
当已知加载的条目已经存储在二级缓存中时,它用于加载实体。迭代背后的想法是只在SQL查询中获得匹配的标识符。通过二级缓存查找,可以从中解析标识符。如果这些二级缓存查找失败,则需要针对数据库发出其他查询。

15.3 区分大小写-Case Sensitivity

除了Java类和属性的名称外,查询不区分大小写。

15.4 语句类型

HQL和JPQL都允许执行:SELECT、UPDATE、DELETE语句。
HQL允许执行INSERT语句。

注意:何时执行UPDATE、DELETE语句?
执行批量更新或删除操作时,可能导致数据库与活动持久性上下文中的实体间出现不一致。通常,批量更新或删除应该只在新持久化上下文中的事务内执行,或者在获取或访问其状态可能受此操作影响的实体之前执行。

15.5 查询语句

你可能感兴趣的:(TODO,Hibernate)