当前位置: 首页 > 知识库问答 >
问题:

如何在没有联接的情况下编写JPA2.1更新条件查询?

米子轩
2023-03-14
final CriteriaBuilder qb = m_entityManager.getCriteriaBuilder();
    final CriteriaUpdate<MyClassroom> q = qb.createCriteriaUpdate(MyClassroom.class);
    final Root<MyClassroom> root = q.from(MyClassroom.class);
    final Join<MyClassroom, MyClassroomUser> rosterJoin = root.join(MyClassroom_.roster);
    final Join<MyClassroomUser, User> userJoin = rosterJoin.join(MyClassroomUser_.user);

    final Calendar today = Calendar.getInstance();
    q.set(root.get(MyClassroom_.enabled), false)
     .where(qb.and(qb.equal(root.get(MyClassroom_.enabled),true),
                            qb.lessThanOrEqualTo(root.get(MyClassroom_.session).get(MyClassroomSession_.schedule).<Calendar>get(MyClassroomSchedule_.endDate), today)),
                            qb.equal(rosterJoin.get(MyClassroomUser_.classroomRole).get(ClassroomRole_.name), ClassroomRoles.TEACHER),
                            qb.equal(userJoin.get(User_.organization).get(Organization_.importDataFromSis), false));

    return m_entityManager.createQuery(q).executeUpdate();
java.lang.IllegalArgumentException: UPDATE/DELETE criteria queries cannot define joins
    at org.hibernate.jpa.criteria.path.RootImpl.illegalJoin(RootImpl.java:81)
    at org.hibernate.jpa.criteria.path.AbstractFromImpl.join(AbstractFromImpl.java:330)
    at org.hibernate.jpa.criteria.path.AbstractFromImpl.join(AbstractFromImpl.java:324)
    at org.mainco.subco.classroom.repo.MyClassroomDaoImpl.disabledNonCleverExpiredClasses(MyClassroomDaoImpl.java:495)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:319)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
    at com.sun.proxy.$Proxy66.disabledNonCleverExpiredClasses(Unknown Source)
    at com.follett.fdr.lycea.lms.classroom.test.da.MyClassroomDaoTest.testDisableNonCleverExpiredClass(MyClassroomDaoTest.java:355)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
   final CriteriaBuilder qb = m_entityManager.getCriteriaBuilder();
    final CriteriaUpdate<Classroom> q = qb.createCriteriaUpdate(Classroom.class);
    final Root<Classroom> mainRoot = q.from(Classroom.class);

    // Subquery to select the classes we want to disable.
    final Subquery<Classroom> subquery = q.subquery(Classroom.class);
    final Root<Classroom> root = subquery.from(Classroom.class);
    final Join<Classroom, ClassroomUser> rosterJoin = root.join(Classroom_.roster);
    final Join<ClassroomUser, User> userJoin = rosterJoin.join(ClassroomUser_.user);
    final SetJoin<User, Organization> orgJoin = userJoin.join(User_.organizations);
    final Calendar today = Calendar.getInstance();
    subquery.select(root)
            .where(qb.and(qb.equal(root.get(Classroom_.enabled),true),
                          qb.lessThanOrEqualTo(root.get(Classroom_.session).get(ClassroomSession_.schedule).<Calendar>get(ClassroomSchedule_.endDate), today)),
                          qb.equal(rosterJoin.get(ClassroomUser_.classroomRole).get(ClassroomRole_.name), ClassroomRoles.TEACHER),
                          qb.equal(orgJoin.get(Organization_.importDataFromSis), false)
                          );

    // Build the update query
    q.set(mainRoot.get(Classroom_.enabled), false)
     .where(mainRoot.in(subquery));

    // execute the update query
    return m_entityManager.createQuery(q).executeUpdate();

但却有例外…

javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: could not execute statement
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1763)
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1677)
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.java:1771)
    at org.hibernate.jpa.spi.AbstractQueryImpl.executeUpdate(AbstractQueryImpl.java:87)
    at …
Caused by: java.sql.SQLException: You can't specify target table ‘my_classroom' for update in FROM clause
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1074)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4096)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4028)
    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2490)
    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2651)
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2734)
    at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2155)
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2458)
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2375)
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2359)
    at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:208)
    ... 49 more

共有1个答案

印季
2023-03-14

连接仅在标准SQL中的SELECT中才可能。它在JPQL/标准中不起作用也就不足为奇了。

您应该尝试使用子查询来创建联接,并在where子句中指定in表达式。

创建子查询与标准CriteriaQuery相同,因为子查询方法是在CommonAbstractCriteria是一个通用分类器中定义的。

 类似资料:
  • 我需要为密码字段设置一个错误,条件是“只允许2到22个字符和符号,\-” 但是我有点困在这里了。 这是我到目前为止得到的: 但问题是,如果我输入了_或-以外的符号,错误消息仍然不会显示。对于输入长度,错误消息显示为它应该显示的样子。

  • 本文向大家介绍如何在没有ON条件的情况下使用MySQL JOIN?,包括了如何在没有ON条件的情况下使用MySQL JOIN?的使用技巧和注意事项,需要的朋友参考一下 我们可以不加条件地使用“交叉连接”。交叉联接以笛卡尔积形式给出结果。例如,如果一个表中有3条记录,而另一个表中有2条记录,则第一个记录将与所有第二个表记录匹配。然后,将重复相同的过程以进行第二次记录,依此类推。 交叉连接的例子 创建

  • 我正在尝试编写一个相当于以下SQL查询的Hibernate Criteria API: 这是我的实体 这是我的实体 是引用的外键。虽然没有明显的实体级关系,我也不能添加任何关系。

  • 对于上面的查询,我得到了错误

  • 我正在尝试在没有项目编写器的情况下使用下面的配置来配置spring批处理步骤。然而,我错误地说writer元素既没有'writer'属性,也没有元素。 我浏览了链接spring批处理:没有ItemWriter的Tasklet。但无法解决问题。有人能告诉我在我提到的代码片段中要做的具体更改吗

  • 问题内容: 嗨,我目前有3个表格,如下所示。表之间没有通用键 表1-> linkage_Table 表2->材料表 表格3-> Color_Table 我希望得到以下结果集 我想编写一条SQL语句将表连接在一起。 链接表中带有*表示我们将从材料或颜色表中检索所有值。 我现在确实需要此解决方案。一直试图解决这个问题超过5个小时。在此先感谢您的帮助。 问题答案: 一种可能的方法: SQL小提琴 说明: