首页 > 其他分享 >Spring Data JPA 3.X集成Querydsl

Spring Data JPA 3.X集成Querydsl

时间:2023-07-28 10:46:59浏览次数:56  
标签:return JPA Spring querydsl element com import Data class

2.X集成方式

参考官方文档,querydsl/querydsl-jpa at master · querydsl/querydsl (github.com),集成方式比较简单

  • pom.xml添加query的依赖,包括querydsl-jpa依赖和apt-maven-pluginmaven插件
<!--依赖-->
<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包中

    image-20230728092614237

成功生成查询对象,在代码中即可正常使用

image-20230728092836895

3.X集成方式

Spring Data JPA 3.0之后,JPA相应的注解包发生变化,之前是在javax包中,新版本包名变成了jakarta.*,按照老版本的方式无法生成实体类的查询对象,网络上查询的集成方式都是基于老版本的。所以在翻看官方文档时提到了一个解决方式

image-20230728094035710

文档如果使用的Hibernate的注解,需要用Hibernate对应的processor处理,其实两种类型注解名称都是一样的只是包名不同,和我们的场景是一样的,我们把源码下载之后,看看HibernateAnnotationProcessor是如何实现的,会发现这个类解析的还是javax包的注解

image-20230728100932330

玄机是在HibernateConfiguration这个类中,这个类重写了getAnnotations方法,将javax的包名换成了org.hibernate.annotations,从而实现了解析Hibernate注解的功能,那我们就可以模仿这两个类自定义processor,将解析的几个注解包改一下即可,直接复JPAAnnotationProcessorJPAConfiguration,把报错的注解替换成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

相关文章

  • org.springframework.beans.factory.parsing.BeanDefinitionParsingException
    org.springframework.beans.factory.parsing.BeanDefinitionParsingException:Configurationproblem:Failedtoimportbeandefinitionsfromrelativelocation[spring-controller.xml]Offendingresource:classpathresource[applicationContext.xml];nestedexcep......
  • Spring boot gradle docker plugin 使用
    Springbootgradledockerplugin使用Springbootgradledockerplugin使用前言增加GradleDocker插件使用GradleDocker插件DockerFile运行docker指令生成DockerImage使用IDEA运行docker指令前言当前容器技术、微服务、JVM语言等新的技术正在快速的占领着Java开发市场,J......
  • 策略模式+Spring配置类优化多if..else思路
    图示1.现状场景:假设设备上报不同类型的消息,我们要对不同类型的消息做不同的处理。如果我们通过if..else的方式处理的话会显得比较冗余。例如:if("alarmEvent".equals(msg)){//处理告警消息逻辑...}elseif("deviceBase".equals(msg)){//处理设备上报的基本......
  • SpringCloud的注册和发现
    什么是微服务架构,为什么要用将原本属于一个项目的根据业务划分模块,部署到不同的服务器上,通过接口相互调用。好处:如果部署在一台服务器上,服务器崩溃后所有功能都不能使用。如果使用的时微服务架构,一个服务器崩了,不会对另一个模块造成很大影响每个微服务项目复杂性低技术更新迭......
  • 用concat比较两个dataframe
    因为equals会比对索引等,可能出现内容相同但是行序不同比对失败,可以采用concat,去除重复后如果为空则表示数据一致。1#比对两个DataFrame23ifdf1.equals(df2):4returnTrue,None5else:6diff_row=pd.concat([df1,df2]).drop_duplicates(keep=False)......
  • springMVC Interceptor 拦截器
    1.springMVCInterceptor拦截器2.Filter和Interceptor比对3.HandlerInterceptor接口方法的作用及其参数、返回值详解4.springMVC拦截器执行顺序 ......
  • uni-app写微信小程序,data字段循环引用
    在写程序过程中,需要使用到globalData里的内容,而这个全局变量,在uni-app上需要通过:varapp=getApp();app.globalData.xxx=xxx来使用。我觉得每次都要获取app对象,嫌麻烦,就在data数据段里定义一个app字段,之后就通过this.app.globalData来使用,问题就出现在这。我用hbuilderX运行......
  • 大数据量时生成DataFrame避免使用效率低的append方法
    转载请注明出处:https://www.cnblogs.com/oceanicstar/p/10900332.html append方法可以很方便地拼接两个DataFramedf1.append(df2)>AB>1A1B1>2A2B2>3A3B3>4A4B4但数据量大时生成DataFrame,应避免使用append方法因为:    与python列表中的appe......
  • springboot上传图片后通过http访问图片
    需要上传图片或pdf文件,放在服务器本地磁盘中,比如window服务器的D:/YG/盘符下,此时想要通过http的方式直接访问图片或pdf 1.图片存储在本地磁盘,实现WebMvcConfigurer接口添加本地静态资源访问过滤2.图片存储在本地磁盘,nginx动静分离  第一种方式:@Configurationpubli......
  • Shiro实战教程(整合SpringBoot,全网最强)
    ​ 本文介绍一个强大的Shiro实战教程,用最简单的代码、最常用的场景让你彻底掌握Shiro的用法,成为Shiro实战高手。本Shiro教程是全网最强的Shiro实战教程。教程地址:Shiro项目实战专栏介绍-自学精灵为什么这个Shiro教程是全网最强?其他资料的特点代码不全,根本运行不起来。不......