我正在使用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方法/类。
而不良的重复方法(以及在实现过程中可以看到的处理过程中)。