Springboot-Jpa-QueryDsl

转载自:https://www.cnblogs.com/vincentren/p/9593427.html

(一)QueryDsl简介

这边简介我就不从各大网站的文章中copy过来了,这边给个官网的中文翻译传送门:http://books.aying.org/querydsl_zh_CN/Introduction.html

(二)引入QueryDsl

2.1 依赖

<dependency>
    <groupId>com.querydsl</groupId>
    <artifactId>querydsl-jpa</artifactId>
</dependency>
<dependency>
    <groupId>com.querydsl</groupId>
    <artifactId>querydsl-apt</artifactId>
    <scope>provided</scope>
</dependency>

2.2 plugin

<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>
     </plugin>

JPAAnnotationProcessor 查找带有 javax.persistence.Entity 注解的领域类型并为其生成查询类型。简单来说,比如有个Student的entity,运行clean install 会在项目的target/generated-sources/java 目录下将生成QStudent,这个QStudent就是查询类型类。

(三)实体 Student类

@Table(name = "student")
@Entity
public class Student {
 
    @Id
    @GeneratedValue(
            strategy = GenerationType.IDENTITY
    )
    private long id;
 
    private String name;
 
    private int age;
 
    private long schoolId;
 
    public long getId() {
        return id;
    }
 
    public void setId(long id) {
        this.id = id;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public int getAge() {
        return age;
    }
 
    public void setAge(int age) {
        this.age = age;
    }
 
    public long getSchoolId() {
        return schoolId;
    }
 
    public void setSchoolId(Long schoolId) {
        this.schoolId = schoolId;
    }
 
    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", schoolId=" + schoolId +
                '}';
    }
}

运行mvn clean install后生成的QStudent

@Generated("com.querydsl.codegen.EntitySerializer")
public class QStudent extends EntityPathBase<Student> {
 
    private static final long serialVersionUID = -5814978L;
 
    public static final QStudent student = new QStudent("student");
 
    public final NumberPath<Integer> age = createNumber("age", Integer.class);
 
    public final NumberPath<Long> id = createNumber("id", Long.class);
 
    public final StringPath name = createString("name");
 
    public final NumberPath<Long> schoolId = createNumber("schoolId", Long.class);
 
    public QStudent(String variable) {
        super(Student.class, forVariable(variable));
    }
 
    public QStudent(Path<? extends Student> path) {
        super(path.getType(), path.getMetadata());
    }
 
    public QStudent(PathMetadata metadata) {
        super(Student.class, metadata);
    }
 
}

(四)查询

4.0 QueryDslTest测试类

@RunWith(SpringRunner.class)
@SpringBootTest
public class QueryDslTest {
 
    @Autowired
    @PersistenceContext
    private EntityManager entityManager;
 
    private JPAQueryFactory queryFactory;
 
    @Before
    public void init() {
        queryFactory = new JPAQueryFactory(entityManager);
    }
}

4.1简单查询

@Test
    public void selectStudent(){
        QStudent qStudent = QStudent.student;
        List<Student> students = queryFactory.selectFrom(qStudent).fetch();
        System.out.println(students);
    }

4.2 单表条件查询

@Test
public void selectStudentWithWhere() {
    QStudent qStudent = QStudent.student;
    //单表单条件查询
    List<Student> students = queryFactory.selectFrom(qStudent).where(qStudent.age.goe(2)).fetch();
    //单表多条件and查询
    List<Student> studentList = queryFactory.selectFrom(qStudent).where(qStudent.age.goe(2).and(qStudent.name.eq("vincent"))).fetch();
    //单表多条件or查询
    List<Student> list = queryFactory.selectFrom(qStudent).where(qStudent.age.goe(20).or(qStudent.name.eq("vincent"))).fetch();
    //单表排序分页查询
    List<Student> list1 = queryFactory.selectFrom(qStudent).offset(1).limit(3).orderBy(qStudent.id.desc()).fetch();
    System.out.println(students);
    System.out.println(studentList);
    System.out.println(list);
    System.out.println(list1);
}

4.3 多表查询

