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

我检查了Javadoc here并发现描述相似,只是createNamedQuery接受本机sql(有单独的方法createNativeQuery,getNamedNativeQuery,getNamedSQLQuery来创建本机查询)。

我想了解是否还有其他根本差异使我的查询更快/更慢。

getNamedQuery:

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

createNamedQuery:

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

最佳答案

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

您的发言很好,因为这些方法的javadoc应该几乎相同,而它们却有所不同。

Query getNamedQuery(String queryName);
为命名查询创建查询实例。

参数:

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



Query createNamedQuery(String name);
JPA定义的命名查询创建方法。这种形式可以代表
HQL / JPQL查询或本机查询。

参数:

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

它给人的感觉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 + "]" ) );
}

我们可以看到那里的getNamedQuery()可以自己执行buildQueryFromName()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 + "]" ) );
}

为了解释这两种看似不必要的重复的方法的存在,您必须注意createNamedQuery()来自Persistence API(更具体地说是EntityManager接口),而getNamedQuery()是Hibernate特定的方法(仅在org.hibernate.Session接口中定义)。
在早期的Hibernate版本中定义了getNamedQuery()方法。例如,Hibernate 3.0(2005年发布)已经做到了。
The specification ( JPA )于2009年发布,因此在Hibernate之后,
不一定保留所有的Hibernate方法/类。
而不良的重复方法(以及在实现过程中可以看到的处理过程中)。

07-24 15:24