Spring Data JPA系列
2、Spring Data JPA Criteria查询、部分字段查询
3、Spring Data JPA数据批量插入、批量更新真的用对了吗
4、Spring Data JPA的一对一、LazyInitializationException异常、一对多、多对多操作
5、Spring Data JPA自定义Id生成策略、复合主键配置、Auditing使用
6、【源码】Spring Data JPA原理解析之Repository的自动注入(一)
7、【源码】Spring Data JPA原理解析之Repository的自动注入(二)
8、【源码】Spring Data JPA原理解析之Repository执行过程及SimpleJpaRepository源码
9、【源码】Spring Data JPA原理解析之Repository自定义方法命名规则执行原理(一)
前言
在第一篇博文
中介绍了JPA的基本使用,在Repository接口中有三大类方法,分别为:
1)继承于JpaRepositoryImplementation接口,自动实现了CRUD等方法。
2)自定义接口方法,通过方法命名规则,无需写SQL或HQL,实现数据库表的操作。
3)自定义接口方法,通过@Query注解,添加SQL或HQL,实现数据库表的操作。
针对第一类,前一篇博文从源码的角度分享了自定义Repository实现JpaRepositoryImplementation接口后自动实现了CRUD等方法的实现原理。
在上面这篇博文中分享了Repository bean的创建。Respository的bean是一个通过ProxyFactory创建的动态代理对象,该代理对象添加了QueryExecutorMethodInterceptor拦截器。Repository中的自定义接口方法都是在QueryExecutorMethodInterceptor中实现的。
QueryExecutorMethodInterceptor
QueryExecutorMethodInterceptor实现了MethodInterceptor,实现了方法拦截功能。在QueryExecutorMethodInterceptor的构造方法中,通过查询查找策略解析Repository中的自定义方法。QueryExecutorMethodInterceptor的代码如下:
package org.springframework.data.repository.core.support;
/**
* 此MethodInterceptor拦截对自定义实现的方法的调用,当自定义的方法被调用时,会被该类拦截。
* 此外,它还解析对finder的方法调用,并触发它们的执行。如果返回true,则可以依赖于设置自定义存储库实现实例。
*/
class QueryExecutorMethodInterceptor implements MethodInterceptor {
// Repository信息,为DefaultRepositoryInformation对象。获取Repository信息,getRepositoryInformation()返回一个RepositoryInformation对象。
// 如子类JpaRepositoryFactory,指定baseClass为SimpleJpaRepository.class
private final RepositoryInformation repositoryInformation;
// 方法缓存,key为方法,value为对应方法的查询解析信息
private final Map<Method, RepositoryQuery> queries;
// 方法调用缓存,key为方法,value为对应方法调用时要执行的执行器
private final Map<Method, RepositoryMethodInvoker> invocationMetadataCache = new ConcurrentReferenceHashMap<>();
// 查询执行结果处理器
private final QueryExecutionResultHandler resultHandler;
// 在实体类中添加@NamedQueries注解,配置相关查询信息,默认为空
private final NamedQueries namedQueries;
private final List<QueryCreationListener<?>> queryPostProcessors;
private final RepositoryInvocationMulticaster invocationMulticaster;
/**
* Creates a new {@link QueryExecutorMethodInterceptor}. Builds a model of {@link QueryMethod}s to be invoked on
* execution of repository interface methods.
*/
public QueryExecutorMethodInterceptor(RepositoryInformation repositoryInformation,
ProjectionFactory projectionFactory, Optional<QueryLookupStrategy> queryLookupStrategy, NamedQueries namedQueries,
List<QueryCreationListener<?>> queryPostProcessors,
List<RepositoryMethodInvocationListener> methodInvocationListeners) {
this.repositoryInformation = repositoryInformation;
// 需要在实体类中添加@NamedQueries注解,配置相关查询信息
this.namedQueries = namedQueries;
// 默认的监听器:RepositoryFactorySupport$QueryCollectingQueryCreationListener
this.queryPostProcessors = queryPostProcessors;
// methodInvocationListeners默认为空
this.invocationMulticaster = methodInvocationListeners.isEmpty() ? NoOpRepositoryInvocationMulticaster.INSTANCE
: new DefaultRepositoryInvocationMulticaster(methodInvocationListeners);
// 查询执行结果处理器
this.resultHandler = new QueryExecutionResultHandler(RepositoryFactorySupport.CONVERSION_SERVICE);
if (!queryLookupStrategy.isPresent() && repositoryInformation.hasQueryMethods()) {
throw new IllegalStateException(
"You have defined query methods in the repository" + " but do not have any query lookup strategy defined."
+ " The infrastructure apparently does not support query methods");
}
// queryLookupStrategy为JpaQueryLookupStrategy对象
this.queries = queryLookupStrategy //
.map(it -> mapMethodsToQuery(repositoryInformation, it, projectionFactory)) //
.orElse(Collections.emptyMap());
}
private Map<Method, RepositoryQuery> mapMethodsToQuery(RepositoryInformation repositoryInformation,
QueryLookupStrategy lookupStrategy, ProjectionFactory projectionFactory) {
Map<Method, RepositoryQuery> result = new HashMap<>();
// 遍历自定义Repository中定义的查询方法
for (Method method : repositoryInformation.getQueryMethods()) {
// 根据lookupStrategy(查找策略,JpaQueryLookupStrategy&CreateIfNotFoundQueryLookupStrategy对象)查询RepositoryQuery,并保存到Pair中
Pair<Method, RepositoryQuery> pair = lookupQuery(method, repositoryInformation, lookupStrategy,
projectionFactory);
// 为RepositoryQuery添加监听
invokeListeners(pair.getSecond());
// 加入到Map中
result.put(pair.getFirst(), pair.getSecond());
}
return result;
}
private Pair<Method, RepositoryQuery> lookupQuery(Method method, RepositoryInformation information,
QueryLookupStrategy strategy, ProjectionFactory projectionFactory) {
try {
// 根据lookupStrategy(查找策略)查询RepositoryQuery
return Pair.of(method, strategy.resolveQuery(method, information, projectionFactory, namedQueries));
} catch (QueryCreationException e) {
throw e;
} catch (RuntimeException e) {
throw QueryCreationException.create(e.getMessage(), e, information.getRepositoryInterface(), method);
}
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private void invokeListeners(RepositoryQuery query) {
// 默认的监听器:RepositoryFactorySupport$QueryCollectingQueryCreationListener
for (QueryCreationListener listener : queryPostProcessors) {
// 可解析类型
ResolvableType typeArgument = ResolvableType.forClass(QueryCreationListener.class, listener.getClass())
.getGeneric(0);
if (typeArgument != null && typeArgument.isAssignableFrom(ResolvableType.forClass(query.getClass()))) {
// RepositoryFactorySupport$QueryCollectingQueryCreationListener将查询对应的QueryMethod添加到集合中
listener.onCreation(query);
}
}
}
@Override
@Nullable
public Object invoke(@SuppressWarnings("null") MethodInvocation invocation) throws Throwable {
Method method = invocation.getMethod();
// 通过返回的返回值,获取执行适配器,默认都为null
QueryExecutionConverters.ExecutionAdapter executionAdapter = QueryExecutionConverters //
.getExecutionAdapter(method.getReturnType());
if (executionAdapter == null) {
return resultHandler.postProcessInvocationResult(doInvoke(invocation), method);
}
return executionAdapter //
.apply(() -> resultHandler.postProcessInvocationResult(doInvoke(invocation), method));
}
@Nullable
private Object doInvoke(MethodInvocation invocation) throws Throwable {
Method method = invocation.getMethod();
// 判断方法是否存在RepositoryQuery。在构造函数中,会解析Repository中的查询方法,并缓存到Map
if (hasQueryFor(method)) {
RepositoryMethodInvoker invocationMetadata = invocationMetadataCache.get(method);
if (invocationMetadata == null) {
// 首次执行对应方法,先创建一个RepositoryQueryMethodInvoker对象,保存方法即方法对应的RepositoryQuery
invocationMetadata = RepositoryMethodInvoker.forRepositoryQuery(method, queries.get(method));
// 加入缓存
invocationMetadataCache.put(method, invocationMetadata);
}
// 获取方法所在的Repository类名、方法的参数值【invocation.getArguments()】,执行RepositoryQueryMethodInvoker.invoke()方法
return invocationMetadata.invoke(repositoryInformation.getRepositoryInterface(), invocationMulticaster,
invocation.getArguments());
}
// 如果能够处理该查询方法,则不执行invocation.proceed(),即结束拦截器链
return invocation.proceed();
}
/**
* 判断是否为给定方法执行查询
*/
private boolean hasQueryFor(Method method) {
return queries.containsKey(method);
}
}
CreateIfNotFoundQueryLookupStrategy
在构造方法中,查询查找策略queryLookupStrategy是一个JpaQueryLookupStrategy.CreateIfNotFoundQueryLookupStrategy对象。
在Repository对应的BeanDefinitionBuilder.build()获取Repository的BeanDefinitionBuilder【用于创建BeanDefinition对象】时,会执行RepositoryConfiguration.getQueryLookupStrategyKey()方法,获取查找策略。默认的实现类DefaultRepositoryConfiguration.getQueryLookupStrategyKey()方法默认返回Key.CREATE_IF_NOT_FOUND。
在JpaRepositoryFactory.getRepository()时,调用getQueryLookupStrategy()方法,使用JpaQueryLookupStrategy.create()创建QueryLookupStrategy对象。返回CreateIfNotFoundQueryLookupStrategy。然后new QueryExecutorMethodInterceptor(),传入该查找策略
在loopupQuery()方法中,执行QueryLookupStrategy.resolveQuery(),即CreateIfNotFoundQueryLookupStrategy.resolveQuery(),解析方法,获得RepositoryQuery对象。
package org.springframework.data.jpa.repository.query;
/**
* JPA的查询查找策略。
* 在create()方法中,根据Key,创建一个QueryLookupStrategy,再通过QueryLookupStrategy,
* 获取一个可以处理对应方法的RepositoryQuery。
*/
public final class JpaQueryLookupStrategy {
private static final Log LOG = LogFactory.getLog(JpaQueryLookupStrategy.class);
private static final RepositoryQuery NO_QUERY = new NoQuery();
private JpaQueryLookupStrategy() {}
/**
* 需要访问EntityManager的QueryLookupStrategy实现的基类
*/
private abstract static class AbstractQueryLookupStrategy implements QueryLookupStrategy {
private final EntityManager em;
// 用于创建对应查询方法的JpaQueryMethod对象
private final JpaQueryMethodFactory queryMethodFactory;
// 查询语句重写提供者。可以重新修改sql语句
private final QueryRewriterProvider queryRewriterProvider;
public AbstractQueryLookupStrategy(EntityManager em, JpaQueryMethodFactory queryMethodFactory,
QueryRewriterProvider queryRewriterProvider) {
Assert.notNull(em, "EntityManager must not be null");
Assert.notNull(queryMethodFactory, "JpaQueryMethodFactory must not be null");
this.em = em;
this.queryMethodFactory = queryMethodFactory;
this.queryRewriterProvider = queryRewriterProvider;
}
@Override
public final RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata, ProjectionFactory factory,
NamedQueries namedQueries) {
// 先创建一个JpaQueryMethod
JpaQueryMethod queryMethod = queryMethodFactory.build(method, metadata, factory);
// 执行抽象方法,解析查询,获得一个RepositoryQuery
return resolveQuery(queryMethod, queryRewriterProvider.getQueryRewriter(queryMethod), em, namedQueries);
}
protected abstract RepositoryQuery resolveQuery(JpaQueryMethod method, QueryRewriter queryRewriter,
EntityManager em, NamedQueries namedQueries);
}
/**
* 返回一个PartTreeJpaQuery的RepositoryQuery对象
*/
private static class CreateQueryLookupStrategy extends AbstractQueryLookupStrategy {
private final EscapeCharacter escape;
public CreateQueryLookupStrategy(EntityManager em, JpaQueryMethodFactory queryMethodFactory,
QueryRewriterProvider queryRewriterProvider, EscapeCharacter escape) {
super(em, queryMethodFactory, queryRewriterProvider);
this.escape = escape;
}
@Override
protected RepositoryQuery resolveQuery(JpaQueryMethod method, QueryRewriter queryRewriter, EntityManager em,
NamedQueries namedQueries) {
return new PartTreeJpaQuery(method, em, escape);
}
}
/**
* 根据@Query中是否带nativeQuery属性值,返回NativeJpaQuery,或SimpleJpaQuery。如果没有配置value和name,则返回NamedQuery
*/
private static class DeclaredQueryLookupStrategy extends AbstractQueryLookupStrategy {
// ExtensionAwareQueryMethodEvaluationContextProvider对象
private final QueryMethodEvaluationContextProvider evaluationContextProvider;
public DeclaredQueryLookupStrategy(EntityManager em, JpaQueryMethodFactory queryMethodFactory,
QueryMethodEvaluationContextProvider evaluationContextProvider, QueryRewriterProvider queryRewriterProvider) {
super(em, queryMethodFactory, queryRewriterProvider);
this.evaluationContextProvider = evaluationContextProvider;
}
@Override
protected RepositoryQuery resolveQuery(JpaQueryMethod method, QueryRewriter queryRewriter, EntityManager em,
NamedQueries namedQueries) {
if (method.isProcedureQuery()) {
return JpaQueryFactory.INSTANCE.fromProcedureAnnotation(method, em);
}
// 如果@Query设置了value属性值,即有数据库执行语句
if (StringUtils.hasText(method.getAnnotatedQuery())) {
if (method.hasAnnotatedQueryName()) {
LOG.warn(String.format(
"Query method %s is annotated with both, a query and a query name; Using the declared query", method));
}
// 如果方法的语句为native原生SQL,则创建NativeJpaQuery,否则创建SimpleJpaQuery
// method.getRequiredAnnotatedQuery():获取@Query注解的value属性值,即查询语句
return JpaQueryFactory.INSTANCE.fromMethodWithQueryString(method, em, method.getRequiredAnnotatedQuery(),
getCountQuery(method, namedQueries, em), queryRewriter, evaluationContextProvider);
}
// 获取@Query设置的name属性值
String name = method.getNamedQueryName();
// 包含在nameQueries中,如果方法的语句为native原生SQL,则创建NativeJpaQuery,否则创建SimpleJpaQuery
if (namedQueries.hasQuery(name)) {
return JpaQueryFactory.INSTANCE.fromMethodWithQueryString(method, em, namedQueries.getQuery(name),
getCountQuery(method, namedQueries, em), queryRewriter, evaluationContextProvider);
}
RepositoryQuery query = NamedQuery.lookupFrom(method, em);
return query != null //
? query //
: NO_QUERY;
}
@Nullable
private String getCountQuery(JpaQueryMethod method, NamedQueries namedQueries, EntityManager em) {
// 如果方法的@Query添加了countQuery属性值,返回属性值
if (StringUtils.hasText(method.getCountQuery())) {
return method.getCountQuery();
}
// 获取queryName。因为没有添加countQuery属性,所以返回如:UserEntity.searchByName.count。searchByName为方法名称
String queryName = method.getNamedCountQueryName();
if (!StringUtils.hasText(queryName)) {
return method.getCountQuery();
}
if (namedQueries.hasQuery(queryName)) {
return namedQueries.getQuery(queryName);
}
// 是否通过@NamedQuires,尝试通过EntityManager.createNamedQuery()执行,不存在返回null
boolean namedQuery = NamedQuery.hasNamedQuery(em, queryName);
if (namedQuery) {
return method.getQueryExtractor().extractQueryString(em.createNamedQuery(queryName));
}
return null;
}
}
/**
* 先构造方法传入的DeclaredQueryLookupStrategy获取RepositoryQuery【详见DeclaredQueryLookupStrategy定义】,
* 如果没有找到,则使用构造方法传入的CreateQueryLookupStrategy获取PartTreeJpaQuery
*/
private static class CreateIfNotFoundQueryLookupStrategy extends AbstractQueryLookupStrategy {
private final DeclaredQueryLookupStrategy lookupStrategy;
private final CreateQueryLookupStrategy createStrategy;
public CreateIfNotFoundQueryLookupStrategy(EntityManager em, JpaQueryMethodFactory queryMethodFactory,
CreateQueryLookupStrategy createStrategy, DeclaredQueryLookupStrategy lookupStrategy,
QueryRewriterProvider queryRewriterProvider) {
super(em, queryMethodFactory, queryRewriterProvider);
Assert.notNull(createStrategy, "CreateQueryLookupStrategy must not be null");
Assert.notNull(lookupStrategy, "DeclaredQueryLookupStrategy must not be null");
this.createStrategy = createStrategy;
this.lookupStrategy = lookupStrategy;
}
@Override
protected RepositoryQuery resolveQuery(JpaQueryMethod method, QueryRewriter queryRewriter, EntityManager em,
NamedQueries namedQueries) {
// 先执行DeclaredQueryLookupStrategy的resolveQuery()
RepositoryQuery lookupQuery = lookupStrategy.resolveQuery(method, queryRewriter, em, namedQueries);
if (lookupQuery != NO_QUERY) {
return lookupQuery;
}
// 没找到,执行CreateQueryLookupStrategy的resolveQuery()
return createStrategy.resolveQuery(method, queryRewriter, em, namedQueries);
}
}
/**
* 通过给定的EntityManager和Key,创建QueryLookupStrategy查询策略
*/
public static QueryLookupStrategy create(EntityManager em, JpaQueryMethodFactory queryMethodFactory,
@Nullable Key key, QueryMethodEvaluationContextProvider evaluationContextProvider,
QueryRewriterProvider queryRewriterProvider, EscapeCharacter escape) {
Assert.notNull(em, "EntityManager must not be null");
Assert.notNull(evaluationContextProvider, "EvaluationContextProvider must not be null");
switch (key != null ? key : Key.CREATE_IF_NOT_FOUND) {
case CREATE:
return new CreateQueryLookupStrategy(em, queryMethodFactory, queryRewriterProvider, escape);
case USE_DECLARED_QUERY:
return new DeclaredQueryLookupStrategy(em, queryMethodFactory, evaluationContextProvider,
queryRewriterProvider);
case CREATE_IF_NOT_FOUND:
return new CreateIfNotFoundQueryLookupStrategy(em, queryMethodFactory,
new CreateQueryLookupStrategy(em, queryMethodFactory, queryRewriterProvider, escape),
new DeclaredQueryLookupStrategy(em, queryMethodFactory, evaluationContextProvider, queryRewriterProvider),
queryRewriterProvider);
default:
throw new IllegalArgumentException(String.format("Unsupported query lookup strategy %s", key));
}
}
/**
* 没有查询
*/
static class NoQuery implements RepositoryQuery {
@Override
public Object execute(Object[] parameters) {
throw new IllegalStateException("NoQuery should not be executed!");
}
@Override
public QueryMethod getQueryMethod() {
throw new IllegalStateException("NoQuery does not have a QueryMethod!");
}
}
}
在CreateIfNotFoundQueryLookupStrategy.resolveQuery()方法中,执行如下:
1)先执行DeclaredQueryLookupStrategy的resolveQuery(),解析方法的@Query注解,根据注解的信息,如果是原生的,返回NativeJpaQuery;如果不是原生,返回SimpleJpaQuery;如果没有@Query注解,返回null;
2)如果1)中返回null,则执行CreateQueryLookupStrategy的resolveQuery(),new一个PartTreeJpaQuery对象,并返回该对象;
对于Repository方法命名规则实现的数据库表查询,因为没有添加@Query,所以返回的是PartTreeJpaQuery对象。获取的PartTreeJpaQuery对象和Method,添加到queries中进行缓存。
PartTreeJpaQuery
PartTreeJpaQuery保存了方法信息,包括方法、方法参数、方法名称解析后的Part树、对应的查询query、查询计数countQuery等信息,构造方法如下:
public class PartTreeJpaQuery extends AbstractJpaQuery {
PartTreeJpaQuery(JpaQueryMethod method, EntityManager em, EscapeCharacter escape) {
super(method, em);
this.em = em;
this.escape = escape;
// 获取方法的参数,包括方法的实际参数,分页、排序在参数中的下标等
this.parameters = method.getParameters();
// 获取Repository<T, ID>中的T
Class<?> domainClass = method.getEntityInformation().getJavaType();
PersistenceUnitUtil persistenceUnitUtil = em.getEntityManagerFactory().getPersistenceUnitUtil();
this.entityInformation = new JpaMetamodelEntityInformation<>(domainClass, em.getMetamodel(), persistenceUnitUtil);
boolean recreationRequired = parameters.hasDynamicProjection() || parameters.potentiallySortsDynamically()
|| method.isScrollQuery();
try {
// 解析方法名称。分解出名称中findBy、exist等关键字、属性、查询关键字【Like、In等】,根据Or分隔、再按And分隔
this.tree = new PartTree(method.getName(), domainClass);
validate(tree, parameters, method.toString());
// 类JpaCountQueryCreator重写了complete()方法,执行query.select(),select为builder.count(),
// 并加上predicate条件信息
this.countQuery = new CountQueryPreparer(recreationRequired);
// 如果是计算的查询,则query和countQuery一样
this.query = tree.isCountProjection() ? countQuery : new QueryPreparer(recreationRequired);
} catch (Exception o_O) {
throw new IllegalArgumentException(
String.format("Failed to create query for method %s; %s", method, o_O.getMessage()), o_O);
}
}
// 省略其他
}
在构造方法中,完成如下:
1)创建一个PartTree,该对象解析方法名称,分解名称中的执行关键字【findBy、exist等】、属性、查询关键字【Like、In等】。先根据Or分隔,再根据And分隔;
2)创建对应方法的countQuery和query,将解析出的查询的基础信息封装在QueryPreparer对象中,根据解析出的查询信息,创建CriteriaQuery对象;
2.1 PartTree
PartTree的源码如下:
package org.springframework.data.repository.query.parser;
public class PartTree implements Streamable<OrPart> {
private static final String KEYWORD_TEMPLATE = "(%s)(?=(\\p{Lu}|\\P{InBASIC_LATIN}))";
private static final String QUERY_PATTERN = "find|read|get|query|search|stream";
private static final String COUNT_PATTERN = "count";
private static final String EXISTS_PATTERN = "exists";
private static final String DELETE_PATTERN = "delete|remove";
// ^(find|read|get|query|search|stream|count|exists|delete|remove)((\p{Lu}.*?))??By
private static final Pattern PREFIX_TEMPLATE = Pattern.compile( //
"^(" + QUERY_PATTERN + "|" + COUNT_PATTERN + "|" + EXISTS_PATTERN + "|" + DELETE_PATTERN + ")((\\p{Lu}.*?))??By");
// 如"findDistinctUserByNameOrderByAge"方法名称,则subject为"DistinctUser"
private final Subject subject;
/**
* Predicate解析方法名中的属性信息、属性类型、关键字【Like、IN等】【先按Or分隔、再按And分隔】、排序信息。
* 如findDistinctUserByNameOrderByAge方法,则predicate包含name、orderByAge、name的属性等信息
*/
private final Predicate predicate;
/**
* @param source Repository中定义的方法的名称
* @param domainClass Repository<T, ID>中的T
*/
public PartTree(String source, Class<?> domainClass) {
Assert.notNull(source, "Source must not be null");
Assert.notNull(domainClass, "Domain class must not be null");
// Kotlin name mangling, @JvmName cannot be used with interfaces
// Kotlin名称篡改,@JvmName不能与接口一起使用
int dash = source.indexOf('-');
if (dash > -1) {
source = source.substring(0, dash);
}
// ^(find|read|get|query|search|stream|count|exists|delete|remove)((\p{Lu}.*?))??By
Matcher matcher = PREFIX_TEMPLATE.matcher(source);
if (!matcher.find()) {
this.subject = new Subject(Optional.empty());
this.predicate = new Predicate(source, domainClass);
} else {
// 查找满足条件的字符串。如findBy、readBy等,创建一个Subject对象
this.subject = new Subject(Optional.of(matcher.group(0)));
// source.substring(matcher.group().length()):获取除findBy等名称中的其他字符串。如findByIdBetween,则为IdBetween
// 创建Predicate,解析方法名中的谓词。解析属性部分(实体类中的属性)、排序部分
this.predicate = new Predicate(source.substring(matcher.group().length()), domainClass);
}
}
public Iterator<OrPart> iterator() {
return predicate.iterator();
}
public Sort getSort() {
return predicate.getOrderBySource().toSort();
}
public boolean isDistinct() {
return subject.isDistinct();
}
public boolean isCountProjection() {
return subject.isCountProjection();
}
/**
* 返回是否应用现有投影
*/
public boolean isExistsProjection() {
return subject.isExistsProjection();
}
public boolean isDelete() {
return subject.isDelete();
}
public boolean isLimiting() {
return getMaxResults() != null;
}
@Nullable
public Integer getMaxResults() {
return subject.getMaxResults().orElse(null);
}
public Limit getResultLimit() {
return subject.getMaxResults().map(Limit::of).orElse(Limit.unlimited());
}
public Streamable<Part> getParts() {
return flatMap(OrPart::stream);
}
public Streamable<Part> getParts(Type type) {
return getParts().filter(part -> part.getType().equals(type));
}
public boolean hasPredicate() {
return predicate.iterator().hasNext();
}
@Override
public String toString() {
return String.format("%s %s", StringUtils.collectionToDelimitedString(predicate.nodes, " or "),
predicate.getOrderBySource().toString()).trim();
}
/**
* 在给定的关键字keyword处拆分给定的文本text。期望驼峰格式大小写样式只匹配具体关键字,而不匹配其派生关键字。
*/
private static String[] split(String text, String keyword) {
Pattern pattern = Pattern.compile(String.format(KEYWORD_TEMPLATE, keyword));
return pattern.split(text);
}
/**
* 先按Or拆分,再按And拆分。OrPart存储了And的部分集合。如P1AndP2OrP3AndP4,则OrPart中的children为{P1、P2}或{P3、P4}
*/
public static class OrPart implements Streamable<Part> {
private final List<Part> children;
/**
* 先按Or拆分,再按And拆分
*/
OrPart(String source, Class<?> domainClass, boolean alwaysIgnoreCase) {
// 按And拆分
String[] split = split(source, "And");
this.children = Arrays.stream(split)//
.filter(StringUtils::hasText)//
.map(part -> new Part(part, domainClass, alwaysIgnoreCase))//
.collect(Collectors.toList());
}
public Iterator<Part> iterator() {
return children.iterator();
}
@Override
public String toString() {
return StringUtils.collectionToDelimitedString(children, " and ");
}
}
private static class Subject {
private static final String DISTINCT = "Distinct";
private static final Pattern COUNT_BY_TEMPLATE = Pattern.compile("^count(\\p{Lu}.*?)??By");
private static final Pattern EXISTS_BY_TEMPLATE = Pattern.compile("^(" + EXISTS_PATTERN + ")(\\p{Lu}.*?)??By");
private static final Pattern DELETE_BY_TEMPLATE = Pattern.compile("^(" + DELETE_PATTERN + ")(\\p{Lu}.*?)??By");
private static final String LIMITING_QUERY_PATTERN = "(First|Top)(\\d*)?";
// ^(find|read|get|query|search|stream)(Distinct)?(First|Top)(\d*)?(\p{Lu}.*?)??By
private static final Pattern LIMITED_QUERY_TEMPLATE = Pattern
.compile("^(" + QUERY_PATTERN + ")(" + DISTINCT + ")?" + LIMITING_QUERY_PATTERN + "(\\p{Lu}.*?)??By");
private final boolean distinct;
private final boolean count;
private final boolean exists;
private final boolean delete;
private final Optional<Integer> maxResults;
public Subject(Optional<String> subject) {
// 判断是否包含Distinct、count、exists、delete、
this.distinct = subject.map(it -> it.contains(DISTINCT)).orElse(false);
this.count = matches(subject, COUNT_BY_TEMPLATE);
this.exists = matches(subject, EXISTS_BY_TEMPLATE);
this.delete = matches(subject, DELETE_BY_TEMPLATE);
this.maxResults = returnMaxResultsIfFirstKSubjectOrNull(subject);
}
/**
* 返回第一个K主题为空时的最大结果
*/
private Optional<Integer> returnMaxResultsIfFirstKSubjectOrNull(Optional<String> subject) {
return subject.map(it -> {
// ^(find|read|get|query|search|stream)(Distinct)?(First|Top)(\d*)?(\p{Lu}.*?)??By
Matcher grp = LIMITED_QUERY_TEMPLATE.matcher(it);
// 传入findBy、countBy等,返回null
if (!grp.find()) {
return null;
}
return StringUtils.hasText(grp.group(4)) ? Integer.valueOf(grp.group(4)) : 1;
});
}
public boolean isDelete() {
return delete;
}
public boolean isCountProjection() {
return count;
}
public boolean isExistsProjection() {
return exists;
}
public boolean isDistinct() {
return distinct;
}
public Optional<Integer> getMaxResults() {
return maxResults;
}
private boolean matches(Optional<String> subject, Pattern pattern) {
return subject.map(it -> pattern.matcher(it).find()).orElse(false);
}
}
/**
* 解析方法名中的谓词。属性部分(实体类中的属性)、排序部分
*/
private static class Predicate implements Streamable<OrPart> {
private static final Pattern ALL_IGNORE_CASE = Pattern.compile("AllIgnor(ing|e)Case");
private static final String ORDER_BY = "OrderBy";
// 保存方法名中的属性部分。即实体类中的属性
private final List<OrPart> nodes;
// 保存方法名中的排序部分
private final OrderBySource orderBySource;
private boolean alwaysIgnoreCase;
public Predicate(String predicate, Class<?> domainClass) {
// 按OrderBy拆分
String[] parts = split(detectAndSetAllIgnoreCase(predicate), ORDER_BY);
if (parts.length > 2) {
throw new IllegalArgumentException("OrderBy must not be used more than once in a method name");
}
// 按Or切分,再按And切分。OrPart存储了And的部分集合。如P1AndP2OrP3AndP4,则OrPart中的children为{P1、P2}或{P3、P4}
this.nodes = Arrays.stream(split(parts[0], "Or")) //
.filter(StringUtils::hasText) //
.map(part -> new OrPart(part, domainClass, alwaysIgnoreCase)) //
.collect(Collectors.toList());
// 排序部分
this.orderBySource = parts.length == 2 ? new OrderBySource(parts[1], Optional.of(domainClass))
: OrderBySource.EMPTY;
}
/**
* 检测并设置所有忽略大小写
* @param predicate 方法名中除findBy等开头的其他字符串信息
*/
private String detectAndSetAllIgnoreCase(String predicate) {
// AllIgnor(ing|e)Case
Matcher matcher = ALL_IGNORE_CASE.matcher(predicate);
// 如果有包含,则删除对应字符串
if (matcher.find()) {
alwaysIgnoreCase = true;
predicate = predicate.substring(0, matcher.start()) + predicate.substring(matcher.end(), predicate.length());
}
return predicate;
}
public OrderBySource getOrderBySource() {
return orderBySource;
}
@Override
public Iterator<OrPart> iterator() {
return nodes.iterator();
}
}
}
在PartTree中,解析方法名称,分解出其中的subject以及predicate,即find、read等,以及属性、查询条件【Between、In等】、排序信息。其中的核心方法都做了注释。
2.2 QueryPreparer
QueryPreparer是PartTreeJpaQuery的内部类,代码如下:
public class PartTreeJpaQuery extends AbstractJpaQuery {
private class QueryPreparer {
private final @Nullable CriteriaQuery<?> cachedCriteriaQuery;
private final @Nullable ParameterBinder cachedParameterBinder;
private final QueryParameterSetter.QueryMetadataCache metadataCache = new QueryParameterSetter.QueryMetadataCache();
QueryPreparer(boolean recreateQueries) {
JpaQueryCreator creator = createCreator(null);
if (recreateQueries) {
this.cachedCriteriaQuery = null;
this.cachedParameterBinder = null;
} else {
// 子类CountQueryPreparer的createQuery(),执行JpaCountQueryCreator重写的complete()方法,
// 执行query.select(),select为builder.count(),并加上predicate条件信息
this.cachedCriteriaQuery = creator.createQuery();
this.cachedParameterBinder = getBinder(creator.getParameterExpressions());
}
}
/**
* 为查询创建一个Query,并调用query.setParameter()设置参数值及分页信息
*/
public Query createQuery(JpaParametersParameterAccessor accessor) {
CriteriaQuery<?> criteriaQuery = cachedCriteriaQuery;
ParameterBinder parameterBinder = cachedParameterBinder;
if (cachedCriteriaQuery == null || accessor.hasBindableNullValue()) {
JpaQueryCreator creator = createCreator(accessor);
criteriaQuery = creator.createQuery(getDynamicSort(accessor));
List<ParameterMetadata<?>> expressions = creator.getParameterExpressions();
parameterBinder = getBinder(expressions);
}
if (parameterBinder == null) {
throw new IllegalStateException("ParameterBinder is null");
}
// 通过EntityManager.createQuery(criteriaQuery),返回TypedQuery
TypedQuery<?> query = createQuery(criteriaQuery);
ScrollPosition scrollPosition = accessor.getParameters().hasScrollPositionParameter()
? accessor.getScrollPosition()
: null;
// 调用invokeBinding()执行query.setParameter()方法,设置查询的条件参数值,如果有分页,设置分页信息
// 如果有需要,设置返回最大值信息
return restrictMaxResultsIfNecessary(invokeBinding(parameterBinder, query, accessor, this.metadataCache),
scrollPosition);
}
@SuppressWarnings("ConstantConditions")
private Query restrictMaxResultsIfNecessary(Query query, @Nullable ScrollPosition scrollPosition) {
if (scrollPosition instanceof OffsetScrollPosition offset && !offset.isInitial()) {
query.setFirstResult(Math.toIntExact(offset.getOffset()) + 1);
}
if (tree.isLimiting()) {
if (query.getMaxResults() != Integer.MAX_VALUE) {
if (query.getMaxResults() > tree.getMaxResults() && query.getFirstResult() > 0) {
query.setFirstResult(query.getFirstResult() - (query.getMaxResults() - tree.getMaxResults()));
}
}
query.setMaxResults(tree.getMaxResults());
}
if (tree.isExistsProjection()) {
query.setMaxResults(1);
}
return query;
}
/**
* 通过EntityManager.createQuery(criteriaQuery),返回TypedQuery
*/
private TypedQuery<?> createQuery(CriteriaQuery<?> criteriaQuery) {
if (this.cachedCriteriaQuery != null) {
synchronized (this.cachedCriteriaQuery) {
return getEntityManager().createQuery(criteriaQuery);
}
}
return getEntityManager().createQuery(criteriaQuery);
}
protected JpaQueryCreator createCreator(@Nullable JpaParametersParameterAccessor accessor) {
EntityManager entityManager = getEntityManager();
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
ResultProcessor processor = getQueryMethod().getResultProcessor();
ParameterMetadataProvider provider;
ReturnedType returnedType;
if (accessor != null) {
provider = new ParameterMetadataProvider(builder, accessor, escape);
returnedType = processor.withDynamicProjection(accessor).getReturnedType();
} else {
provider = new ParameterMetadataProvider(builder, parameters, escape);
returnedType = processor.getReturnedType();
}
if (accessor != null && accessor.getScrollPosition() instanceof KeysetScrollPosition keyset) {
return new JpaKeysetScrollQueryCreator(tree, returnedType, builder, provider, entityInformation, keyset);
}
return new JpaQueryCreator(tree, returnedType, builder, provider);
}
/**
* 调用query.setParameter()方法,设置查询的条件参数值,如果有分页,设置分页信息
*/
protected Query invokeBinding(ParameterBinder binder, TypedQuery<?> query, JpaParametersParameterAccessor accessor,
QueryParameterSetter.QueryMetadataCache metadataCache) {
// 将query查询添加到缓存
QueryParameterSetter.QueryMetadata metadata = metadataCache.getMetadata("query", query);
return binder.bindAndPrepare(query, metadata, accessor);
}
private ParameterBinder getBinder(List<ParameterMetadata<?>> expressions) {
return ParameterBinderFactory.createCriteriaBinder(parameters, expressions);
}
private Sort getDynamicSort(JpaParametersParameterAccessor accessor) {
return parameters.potentiallySortsDynamically() //
? accessor.getSort() //
: Sort.unsorted();
}
}
private class CountQueryPreparer extends QueryPreparer {
CountQueryPreparer(boolean recreateQueries) {
super(recreateQueries);
}
/**
* 创建一个JpaCountQueryCreator
*/
@Override
protected JpaQueryCreator createCreator(@Nullable JpaParametersParameterAccessor accessor) {
EntityManager entityManager = getEntityManager();
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
ParameterMetadataProvider provider;
if (accessor != null) {
provider = new ParameterMetadataProvider(builder, accessor, escape);
} else {
provider = new ParameterMetadataProvider(builder, parameters, escape);
}
return new JpaCountQueryCreator(tree, getQueryMethod().getResultProcessor().getReturnedType(), builder, provider);
}
@Override
protected Query invokeBinding(ParameterBinder binder, TypedQuery<?> query, JpaParametersParameterAccessor accessor,
QueryParameterSetter.QueryMetadataCache metadataCache) {
QueryParameterSetter.QueryMetadata metadata = metadataCache.getMetadata("countquery", query);
return binder.bind(query, metadata, accessor);
}
}
}
在QueryPreparer的构造方法中,
1)执行createCreator()方法,创建一个JpaQueryCreator对象,如果是CountQueryPreparer,返回的是子类JpaCountQueryCreator对象;
2)调用JpaQueryCreator.createQuery,创建CriteriaQuery对象;
public abstract class AbstractQueryCreator<T, S> {
private final Optional<ParameterAccessor> parameters;
private final PartTree tree;
public T createQuery() {
return createQuery(parameters.map(ParameterAccessor::getSort) //
.orElse(Sort.unsorted()));
}
public T createQuery(Sort dynamicSort) {
Assert.notNull(dynamicSort, "DynamicSort must not be null");
return complete(createCriteria(tree), tree.getSort().and(dynamicSort));
}
/**
* 构建实际查询逻辑。遍历{@link PartTree}并调用回调方法来委托实际的条件创建和连接。
*/
@Nullable
private S createCriteria(PartTree tree) {
S base = null;
Iterator<Object> iterator = parameters.map(ParameterAccessor::iterator).orElse(Collections.emptyIterator());
// 遍历Or部分
for (PartTree.OrPart node : tree) {
Iterator<Part> parts = node.iterator();
if (!parts.hasNext()) {
throw new IllegalStateException(String.format("No part found in PartTree %s", tree));
}
// 创建criteria对象,并根据属性中的查询关键字,执行CriteriaBuilder.between()、CriteriaBuilder.greaterThan()等
S criteria = create(parts.next(), iterator);
// 遍历or中的and
while (parts.hasNext()) {
criteria = and(parts.next(), criteria, iterator);
}
base = base == null ? criteria : or(base, criteria);
}
return base;
}
/**
* 创建criteria对象的新原子实例
*/
protected abstract S create(Part part, Iterator<Object> iterator);
/**
* 完成CriteriaQuery的创建
*/
protected abstract T complete(@Nullable S criteria, Sort sort);
// 省略其他
}
createQuery()方法代码如上所示,该方法执行如下:
2.1)执行createCriteria()方法,根据方法名称解析后的PartTree,即查询的属性、关键字,调用create()抽象方法,创建一个Criteria API的Predicate对象。Criteria查询可以看
2.2)执行tree.getSort().and(dynamicSort),添加排序信息;
2.3)执行complete(),创建CriteriaQuery对象;
以上的create()以及complete()都是抽象方法,其实现在子类JpaQueryCreator。
2.2.1 JpaQueryCreator
JpaQueryCreator的核心代码如下:
public class JpaQueryCreator extends AbstractQueryCreator<CriteriaQuery<? extends Object>, Predicate> {
private final CriteriaBuilder builder;
private final Root<?> root;
private final CriteriaQuery<? extends Object> query;
private final ParameterMetadataProvider provider;
private final ReturnedType returnedType;
private final PartTree tree;
private final EscapeCharacter escape;
public JpaQueryCreator(PartTree tree, ReturnedType type, CriteriaBuilder builder,
ParameterMetadataProvider provider) {
super(tree);
this.tree = tree;
// 创建一个CriteriaQuery
CriteriaQuery<?> criteriaQuery = createCriteriaQuery(builder, type);
this.builder = builder;
this.query = criteriaQuery.distinct(tree.isDistinct() && !tree.isCountProjection());
// 设置root
this.root = query.from(type.getDomainType());
this.provider = provider;
this.returnedType = type;
this.escape = provider.getEscape();
}
protected CriteriaQuery<? extends Object> createCriteriaQuery(CriteriaBuilder builder, ReturnedType type) {
Class<?> typeToRead = tree.isDelete() ? type.getDomainType() : type.getTypeToRead();
return (typeToRead == null) || tree.isExistsProjection() //
? builder.createTupleQuery() //
: builder.createQuery(typeToRead);
}
@Override
protected Predicate create(Part part, Iterator<Object> iterator) {
return toPredicate(part, root);
}
@Override
protected final CriteriaQuery<? extends Object> complete(Predicate predicate, Sort sort) {
// 子类JpaCountQueryCreator重写了complete()方法,执行query.select(),select为builder.count(),
// 并加上predicate条件信息
return complete(predicate, sort, query, builder, root);
}
@SuppressWarnings({ "unchecked", "rawtypes" })
protected CriteriaQuery<? extends Object> complete(@Nullable Predicate predicate, Sort sort,
CriteriaQuery<? extends Object> query, CriteriaBuilder builder, Root<?> root) {
// 判断是否需要自定义构造
if (returnedType.needsCustomConstruction()) {
Collection<String> requiredSelection = getRequiredSelection(sort, returnedType);
List<Selection<?>> selections = new ArrayList<>();
for (String property : requiredSelection) {
PropertyPath path = PropertyPath.from(property, returnedType.getDomainType());
selections.add(toExpressionRecursively(root, path, true).alias(property));
}
Class<?> typeToRead = returnedType.getReturnedType();
query = typeToRead.isInterface() //
? query.multiselect(selections) //
: query.select((Selection) builder.construct(typeToRead, //
selections.toArray(new Selection[0])));
} else if (tree.isExistsProjection()) { // 是否应用现有投影
if (root.getModel().hasSingleIdAttribute()) {
SingularAttribute<?, ?> id = root.getModel().getId(root.getModel().getIdType().getJavaType());
query = query.multiselect(root.get((SingularAttribute) id).alias(id.getName()));
} else {
query = query.multiselect(root.getModel().getIdClassAttributes().stream()//
.map(it -> (Selection<?>) root.get((SingularAttribute) it).alias(it.getName()))
.collect(Collectors.toList()));
}
} else {
// 否则直接查询
query = query.select((Root) root);
}
// 添加排序
CriteriaQuery<? extends Object> select = query.orderBy(QueryUtils.toOrders(sort, root, builder));
// 添加条件
return predicate == null ? select : select.where(predicate);
}
/**
* 通过给定的Part【查询条件部分】创建Predicate对象
* @param part
* @param root
* @return
*/
private Predicate toPredicate(Part part, Root<?> root) {
return new PredicateBuilder(part, root).build();
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private class PredicateBuilder {
private final Part part;
private final Root<?> root;
public PredicateBuilder(Part part, Root<?> root) {
Assert.notNull(part, "Part must not be null");
Assert.notNull(root, "Root must not be null");
this.part = part;
this.root = root;
}
/**
* 基于Part创建JPA的Predicate对象
* @return
*/
public Predicate build() {
// PropertyPath保存查询条件中的属性的信息,如名称、类型、对应实体类等
PropertyPath property = part.getProperty();
Type type = part.getType();
switch (type) {
case BETWEEN:
ParameterMetadata<Comparable> first = provider.next(part);
ParameterMetadata<Comparable> second = provider.next(part);
return builder.between(getComparablePath(root, part), first.getExpression(), second.getExpression());
case AFTER:
case GREATER_THAN:
return builder.greaterThan(getComparablePath(root, part),
provider.next(part, Comparable.class).getExpression());
case GREATER_THAN_EQUAL:
return builder.greaterThanOrEqualTo(getComparablePath(root, part),
provider.next(part, Comparable.class).getExpression());
case BEFORE:
case LESS_THAN:
return builder.lessThan(getComparablePath(root, part), provider.next(part, Comparable.class).getExpression());
case LESS_THAN_EQUAL:
return builder.lessThanOrEqualTo(getComparablePath(root, part),
provider.next(part, Comparable.class).getExpression());
case IS_NULL:
return getTypedPath(root, part).isNull();
case IS_NOT_NULL:
return getTypedPath(root, part).isNotNull();
case NOT_IN:
// cast required for eclipselink workaround, see DATAJPA-433
return upperIfIgnoreCase(getTypedPath(root, part))
.in((Expression<Collection<?>>) provider.next(part, Collection.class).getExpression()).not();
case IN:
// cast required for eclipselink workaround, see DATAJPA-433
return upperIfIgnoreCase(getTypedPath(root, part))
.in((Expression<Collection<?>>) provider.next(part, Collection.class).getExpression());
case STARTING_WITH:
case ENDING_WITH:
case CONTAINING:
case NOT_CONTAINING:
if (property.getLeafProperty().isCollection()) {
Expression<Collection<Object>> propertyExpression = traversePath(root, property);
ParameterExpression<Object> parameterExpression = provider.next(part).getExpression();
// Can't just call .not() in case of negation as EclipseLink chokes on that.
return type.equals(NOT_CONTAINING) //
? isNotMember(builder, parameterExpression, propertyExpression) //
: isMember(builder, parameterExpression, propertyExpression);
}
case LIKE:
case NOT_LIKE:
Expression<String> stringPath = getTypedPath(root, part);
Expression<String> propertyExpression = upperIfIgnoreCase(stringPath);
Expression<String> parameterExpression = upperIfIgnoreCase(provider.next(part, String.class).getExpression());
Predicate like = builder.like(propertyExpression, parameterExpression, escape.getEscapeCharacter());
return type.equals(NOT_LIKE) || type.equals(NOT_CONTAINING) ? like.not() : like;
case TRUE:
Expression<Boolean> truePath = getTypedPath(root, part);
return builder.isTrue(truePath);
case FALSE:
Expression<Boolean> falsePath = getTypedPath(root, part);
return builder.isFalse(falsePath);
case SIMPLE_PROPERTY:
ParameterMetadata<Object> expression = provider.next(part);
Expression<Object> path = getTypedPath(root, part);
return expression.isIsNullParameter() ? path.isNull()
: builder.equal(upperIfIgnoreCase(path), upperIfIgnoreCase(expression.getExpression()));
case NEGATING_SIMPLE_PROPERTY:
return builder.notEqual(upperIfIgnoreCase(getTypedPath(root, part)),
upperIfIgnoreCase(provider.next(part).getExpression()));
case IS_EMPTY:
case IS_NOT_EMPTY:
if (!property.getLeafProperty().isCollection()) {
throw new IllegalArgumentException("IsEmpty / IsNotEmpty can only be used on collection properties");
}
Expression<Collection<Object>> collectionPath = traversePath(root, property);
return type.equals(IS_NOT_EMPTY) ? builder.isNotEmpty(collectionPath) : builder.isEmpty(collectionPath);
default:
throw new IllegalArgumentException("Unsupported keyword " + type);
}
}
}
// 省略其他
}
a)在JpaQueryCreator的构造方法中,通过CriteriaBuilder创建了CriteriaQuery对象;
b)在create()实现方法中,最终执行了new PredicateBuilder(part, root).build()。在build()方法中,根据Part【包含查询条件属性、查询条件关键字】中的查询条件关键字,使用CriteriaBuilder创建对应的Predicate;
c)在complete()方法中,通过构造方法中创建的CriteriaQuery对象,执行CriteriaQuery.select(),添加查询的Root。添加排序信息,然后将b)中的Predicate作为CriteriaQuery的查询条件,返回CriteriaQuery对象;
对于complete()方法,子类JpaCountQueryCreator重写了该方法。
2.2.2 JpaCountQueryCreator
JpaCountQueryCreator的代码如下:
public class JpaCountQueryCreator extends JpaQueryCreator {
private boolean distinct;
public JpaCountQueryCreator(PartTree tree, ReturnedType type, CriteriaBuilder builder,
ParameterMetadataProvider provider) {
super(tree, type, builder, provider);
this.distinct = tree.isDistinct();
}
@Override
protected CriteriaQuery<? extends Object> createCriteriaQuery(CriteriaBuilder builder, ReturnedType type) {
// 查询返回Long类型
return builder.createQuery(Long.class);
}
/**
* 执行query.select(),select为builder.count(),并加上predicate条件信息
*/
@Override
@SuppressWarnings("unchecked")
protected CriteriaQuery<? extends Object> complete(@Nullable Predicate predicate, Sort sort,
CriteriaQuery<? extends Object> query, CriteriaBuilder builder, Root<?> root) {
CriteriaQuery<? extends Object> select = query.select(getCountQuery(query, builder, root));
return predicate == null ? select : select.where(predicate);
}
/**
* 获取count表达式
*/
@SuppressWarnings("rawtypes")
private Expression getCountQuery(CriteriaQuery<?> query, CriteriaBuilder builder, Root<?> root) {
return distinct ? builder.countDistinct(root) : builder.count(root);
}
}
JpaCountQueryCreator的代码比较简单,创建一个查询返回值为Long的CriteriaQuery对象。在complete()方法中,执行CriteriaBuilder.count()统计,以及添加Predicate作为查询条件。
在QueryExecutorMethodInterceptor的构造方法中,通过CreateIfNotFoundQueryLookupStrategy查找策略解析Repository的方法的信息后,封装在RepositoryQuery对象后,保存到Map<Method, RepositoryQuery> queries中。
小结
限于篇幅,本篇先分享到这里。以下做一个小结:
1)Repository的代理类中,会添加QueryExecutorMethodInterceptor方法拦截器;
2)QueryExecutorMethodInterceptor方法拦截器的构造方法中,会根据查询查找策略CreateIfNotFoundQueryLookupStrategy,获得RepositoryQuery对象,解析方法。对于按方法命名规则实现的方法,使用的RepositoryQuery对象为PartTreeJpaQuery;
3)在PartTreeJpaQuery构造方法中,创建一个PartTree对象,解析方法名称中的起始关键字【如:findBy、readBy、deleteBy等】、条件属性【实体类中的属性】、查询关键字【Between、In、Equals等】;
4)创建对应方法的countQuery和query,将解析出的查询的基础信息封装在QueryPreparer对象中,根据解析出的查询信息,创建CriteriaQuery对象;
5)解析完方法信息,保存在PartTreeJpaQuery后,保存到QueryExecutorMethodInterceptor的Map<Method, RepositoryQuery> queries中;
关于本篇内容你有什么自己的想法或独到见解,欢迎在评论区一起交流探讨下吧。
标签:return,自定义,private,final,public,源码,query,原理,method From: https://blog.csdn.net/JingAi_jia917/article/details/139237128