@Test
 public void selectStudent1() {
     QStudent qStudent = QStudent.student;
     QSchool qSchool = QSchool.school;
     List<Student> students = queryFactory.select(qStudent).from(qSchool, qStudent).where(qSchool.id.eq(qStudent.schoolId)).fetch();
     System.out.println(students);
 }

以上查询的结果只是student的表的值,比如我现在关心学校名称,那么这样子就不能得到,用下面的做法可以得到你想要的值

@Test
public void selectStudent2() {
    QStudent qStudent = QStudent.student;
    QSchool qSchool = QSchool.school;
    List<Tuple> students = queryFactory.select(qStudent.age, qStudent.name, qSchool.name).from(qSchool, qStudent).where(qSchool.id.eq(qStudent.schoolId)).fetch();
    List<Map<String, Object>> maps = students.stream().map(tuple -> {
        Map<String, Object> map = new HashMap<>();
        map.put("studentName", tuple.get(qStudent.name));
        map.put("age", tuple.get(qStudent.age));
        map.put("schoolName", tuple.get(qSchool.name));
        return map;
    }).collect(Collectors.toList());
    System.out.println(maps);
}

4.4 leftjoin查询

@Test
public void selectStudent3() {
    QStudent qStudent = QStudent.student;
    QSchool qSchool = QSchool.school;
    List<Student> students = queryFactory.select(qStudent)
            .from(qStudent)
            .leftJoin(qSchool)
            .on(qStudent.schoolId.eq(qSchool.id))
            .fetch();
    System.out.println(students);
}

这段代码本身是没有问题的,不过按照之前的配置运行起来将会报以下错误。

2018-09-06 10:25:25.678 ERROR 4742 --- [           main] o.h.hql.internal.ast.ErrorCounter        :  Path expected for join!
2018-09-06 10:25:25.686 ERROR 4742 --- [           main] o.h.hql.internal.ast.ErrorCounter        :  Path expected for join!
 
