2.X集成方式
参考官方文档,querydsl/querydsl-jpa at master · querydsl/querydsl (github.com),集成方式比较简单
- pom.xml添加query的依赖,包括
querydsl-jpa
依赖和apt-maven-plugin
maven插件
<!--依赖-->
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-jpa</artifactId>
<version>${querydsl.version}</version>
</dependency>
<!--插件-->
<plugin>
<groupId>com.mysema.maven</groupId>
<artifactId>apt-maven-plugin</artifactId>
<version>1.1.3</version>
<executions>
<execution>
<goals>
<goal>process</goal>
</goals>
<configuration>
<outputDirectory>target/generated-sources/java</outputDirectory>
<processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
<version>${querydsl.version}</version>
</dependency>
</dependencies>
</plugin>
这个插件是用来生成实体对象对应的查询对象,假设有个Student
对象,那么生成的查询对象就是QStudent
-
插件和依赖引入完毕后点击下图所示的按钮,或者执行
mvn install
命令,就可以在target/generated-sources/java
中生成查询对象,打包后也会将该对象引入jar包中
成功生成查询对象,在代码中即可正常使用
3.X集成方式
Spring Data JPA 3.0之后,JPA相应的注解包发生变化,之前是在javax包中,新版本包名变成了jakarta.*,按照老版本的方式无法生成实体类的查询对象,网络上查询的集成方式都是基于老版本的。所以在翻看官方文档时提到了一个解决方式
文档如果使用的Hibernate的注解,需要用Hibernate对应的processor处理,其实两种类型注解名称都是一样的只是包名不同,和我们的场景是一样的,我们把源码下载之后,看看HibernateAnnotationProcessor是如何实现的,会发现这个类解析的还是javax包的注解
玄机是在HibernateConfiguration这个类中,这个类重写了getAnnotations方法,将javax的包名换成了org.hibernate.annotations
,从而实现了解析Hibernate注解的功能,那我们就可以模仿这两个类自定义processor,将解析的几个注解包改一下即可,直接复JPAAnnotationProcessor
和JPAConfiguration
,把报错的注解替换成jakarta.persistence
包的注解即可,源码如下,然后修改pom.xml插件的processor的全限定名为自定义类的全限定名即可
JPAConfiguration源码
package com.komisch.springdatajpademo.processor;
import com.querydsl.apt.DefaultConfiguration;
import com.querydsl.apt.QueryTypeImpl;
import com.querydsl.apt.TypeUtils;
import com.querydsl.apt.VisitorConfig;
import com.querydsl.codegen.Keywords;
import com.querydsl.core.annotations.*;
import com.querydsl.core.util.Annotations;
import jakarta.persistence.*;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.element.*;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Types;
import java.lang.annotation.Annotation;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* Configuration for {@link JPAAnnotationProcessor}
*
* @see JPAAnnotationProcessor
*/
public class JPAConfiguration extends DefaultConfiguration {
private final List<Class<? extends Annotation>> annotations;
private final Types types;
public JPAConfiguration(RoundEnvironment roundEnv,
ProcessingEnvironment processingEnv,
Class<? extends Annotation> entityAnn,
Class<? extends Annotation> superTypeAnn,
Class<? extends Annotation> embeddableAnn,
Class<? extends Annotation> embeddedAnn,
Class<? extends Annotation> skipAnn) {
super(processingEnv, roundEnv, Keywords.JPA, QueryEntities.class, entityAnn, superTypeAnn,
embeddableAnn, embeddedAnn, skipAnn);
this.annotations = getAnnotations();
this.types = processingEnv.getTypeUtils();
setStrictMode(true);
}
@SuppressWarnings("unchecked")
protected List<Class<? extends Annotation>> getAnnotations() {
return Collections.unmodifiableList(Arrays.asList(
Access.class, Basic.class, Column.class, ElementCollection.class,
Embedded.class, EmbeddedId.class, Enumerated.class, GeneratedValue.class, Id.class,
JoinColumn.class, ManyToOne.class, ManyToMany.class, MapKeyEnumerated.class,
OneToOne.class, OneToMany.class, PrimaryKeyJoinColumn.class, QueryType.class, QueryInit.class,
QueryTransient.class, Temporal.class, Transient.class, Version.class));
}
@Override
public VisitorConfig getConfig(TypeElement e, List<? extends Element> elements) {
Access access = e.getAnnotation(Access.class);
if (access != null) {
if (access.value() == AccessType.FIELD) {
return VisitorConfig.FIELDS_ONLY;
} else {
return VisitorConfig.METHODS_ONLY;
}
}
boolean fields = false, methods = false;
for (Element element : elements) {
if (hasRelevantAnnotation(element)) {
fields |= element.getKind().equals(ElementKind.FIELD);
methods |= element.getKind().equals(ElementKind.METHOD);
}
}
return VisitorConfig.get(fields, methods, VisitorConfig.ALL);
}
@Override
public TypeMirror getRealType(ExecutableElement method) {
return getRealElementType(method);
}
@Override
public TypeMirror getRealType(VariableElement field) {
return getRealElementType(field);
}
private TypeMirror getRealElementType(Element element) {
AnnotationMirror mirror = TypeUtils.getAnnotationMirrorOfType(element, ManyToOne.class);
if (mirror == null) {
mirror = TypeUtils.getAnnotationMirrorOfType(element, OneToOne.class);
}
if (mirror != null) {
return TypeUtils.getAnnotationValueAsTypeMirror(mirror, "targetEntity");
}
mirror = TypeUtils.getAnnotationMirrorOfType(element, OneToMany.class);
if (mirror == null) {
mirror = TypeUtils.getAnnotationMirrorOfType(element, ManyToMany.class);
}
if (mirror != null) {
TypeMirror typeArg = TypeUtils.getAnnotationValueAsTypeMirror(mirror, "targetEntity");
TypeMirror erasure;
if (element instanceof ExecutableElement) {
erasure = ((ExecutableElement) element).getReturnType();
} else {
erasure = types.erasure(element.asType());
}
TypeElement typeElement = (TypeElement) types.asElement(erasure);
if (typeElement != null && typeArg != null) {
if (typeElement.getTypeParameters().size() == 1) {
return types.getDeclaredType(typeElement, typeArg);
} else if (typeElement.getTypeParameters().size() == 2) {
if (element.asType() instanceof DeclaredType) {
TypeMirror first = ((DeclaredType) element.asType()).getTypeArguments().get(0);
return types.getDeclaredType(typeElement, first, typeArg);
}
}
}
}
return null;
}
@Override
public void inspect(Element element, Annotations annotations) {
Temporal temporal = element.getAnnotation(Temporal.class);
if (temporal != null && element.getAnnotation(ElementCollection.class) == null) {
PropertyType propertyType = null;
switch (temporal.value()) {
case DATE:
propertyType = PropertyType.DATE;
break;
case TIME:
propertyType = PropertyType.TIME;
break;
case TIMESTAMP:
propertyType = PropertyType.DATETIME;
}
annotations.addAnnotation(new QueryTypeImpl(propertyType));
}
}
private boolean hasRelevantAnnotation(Element element) {
for (Class<? extends Annotation> annotation : annotations) {
if (element.getAnnotation(annotation) != null) {
return true;
}
}
return false;
}
}
JPAAnnotationProcessor源码
package com.komisch.springdatajpademo.processor;
import com.querydsl.apt.AbstractQuerydslProcessor;
import com.querydsl.apt.Configuration;
import jakarta.persistence.*;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import java.lang.annotation.Annotation;
@SupportedAnnotationTypes({"com.querydsl.core.annotations.*", "jakarta.persistence.*"})
public class JPAAnnotationProcessor extends AbstractQuerydslProcessor {
public JPAAnnotationProcessor() {
}
protected Configuration createConfiguration(RoundEnvironment roundEnv) {
Class<? extends Annotation> entity = Entity.class;
Class<? extends Annotation> superType = MappedSuperclass.class;
Class<? extends Annotation> embeddable = Embeddable.class;
Class<? extends Annotation> embedded = Embedded.class;
Class<? extends Annotation> skip = Transient.class;
System.out.println(processingEnv);
return new JPAConfiguration(roundEnv, this.processingEnv, entity, superType, embeddable, embedded, skip);
}
}
标签:return,JPA,Spring,querydsl,element,com,import,Data,class
From: https://www.cnblogs.com/komisch/p/17586955.html