休眠会话的 getNamedQuery(String name) 和 createNamedQuery(String name) 有什么区别?

sha*_*ulk 5 java hibernate jpa

我正在使用 Spring 和 Hibernate 开发应用程序。我想知道为什么有两个单独的方法 getNamedQuery(String name) 和 createNamedQuery(String name)。

在这里检查了 Javadoc ,发现除了 createNamedQuery 接受本机 sql 之外,描述是相似的(有单独的方法 createNativeQuery、getNamedNativeQuery、getNamedSQLQuery 来创建本机查询)。

我想了解是否有任何其他根本区别使我的查询更快/更慢。

获取命名查询:

Query getNamedQuery(String queryName) 为命名查询创建一个 Query 实例。参数: queryName - 预定义的命名查询的名称返回: 用于操作和执行的查询实例抛出: IllegalArgumentException - 如果未使用给定名称定义查询或发现查询字符串无效

创建命名查询:

Query createNamedQuery(String name) JPA 定义的命名查询创建方法。这种形式可以表示 HQL/JPQL 查询或本机查询。参数: name - 预定义的命名查询的名称返回: 用于操作和执行的查询实例抛出: IllegalArgumentException - 如果未使用给定名称定义查询或发现查询字符串无效另请参见: EntityManager.createNamedQuery(String)

dav*_*xxx 4

TL;DR
这两种方法执行(除了一些小事情之外)相同的处理:尝试使用几乎相同的逻辑执行命名的 JPQL 或 SQL 查询。


你的评论很好,因为这些方法的 javadoc 应该几乎相同,但它们有所不同。

Query getNamedQuery(String queryName);

为命名查询创建一个查询实例。

参数:

queryName预定义的命名查询的名称

Query createNamedQuery(String name);

JPA 定义的命名查询创建方法。此形式可以表示 HQL/JPQL 查询或本机查询。

参数

name预定义的命名查询的名称

它给人的感觉是getNamedQuery()可能不处理任何类型的查询。

对于此类问题,理解差异的最佳方法通常是研究方法实现。

这些方法的实现位于类中org.hibernate.internal.AbstractSharedSessionContract

我们可以在这里看到createNamedQuery()依赖于buildQueryFromName()

@Override
public QueryImplementor createNamedQuery(String name) {
    final QueryImplementor<Object> query = buildQueryFromName( name, null );
    query.getParameterMetadata().setOrdinalParametersZeroBased( false );
    return query;
}

protected  <T> QueryImplementor<T> buildQueryFromName(String name, Class<T> resultType) {
    checkOpen();
    checkTransactionSynchStatus();
    delayedAfterCompletion();

    // todo : apply stored setting at the JPA Query level too

    final NamedQueryDefinition namedQueryDefinition = getFactory().getNamedQueryRepository().getNamedQueryDefinition( name );
    if ( namedQueryDefinition != null ) {
        return createQuery( namedQueryDefinition, resultType );
    }

    final NamedSQLQueryDefinition nativeQueryDefinition = getFactory().getNamedQueryRepository().getNamedSQLQueryDefinition( name );
    if ( nativeQueryDefinition != null ) {
        return (QueryImplementor<T>) createNativeQuery( nativeQueryDefinition, resultType );
    }

    throw exceptionConverter.convert( new IllegalArgumentException( "No query defined for that name [" + name + "]" ) );
}
Run Code Online (Sandbox Code Playgroud)

我们可以看到getNamedQuery()它的表现与buildQueryFromName()for 的作用相同createNamedQuery()

@Override
public QueryImplementor getNamedQuery(String name) {
    checkOpen();
    checkTransactionSynchStatus();
    delayedAfterCompletion();

    // look as HQL/JPQL first
    final NamedQueryDefinition queryDefinition = factory.getNamedQueryRepository().getNamedQueryDefinition( name );
    if ( queryDefinition != null ) {
        return createQuery( queryDefinition );
    }

    // then as a native query
    final NamedSQLQueryDefinition nativeQueryDefinition = factory.getNamedQueryRepository().getNamedSQLQueryDefinition( name );
    if ( nativeQueryDefinition != null ) {
        return createNativeQuery( nativeQueryDefinition, true );
    }

    throw exceptionConverter.convert( new IllegalArgumentException( "No query defined for that name [" + name + "]" ) );
}
Run Code Online (Sandbox Code Playgroud)

为了解释这两个看起来不合需要的重复方法的存在,您必须意识到它们createNamedQuery()来自 Persistence API(EntityManager更具体地说是接口),而getNamedQuery()是 Hibernate 特定方法(仅在org.hibernate.Session接口中定义)。
方法getNamedQuery()是在非常早期的 Hibernate 版本中定义的。
例如 Hibernate 3.0(2005 年发布)就已经具备了这一点。
该规范(JPA于 2009 年发布,因此在 Hibernate 之后,不一定保留所有 Hibernate 方法/类。
而不受欢迎的重复方法(以及我们在其实现中看到的处理过程中)。