有什么方法可以使用JPA查询更新SET类型列?

问题描述

我想做的是通过JPA查询更新表中的字段。 我将MysqL表设置为SET类型。

create table staff (
   id    BIGINT,...
   roles  SET('A','B','C')    not null,...
)

和班级

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的“集合”,此问题再次发生:(

Querydsl

// newRoles : Set<Role>
// Error: IllegalArgumentException
query.set(QStaff.Staff.roles,newRoles));

// Of course,compile error
query.set(QStaff.Staff.roles,Set.of(newRoles)));

解决方法

自定义类型需要通过JPA实现中的自定义类型进行映射。对于Hibernate,这是通过“用户类型”界面进行的。为了通过QueryDSL使用扩展类型,您需要为其创建自定义表达式类型。此外,对于您要支持的任何操作(例如set包含,相等),您都必须注册自定义函数。可以完成,但不能使用常规API。您最好关闭对元模型的规范化,而使用@ElementCollection。但是,如果您坚持要上班,这里有一些提示:

  • hibernate-types是一个广受欢迎的项目,为Hibernate实现了许多自定义类型。它没有实现SET,但是您可以使用数组的实现作为基础。
  • hibernate-types-querydsl-apt是一个项目,用于扩展某些自定义类型的QueryDSL元模型生成。您可能还应该模仿该存储库中的任何集。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...