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