#spring-boot #spring-mvc #jpa #spring-data-jpa #spring-data
#весенняя загрузка #spring-mvc #jpa #spring-data-jpa #весна-данные
Вопрос:
У меня есть приложение веб-службы SpringBoot 2.1.4.RELEASE RESTful., использующее инициализатор Spring, встроенный Tomcat, механизм шаблонов Thymeleaf и пакет в виде исполняемого файла JAR. Я использую inMemoryDatabase: ядро базы данных H2
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
У меня есть эти объекты:
@Entity
@Table(name="t_menu_alert_notification")
public class MenuAlertNotification implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@JsonProperty("id")
private Long id;
@ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.REMOVE)
@JoinColumn(name = "menu_alert_id")
@JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="name")
@JsonIdentityReference(alwaysAsId=true)
protected MenuAlert menuAlert;
...
}
@Entity
@Table(name="t_menu_alert")
public class MenuAlert implements Serializable {
public MenuAlert() {
}
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "menu_id")
@JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="name")
@JsonIdentityReference(alwaysAsId=true)
Menu menu;
..
}
@Entity
@Table(name = "t_menu")
@JsonPropertyOrder({ "id", "name", "address", "description" })
public class Menu implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@JsonProperty("id")
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id", nullable = false)
@JsonIgnore
private User user;
..
}
У меня есть этот метод в классе репозитория, который расширяется из CrudRepository
@Transactional
@Modifying
@Query("update MenuAlertNotification n set n.read = :status where n.id in :notificationIdList and n.menuAlert.menu.user.id = :userId")
void changeMenuNotificationListReadStatus( @Param("notificationIdList") List<Long> notificationIdList,
@Param("userId") long userId,
@Param("status") boolean status);
}
Но когда я запускаю этот метод, у меня возникает эта ошибка:
org.springframework.dao.InvalidDataAccessResourceUsageException: could not prepare statement; SQL [update t_menu_alert_notification cross join set is_read=? where (id in (?)) and user_id=?]; nested exception is org.hibernate.exception.SQLGrammarException: could not prepare statement
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:279)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:253)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:209)
Caused by: org.hibernate.exception.SQLGrammarException: could not prepare statement
at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:106)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139)
... 51 more
Caused by: org.h2.jdbc.JdbcSQLException: Syntax error in SQL statement "UPDATE T_MENU_ALERT_NOTIFICATION CROSS[*] JOIN SET IS_READ=? WHERE (ID IN (?)) AND USER_ID=? "; expected "., AS, SET"; SQL statement:
update t_menu_alert_notification cross join set is_read=? where (id in (?)) and user_id=? [42001-197]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:357)
at org.h2.message.DbException.getSyntaxError(DbException.java:217)
at org.h2.command.Parser.getSyntaxError(Parser.java:555)
at org.h2.command.Parser.read(Parser.java:3518)
at org.h2.command.Parser.parseUpdateSetClause(Parser.java:785)
at org.h2.command.Parser.parseUpdate(Parser.java:780)
at org.h2.command.Parser.parsePrepared(Parser.java:485)
at org.h2.command.Parser.parse(Parser.java:335)
at org.h2.command.Parser.parse(Parser.java:311)
at org.h2.command.Parser.prepareCommand(Parser.java:278)
at org.h2.engine.Session.prepareLocal(Session.java:611)
at org.h2.engine.Session.prepareCommand(Session.java:549)
at org.h2.jdbc.JdbcConnection.prepareCommand(JdbcConnection.java:1247)
at org.h2.jdbc.JdbcPreparedStatement.<init>(JdbcPreparedStatement.java:76)
at org.h2.jdbc.JdbcConnection.prepareStatement(JdbcConnection.java:304)
at com.zaxxer.hikari.pool.ProxyConnection.prepareStatement(ProxyConnection.java:311)
at com.zaxxer.hikari.pool.HikariProxyConnection.prepareStatement(HikariProxyConnection.java)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$1.doPrepare(StatementPreparerImpl.java:87)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:172)
... 73 more
Комментарии:
1. используете ли вы базу данных h2 (hickari)?
2. Неявные
JOIN
s (n.menuAlert.menu.user
) не допускаются в операторах JPQLUPDATE
. Вам нужноSELECT
и затемUPDATE
Ответ №1:
Согласно официальной документации:
В массовом запросе HQL не могут быть указаны объединения, ни неявные, ни явные.
Итак, вам нужно сначала найти n.menuAlert
, а затем передать в качестве параметра в запрос обновления или использовать собственный запрос.