有什么方法可以使用 JPA 查询更新 SET 类型的列吗?
Is there any way to update SET type column using JPA query?
我想做的是通过 JPA 查询更新 table 中的字段。
我将 MySQL table 设置为 SET 类型。
create table staff (
id BIGINT,
...
roles SET('A', 'B', 'C') not null,
...
)
和class
public class Staff {
private Long id;
@Converter(someConverterHere.class)
private Set<Role> roles;
}
我尝试按照下面的方式更新此字段
@Modifying
@Query("update Staff s SET s.roles = :newRoles where s.id = :id")
Integer updateStaffRoles(@Param("id") Long id, @Param("newRoles") Set<Role> newRoles);
然后,当我给这个 Set.of(Role.A, Role.B) 作为参数时,它向我显示了这样的错误,
Caused by: java.lang.IllegalArgumentException: Parameter value [A] did not match expected type [java.util.Set (n/a)]
at org.hibernate.query.spi.QueryParameterBindingValidator.validate(QueryParameterBindingValidator.java:54)
at org.hibernate.query.spi.QueryParameterBindingValidator.validate(QueryParameterBindingValidator.java:27)
at org.hibernate.query.internal.QueryParameterBindingImpl.validate(QueryParameterBindingImpl.java:90)
at org.hibernate.query.internal.QueryParameterBindingImpl.setBindValue(QueryParameterBindingImpl.java:55)
at org.hibernate.query.internal.QueryParameterBindingsImpl.expandListValuedParameters(QueryParameterBindingsImpl.java:636)
at org.hibernate.query.internal.AbstractProducedQuery.doExecuteUpdate(AbstractProducedQuery.java:1629)
at org.hibernate.query.internal.AbstractProducedQuery.executeUpdate(AbstractProducedQuery.java:1612)
at org.springframework.data.jpa.repository.query.JpaQueryExecution$ModifyingExecution.doExecute(JpaQueryExecution.java:238)
at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:88)
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:154)
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:142)
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor$QueryMethodInvoker.invoke(QueryExecutorMethodInterceptor.java:195)
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:152)
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:130)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:80)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:367)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:118)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139)
... 81 common frames omitted
jpa 查询生成器似乎验证了 newRoles 中的所有单个值并将其类型与 Staff.roles 的类型进行比较,这不能为真(角色和集合)
有什么办法可以解决吗?我找不到任何解决方案。
依赖性
- org.springframework.data:spring-data-jpa:2.3.2.RELEASE
============================================= ========
临时解决方案:
我将参数类型从 Set 更改为 Set 并且它有效。而现在,当使用 QueryDsl 时,这个问题就变成了问题。使用querydsl的“set”,这个问题又发生了:(
查询dsl
// newRoles : Set<Role>
// Error: IllegalArgumentException
query.set(QStaff.Staff.roles, newRoles));
// Of course, compile error
query.set(QStaff.Staff.roles, Set.of(newRoles)));
自定义类型需要由您的 JPA 实现中的自定义类型映射。对于通过 User Type 接口的 Hibernate。为了通过 QueryDSL 使用扩展类型,您需要为其创建自定义表达式类型。此外,对于您想要支持的任何操作(如集合包含、相等),您将必须注册自定义函数。可以做到,但不能使用常规的 API。您可能最好取消规范化元模型并改用 @ElementCollection
。但是,如果您坚持要上班,这里有一些建议:
hibernate-types
是一个广受欢迎的项目,它为 Hibernate 实现了许多自定义类型。它没有实现 SET,但您可以使用数组的实现作为基础。
hibernate-types-querydsl-apt
是一个为某些自定义类型扩展 QueryDSL 元模型生成的项目。您可能还应该模仿该存储库中的任何内容。
我想做的是通过 JPA 查询更新 table 中的字段。 我将 MySQL table 设置为 SET 类型。
create table staff (
id BIGINT,
...
roles SET('A', 'B', 'C') not null,
...
)
和class
public class Staff {
private Long id;
@Converter(someConverterHere.class)
private Set<Role> roles;
}
我尝试按照下面的方式更新此字段
@Modifying
@Query("update Staff s SET s.roles = :newRoles where s.id = :id")
Integer updateStaffRoles(@Param("id") Long id, @Param("newRoles") Set<Role> newRoles);
然后,当我给这个 Set.of(Role.A, Role.B) 作为参数时,它向我显示了这样的错误,
Caused by: java.lang.IllegalArgumentException: Parameter value [A] did not match expected type [java.util.Set (n/a)]
at org.hibernate.query.spi.QueryParameterBindingValidator.validate(QueryParameterBindingValidator.java:54)
at org.hibernate.query.spi.QueryParameterBindingValidator.validate(QueryParameterBindingValidator.java:27)
at org.hibernate.query.internal.QueryParameterBindingImpl.validate(QueryParameterBindingImpl.java:90)
at org.hibernate.query.internal.QueryParameterBindingImpl.setBindValue(QueryParameterBindingImpl.java:55)
at org.hibernate.query.internal.QueryParameterBindingsImpl.expandListValuedParameters(QueryParameterBindingsImpl.java:636)
at org.hibernate.query.internal.AbstractProducedQuery.doExecuteUpdate(AbstractProducedQuery.java:1629)
at org.hibernate.query.internal.AbstractProducedQuery.executeUpdate(AbstractProducedQuery.java:1612)
at org.springframework.data.jpa.repository.query.JpaQueryExecution$ModifyingExecution.doExecute(JpaQueryExecution.java:238)
at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:88)
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:154)
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:142)
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor$QueryMethodInvoker.invoke(QueryExecutorMethodInterceptor.java:195)
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:152)
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:130)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:80)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:367)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:118)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139)
... 81 common frames omitted
jpa 查询生成器似乎验证了 newRoles 中的所有单个值并将其类型与 Staff.roles 的类型进行比较,这不能为真(角色和集合)
有什么办法可以解决吗?我找不到任何解决方案。
依赖性
- org.springframework.data:spring-data-jpa:2.3.2.RELEASE
============================================= ========
临时解决方案:
我将参数类型从 Set 更改为 Set
查询dsl
// newRoles : Set<Role>
// Error: IllegalArgumentException
query.set(QStaff.Staff.roles, newRoles));
// Of course, compile error
query.set(QStaff.Staff.roles, Set.of(newRoles)));
自定义类型需要由您的 JPA 实现中的自定义类型映射。对于通过 User Type 接口的 Hibernate。为了通过 QueryDSL 使用扩展类型,您需要为其创建自定义表达式类型。此外,对于您想要支持的任何操作(如集合包含、相等),您将必须注册自定义函数。可以做到,但不能使用常规的 API。您可能最好取消规范化元模型并改用 @ElementCollection
。但是,如果您坚持要上班,这里有一些建议:
hibernate-types
是一个广受欢迎的项目,它为 Hibernate 实现了许多自定义类型。它没有实现 SET,但您可以使用数组的实现作为基础。hibernate-types-querydsl-apt
是一个为某些自定义类型扩展 QueryDSL 元模型生成的项目。您可能还应该模仿该存储库中的任何内容。