antlr.SemanticException: Path expected for join!
    at org.hibernate.hql.internal.ast.HqlSqlWalker.createFromJoinElement(HqlSqlWalker.java:368) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.joinElement(HqlSqlBaseWalker.java:3912) [hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.fromElement(HqlSqlBaseWalker.java:3698) [hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.fromElementList(HqlSqlBaseWalker.java:3576) [hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.fromClause(HqlSqlBaseWalker.java:716) [hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.query(HqlSqlBaseWalker.java:572) [hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.selectStatement(HqlSqlBaseWalker.java:309) [hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.statement(HqlSqlBaseWalker.java:257) [hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:262) [hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:190) [hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:142) [hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:115) [hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:76) [hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:150) [hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.internal.AbstractSessionImpl.getHQLQueryPlan(AbstractSessionImpl.java:302) [hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.internal.AbstractSessionImpl.createQuery(AbstractSessionImpl.java:240) [hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.internal.SessionImpl.createQuery(SessionImpl.java:1894) [hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.createQuery(AbstractEntityManagerImpl.java:291) [hibernate-entitymanager-5.0.12.Final.jar:5.0.12.Final]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_144]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_144]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_144]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_144]
    at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:347) [spring-orm-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at com.sun.proxy.$Proxy91.createQuery(Unknown Source) [na:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_144]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_144]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_144]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_144]
    at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:298) [spring-orm-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at com.sun.proxy.$Proxy91.createQuery(Unknown Source) [na:na]
    at com.querydsl.jpa.impl.AbstractJPAQuery.createQuery(AbstractJPAQuery.java:101) [querydsl-jpa-4.1.4.jar:na]
    at com.querydsl.jpa.impl.AbstractJPAQuery.createQuery(AbstractJPAQuery.java:94) [querydsl-jpa-4.1.4.jar:na]
    at com.querydsl.jpa.impl.AbstractJPAQuery.fetch(AbstractJPAQuery.java:201) [querydsl-jpa-4.1.4.jar:na]
    at com.vincent.QueryDslTest.selectStudent4(QueryDslTest.java:129) [test-classes/:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_144]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_144]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_144]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_144]
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) [junit-4.12.jar:4.12]
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) [junit-4.12.jar:4.12]
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) [junit-4.12.jar:4.12]
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) [junit-4.12.jar:4.12]
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26) [junit-4.12.jar:4.12]
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75) [spring-test-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86) [spring-test-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84) [spring-test-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) [junit-4.12.jar:4.12]
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252) [spring-test-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) [spring-test-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) [junit-4.12.jar:4.12]
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) [junit-4.12.jar:4.12]
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) [junit-4.12.jar:4.12]
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) [junit-4.12.jar:4.12]
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) [junit-4.12.jar:4.12]
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) [spring-test-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) [spring-test-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363) [junit-4.12.jar:4.12]
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) [spring-test-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137) [junit-4.12.jar:4.12]
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68) [junit-rt.jar:na]
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47) [junit-rt.jar:na]
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242) [junit-rt.jar:na]
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70) [junit-rt.jar:na]
 
 
java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: Path expected for join! [select student
from com.vincent.model.Student student
  left join School school with student.schoolId = school.id
where student.name = ?1]
 
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1679)
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1602)
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1608)
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.createQuery(AbstractEntityManagerImpl.java:294)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:347)
    at com.sun.proxy.$Proxy91.createQuery(Unknown Source)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:298)
    at com.sun.proxy.$Proxy91.createQuery(Unknown Source)
    at com.querydsl.jpa.impl.AbstractJPAQuery.createQuery(AbstractJPAQuery.java:101)
    at com.querydsl.jpa.impl.AbstractJPAQuery.createQuery(AbstractJPAQuery.java:94)
    at com.querydsl.jpa.impl.AbstractJPAQuery.fetch(AbstractJPAQuery.java:201)
    at com.vincent.QueryDslTest.selectStudent4(QueryDslTest.java:129)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: Path expected for join! [select student
from com.vincent.model.Student student
  left join School school with student.schoolId = school.id
where student.name = ?1]
    at org.hibernate.hql.internal.ast.QuerySyntaxException.convert(QuerySyntaxException.java:74)
    at org.hibernate.hql.internal.ast.ErrorCounter.throwQueryException(ErrorCounter.java:91)
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:268)
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:190)
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:142)
    at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:115)
    at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:76)
    at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:150)
    at org.hibernate.internal.AbstractSessionImpl.getHQLQueryPlan(AbstractSessionImpl.java:302)
    at org.hibernate.internal.AbstractSessionImpl.createQuery(AbstractSessionImpl.java:240)
    at org.hibernate.internal.SessionImpl.createQuery(SessionImpl.java:1894)
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.createQuery(AbstractEntityManagerImpl.java:291)
    ... 45 more

根据这个异常还有他报错的其他信息,网上找了很多都没有真正解决。

最后对比了实际可以运行的项目,修改了pom的一个小配置即解决了问题。

在pom的<properties>标签中加入

<hibernate.version>5.1.15.Final</hibernate.version>

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <hibernate.version>5.1.15.Final</hibernate.version>
</properties>

我这边的项目springboot版本是1.5.9.RELEASE,他这边默认的hibernate版本是5.0.12.Final版本,而使用这个版本就会报上节4.4说的那个异常。

经测试把hibernate版本改为5.1.10Final版本都可执行成功,具体原因,目前还没找空闲时间细细探究。

(五)更新

在Querydsl JPA中,更新语句是简单的 update-set/where-execute 形式。

execute()执行后返回的是被更新的实体的数量。

@Test
public void testUpdate() {
    QStudent qStudent = QStudent.student;
    Long result = queryFactory.update(qStudent)
            .set(qStudent.name, "haha")
            .where(qStudent.id.eq(111L)).execute();
    assertThat(result,equalTo(1L));
}

这段代码运行后会报错,错误如下。

