转载自:https://www.cnblogs.com/vincentren/p/9593427.html
这边简介我就不从各大网站的文章中copy过来了,这边给个官网的中文翻译传送门:http://books.aying.org/querydsl_zh_CN/Introduction.html
com.querydsl
querydsl-jpa
com.querydsl
querydsl-apt
provided
com.mysema.maven
apt-maven-plugin
1.1.3
process
target/generated-sources/java
com.querydsl.apt.jpa.JPAAnnotationProcessor
JPAAnnotationProcessor 查找带有 javax.persistence.Entity 注解的领域类型并为其生成查询类型。简单来说,比如有个Student的entity,运行clean install 会在项目的target/generated-sources/java 目录下将生成QStudent,这个QStudent就是查询类型类。
@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 {
private static final long serialVersionUID = -5814978L;
public static final QStudent student = new QStudent("student");
public final NumberPath age = createNumber("age", Integer.class);
public final NumberPath id = createNumber("id", Long.class);
public final StringPath name = createString("name");
public final NumberPath 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);
}
}
@RunWith(SpringRunner.class)
@SpringBootTest
public class QueryDslTest {
@Autowired
@PersistenceContext
private EntityManager entityManager;
private JPAQueryFactory queryFactory;
@Before
public void init() {
queryFactory = new JPAQueryFactory(entityManager);
}
}
@Test
public void selectStudent(){
QStudent qStudent = QStudent.student;
List students = queryFactory.selectFrom(qStudent).fetch();
System.out.println(students);
}
@Test
public void selectStudentWithWhere() {
QStudent qStudent = QStudent.student;
//单表单条件查询
List students = queryFactory.selectFrom(qStudent).where(qStudent.age.goe(2)).fetch();
//单表多条件and查询
List studentList = queryFactory.selectFrom(qStudent).where(qStudent.age.goe(2).and(qStudent.name.eq("vincent"))).fetch();
//单表多条件or查询
List list = queryFactory.selectFrom(qStudent).where(qStudent.age.goe(20).or(qStudent.name.eq("vincent"))).fetch();
//单表排序分页查询
List 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);
}
@Test
public void selectStudent1() {
QStudent qStudent = QStudent.student;
QSchool qSchool = QSchool.school;
List 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 students = queryFactory.select(qStudent.age, qStudent.name, qSchool.name).from(qSchool, qStudent).where(qSchool.id.eq(qStudent.schoolId)).fetch();
List
@Test
public void selectStudent3() {
QStudent qStudent = QStudent.student;
QSchool qSchool = QSchool.school;
List 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.(HQLQueryPlan.java:115) [hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.engine.query.spi.HQLQueryPlan.(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.(HQLQueryPlan.java:115)
at org.hibernate.engine.query.spi.HQLQueryPlan.(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的
UTF-8
5.1.15.Final
我这边的项目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 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。