为什么使用别名的本机删除查询在 Spring Data JPA 中不起作用?
Why does a native delete query using aliases not work in Spring Data JPA?
在 JPA Spring 数据中使用 DELETE 别名是否存在任何已知问题?同样的工作就像删除别名的魅力一样。
我有一个 JPA Spring 数据本机查询,如下所示:-
@Modifying
@Transactional
@Query(value = "delete from Customer d where d.name = ?1", nativeQuery = true)
public void removeOnName(String name);
这会引发如下异常:-
01:11:13.616 [main] WARN o.h.e.jdbc.spi.SqlExceptionHelper - SQL Error: 1064, SQLState: 42000
01:11:13.616 [main] ERROR o.h.e.jdbc.spi.SqlExceptionHelper - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'd where d.name = 'kiran'' at line 1
01:11:13.621 [main] WARN o.h.e.jdbc.spi.SqlExceptionHelper - SQL Warning Code: 1064, SQLState: 42000
01:11:13.621 [main] WARN o.h.e.jdbc.spi.SqlExceptionHelper - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'd where d.name = 'kiran'' at line 1
org.springframework.dao.InvalidDataAccessResourceUsageException: could not execute statement; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not execute statement
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:172)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:155)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:417)
at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:59)
at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:147)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodIntercceptor.invoke(CrudMethodMetadataPostProcessor.java:122)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
at com.sun.proxy.$Proxy91.removeDevciesOnGuid(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:483)
当我删除别名时查询执行正常。
工作查询如下:-
@Modifying
@Transactional
@Query(value = "delete from Customer where name = ?1", nativeQuery = true)
public void removeOnName(String name);
在 JPA Spring 数据中使用 DELETE 别名是否存在任何已知问题?同样的方法就像删除别名的魅力一样。
参考完成
该文档还显示使用别名 http://docs.spring.io/spring-data/jpa/docs/1.4.2.RELEASE/reference/html/jpa.repositories.html
来自文档:-
2.5.1 事务查询方式
要允许您的查询方法是事务性的,只需在您定义的存储库接口上使用@Transactional。
示例 2.20。在查询方法中使用@Transactional
@Transactional(readOnly = true)
public interface UserRepository extends JpaRepository<User, Long> {
List<User> findByLastname(String lastname);
@Modifying
@Transactional
@Query("delete from User u where u.active = false")
void deleteInactiveUsers();
}
通常您会希望将 readOnly 标志设置为 true,因为大多数查询方法只会读取数据。与 deleteInactiveUsers() 相比,它使用 @Modifying 注释并覆盖事务配置。因此,该方法将在 readOnly 标志设置为 false 的情况下执行。
您将 @Query
的 nativeQuery
标志设置为 true,因此查询按原样发送到服务器(在您的情况下为 Mysql)。 Mysql 不允许在 DELETE
中使用别名。将 nativeQuery
设置为 false 或不使用别名。
* 当然,还有一个选项可以使用,例如,SQLServer 可以接受这种语法而不是 Mysql :)
执行以下查询时出现错误的原因是它不是删除查询的正确 MySql 语法。您正在使用 nativeQuery 并且别名使用不正确。
正确的语法是:
"delete d from Customer as d where d.name=?1"
@Modifying
@Transactional
@Query(value = "delete d from Customer as d where d.name=?1", nativeQuery = true)
public void removeOnName(String name);
在 JPA Spring 数据中使用 DELETE 别名是否存在任何已知问题?同样的工作就像删除别名的魅力一样。 我有一个 JPA Spring 数据本机查询,如下所示:-
@Modifying
@Transactional
@Query(value = "delete from Customer d where d.name = ?1", nativeQuery = true)
public void removeOnName(String name);
这会引发如下异常:-
01:11:13.616 [main] WARN o.h.e.jdbc.spi.SqlExceptionHelper - SQL Error: 1064, SQLState: 42000
01:11:13.616 [main] ERROR o.h.e.jdbc.spi.SqlExceptionHelper - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'd where d.name = 'kiran'' at line 1
01:11:13.621 [main] WARN o.h.e.jdbc.spi.SqlExceptionHelper - SQL Warning Code: 1064, SQLState: 42000
01:11:13.621 [main] WARN o.h.e.jdbc.spi.SqlExceptionHelper - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'd where d.name = 'kiran'' at line 1
org.springframework.dao.InvalidDataAccessResourceUsageException: could not execute statement; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not execute statement
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:172)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:155)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:417)
at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:59)
at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:147)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodIntercceptor.invoke(CrudMethodMetadataPostProcessor.java:122)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
at com.sun.proxy.$Proxy91.removeDevciesOnGuid(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:483)
当我删除别名时查询执行正常。 工作查询如下:-
@Modifying
@Transactional
@Query(value = "delete from Customer where name = ?1", nativeQuery = true)
public void removeOnName(String name);
在 JPA Spring 数据中使用 DELETE 别名是否存在任何已知问题?同样的方法就像删除别名的魅力一样。
参考完成 该文档还显示使用别名 http://docs.spring.io/spring-data/jpa/docs/1.4.2.RELEASE/reference/html/jpa.repositories.html
来自文档:- 2.5.1 事务查询方式
要允许您的查询方法是事务性的,只需在您定义的存储库接口上使用@Transactional。
示例 2.20。在查询方法中使用@Transactional
@Transactional(readOnly = true)
public interface UserRepository extends JpaRepository<User, Long> {
List<User> findByLastname(String lastname);
@Modifying
@Transactional
@Query("delete from User u where u.active = false")
void deleteInactiveUsers();
}
通常您会希望将 readOnly 标志设置为 true,因为大多数查询方法只会读取数据。与 deleteInactiveUsers() 相比,它使用 @Modifying 注释并覆盖事务配置。因此,该方法将在 readOnly 标志设置为 false 的情况下执行。
您将 @Query
的 nativeQuery
标志设置为 true,因此查询按原样发送到服务器(在您的情况下为 Mysql)。 Mysql 不允许在 DELETE
中使用别名。将 nativeQuery
设置为 false 或不使用别名。
* 当然,还有一个选项可以使用,例如,SQLServer 可以接受这种语法而不是 Mysql :)
执行以下查询时出现错误的原因是它不是删除查询的正确 MySql 语法。您正在使用 nativeQuery 并且别名使用不正确。
正确的语法是:
"delete d from Customer as d where d.name=?1"
@Modifying
@Transactional
@Query(value = "delete d from Customer as d where d.name=?1", nativeQuery = true)
public void removeOnName(String name);