javax.persistence.TransactionRequiredException: Executing an update/delete query
 
    at org.hibernate.jpa.spi.AbstractQueryImpl.executeUpdate(AbstractQueryImpl.java:54)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.orm.jpa.SharedEntityManagerCreator$DeferredQueryInvocationHandler.invoke(SharedEntityManagerCreator.java:372)
    at com.sun.proxy.$Proxy102.executeUpdate(Unknown Source)
    at com.querydsl.jpa.impl.JPAUpdateClause.execute(JPAUpdateClause.java:77)
    at com.vincent.QueryDslTest.testUpdate(QueryDslTest.java:156)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

原因是jpa的update和delete需要加上@Transactional注解,这个细节很重要

可执行版本如下

@Test
@Transactional
public void testUpdate() {
    QStudent qStudent = QStudent.student;
    Long result = queryFactory.update(qStudent)
            .set(qStudent.name, "haha")
            .where(qStudent.id.eq(111L)).execute();
    assertThat(result,equalTo(1L));
}

(六)删除 

 删除语句是简单的 delete-where-execute 形式。

@Test
@Transactional
public void testDelete() {
    QStudent qStudent = QStudent.student;
    //删除指定的一个
    Long result = queryFactory.delete(qStudent)
            .where(qStudent.id.eq(111L))
            .execute();
    assertThat(result, equalTo(1L));
    //删除所有
    Long totalResult = queryFactory.delete(qStudent)
            .execute();
    System.out.println(totalResult);
}

如果多表关联查询时(上节4.3)想将多表的中不同字段选出来时,咱们用的是java8语法将list组装,那么有没有不需要自行组装这一步,查询返回的结果自动就帮我们组装好了呢?

这边介绍个简便方法,使用Projections。

首先我们还是以学校和学生表作为例子。

这边我们先建一个StudentDto

public class StudentDto {
 
    private long id;
 
    private String name;
 
    private int age;
 
    private long schoolId;
 
    private String schoolName;
 
    public long getId() {
        return id;
    }
 
    public void setId(long id) {
        this.id = id;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public int getAge() {
        return age;
    }
 
    public void setAge(int age) {
        this.age = age;
    }
 
    public long getSchoolId() {
        return schoolId;
    }
 
    public void setSchoolId(long schoolId) {
        this.schoolId = schoolId;
    }
 
    public String getSchoolName() {
        return schoolName;
    }
 
    public void setSchoolName(String schoolName) {
        this.schoolName = schoolName;
    }
 
    @Override
    public String toString() {
        return "StudentDto{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", schoolId=" + schoolId +
                ", schoolName='" + schoolName + '\'' +
                '}';
    }
}

这里包含我们想要的学生id,姓名,年龄,学校id,学校名称等字段。

将上节4.3的代码修改成如下

@Test
public void selectStudent5() {
    QStudent qStudent = QStudent.student;
    QSchool qSchool = QSchool.school;
    List<StudentDto> students = queryFactory
            .select(Projections
                    .fields(StudentDto.class,
                            qStudent.id,
                            qStudent.name,
                            qStudent.age,
                            qStudent.schoolId,
                            qSchool.name.as("schoolName")))
            .from(qSchool, qStudent)
            .where(qSchool.id.eq(qStudent.schoolId))
            .fetch();
    System.out.println(students);
}  

返回的结果就自动拼装成了我们想要的StudentDto。

当然了,如果不想要每次都定义Dto,那么还是可以用上节4.3的那种方式组装成一个map。

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
无法解析 com.querydsl:querydsl-jpa:${querydsl.version}是因为在引用中使用了变量${querydsl.version}。这种情况通常是在项目的pom.xml文件中定义了一个名为querydsl.version的属性,然后在引用中使用该属性的值。如果没有定义这个属性或者属性的值无法解析,就会出现无法解析的情况。为了解决这个问题,你可以在pom.xml文件中定义querydsl.version属性并赋予一个具体的值,或者直接在引用中使用具体的版本号。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [SpringBoot项目整合JPA+QueryDSL,及apt-maven-plugin报错问题解决](https://blog.csdn.net/weixin_42315600/article/details/103627304)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [java.lang.NoSuchMethodError: com.querydsl.jpa.JPQLSerializer.....Ljava/util jar冲突](https://blog.csdn.net/weixin_38175213/article/details/127266784)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值