**
spring-data-jpa对与@Query运行机制
**
我们可以使用@Query注解符给Repository中的方法加入自定义sql,使得方法能按照我们自己想要的方式搜索或修改数据。
关于这个@Query的注解符我们可以看到有一个参数nativeQuery默认值为false,当nativeQuery为false时我们需要给value一个Hql(Hibernate Query Language),当nativeQuery为true时我们需要给value一个Sql。
下面来看一下nativeQuery的true和false会在运行中有什么不同
- org.springframework.data.jpa.repository.query.JpaQueryFactory
JpaQueryFactory是一个enum,他负责生成JpaQuery类,他的内部有这样几个方法
@Nullable
AbstractJpaQuery fromQueryAnnotation(JpaQueryMethod method, EntityManager em,
QueryMethodEvaluationContextProvider evaluationContextProvider) {
LOG.debug("Looking up query for method {}", method.getName());
return fromMethodWithQueryString(method, em, method.getAnnotatedQuery(), evaluationContextProvider);
}
@Nullable
AbstractJpaQuery fromMethodWithQueryString(JpaQueryMethod method, EntityManager em, @Nullable String queryString,
QueryMethodEvaluationContextProvider evaluationContextProvider) {
if (queryString == null) {
return null;
}
return method.isNativeQuery() ? new NativeJpaQuery(method, em, queryString, evaluationContextProvider, PARSER)
: new SimpleJpaQuery(method, em, queryString, evaluationContextProvider, PARSER);
}
@Nullable
public StoredProcedureJpaQuery fromProcedureAnnotation(JpaQueryMethod method, EntityManager em) {
if (!method.isProcedureQuery()) {
return null;
}
return new StoredProcedureJpaQuery(method, em);
}
这些方法被org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy的resolveQuery调用来生成JapQuery
可以看到,当我们的使用了@Query注解符以后,会使用fromQueryAnnotation方法来生成,JpaQuery,而fromQueryAnnotation又调用了fromMethodWithQueryString方法,在fromMethodWithQueryString方法中更具method.isNativeQuery()来生成JpaQuery,而这个method.isNativeQuery(),正是获取了注解符中nativeQuery的值(默认是false),也就是说当nativeQuery为true的时候这个三元表达式会返回NativeJapQuery否则返回SimpleJpaQuery
- NativeJpaQuery 和 SimpleJpaQuery
这两个JpaQuery 都继承了AbstractStringBasedJpaQuery类不同的是NativeJpaQuery重写了AbstractStringBasedJpaQuery里面的createJpaQuery方法。
@Override
protected Query createJpaQuery(String queryString, ReturnedType returnedType) {
EntityManager em = getEntityManager();
Class<?> type = getTypeToQueryFor(returnedType);
return type == null ? em.createNativeQuery(queryString) : em.createNativeQuery(queryString, type);
}
可以看到createJpaQuery方法返回的是EntityManager.createNativeQuery方法,这个方法是hibernate自己实现的。
再看AbstractStringBasedJpaQuery的createJpaQuery方法
protected Query createJpaQuery(String queryString, ReturnedType returnedType) {
EntityManager em = getEntityManager();
if (this.query.hasConstructorExpression() || this.query.isDefaultProjection()) {
return em.createQuery(queryS