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 + "]" ) );
}
我们可以看到 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 方法/类。
而不受欢迎的重复方法(以及我们在其实现中看到的处理过程中)。