【问题标题】:QuerySyntaxException with enum带有枚举的 QuerySyntaxException
【发布时间】:2020-04-19 22:56:58
【问题描述】:

我有一个这样的 UserAssignmentRole 类:

@Data
@Entity
public class UserAssignmentRole {
    ...
    @Enumerated(EnumType.STRING)
    public Role role;
}

而Role是枚举,看起来是这样的:

public enum Role{
    admin,
    member,
    pending
}

现在,当我在我的存储库中尝试查询以选择具有管理员角色的所有内容时,它给了我错误:

@Query("select uar from UserAssignmentRole uar where uar.role=Role.admin")
public List<UserAssignmentRole> listAdmin(Long userID, Long assignmentID);

如何解决?

错误:org.hibernate.hql.internal.ast.QuerySyntaxException:无效路径:'Role.admin'

完全错误:https://pastebin.com/tk9r3wDg

【问题讨论】:

  • 您是否使用了完全限定类来枚举?带包。或者你可能在这里找到答案:stackoverflow.com/questions/18402988/…
  • 你把枚举放在哪里了?您可以尝试将枚举定义移动到 UserAssignmentRole

标签: spring spring-boot spring-mvc jpa h2


【解决方案1】:

这是自 5.2.x 以来 Hibernate 的一种奇怪但有意的行为 枚举值是一个常量,并且您使用的是非常规命名(小写)

看看this issue 和 Vlad Mihalcea 对performance penalty 的详细解释。

如果您使用非常规 Java 常量,则必须将 hibernate.query.conventional_java_constants 配置属性设置为 false。这样,Hibernate 将退回到之前的行为,将任何表达式视为 Java 常量的可能候选者。

【讨论】:

    【解决方案2】:

    您可以尝试不要自己编写此 sql,而是使用存储库创建这样的代码:

    @Repository
    public interface UserAssignmentRolelRepository extends JpaRepository<UserModel, Long>{
    
        public List<UserAssignmentRole> findByRole(Role role);
    
    }
    

    然后:

    @Autowired
    UserAssignmentRolelRepository repository ;
    
    public void someMethod(){
       List<UserAssignmentRole> userAssignmentRoles = repository.findByRole(Role.admin);
    }
    

    更新 1

    正如in this answer 指出的那样:非常规命名。您可以将枚举中的标签更改为大写。

    public enum Role{
        Admin,
        Member,
        Pending
    }
    

    然后:

    @Query("select uar from UserAssignmentRole uar where uar.role=com.example.package.Role.Admin")
    public List<UserAssignmentRole> listAdmin(Long userID, Long assignmentID);
    

    更新 2

    但如果你真的想在 DB 中使用小写字母。 它需要更多的代码来改变。枚举更改为:

    public enum Role{
        Admin("admin"),
        Member("member"),
        Pending("pending");
    
        private String name;
    
        Role(String name) {
            this.name = name;
        }
    
        public String getName() { return name; }
    
        public static Role parse(String id) {
            Role role = null; // Default
            for (Role item : Role.values()) {
                if (item.name.equals(id)) {
                    role = item;
                    break;
                }
            }
            return role;
        }
    }
    

    UserAssignmentRole

    //    @Enumerated(EnumType.STRING)
        @Convert(converter = RoleConverter.class)
        private Role role;
    

    还有额外的课程:

    import javax.persistence.AttributeConverter;
    import javax.persistence.Converter;
    
    @Converter(autoApply = true)
    public class RoleConverter implements AttributeConverter<Role, String> {
    
        @Override
        public String convertToDatabaseColumn(Role role) {
            return role.getName();
        }
    
        @Override
        public Role convertToEntityAttribute(String dbData) {
            return Role.parse(dbData);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-20
      • 1970-01-01
      相关资源
      最近更新 更多