hibernate session的getNamedQuery(String name)和createNamedQuery(String name)有什么区别?

问题描述 投票:4回答:1

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

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

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

getNamedQuery:

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

createNamedQuery:

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

java hibernate jpa
1个回答
1
投票

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


你的评论很好,因为这些方法的javadoc应该几乎相同,而这些方法不同。

Query getNamedQuery(String queryName);

为命名查询创建Query实例。

参数:

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接口中定义)。 getNamedQuery()方法是在很早的Hibernate版本中定义的。 例如,Hibernate 3.0(2005年发布)就已经有了。 The specification (JPA)于2009年发布,因此在Hibernate之后,并不一定保留所有Hibernate方法/类。 而不受欢迎的重复方法(以及我们在其实现中可以看到的处理)。

© www.soinside.com 2019 - 2024. All rights reserved.