当前位置: 首页 > 知识库问答 >
问题:

在具有@convert的字段上创建路径时引发的IllegalArgumentException

邹玮
2023-03-14

我试图构建一个条件查询,并为每个传入的过滤器构建一个谓词“and”连接,例如。

CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Long> criteriaQuery = criteriaBuilder.createQuery(Long.class);
Root<T> entityRoot = criteriaQuery.from(SampleEntity.class);
// for each filterable field create a Predicate and included in as `criteriaQuery.where(...)`
criteriaQuery.select(criteriaBuilder.count(entityRoot));
entityManager.createQuery(criteriaQuery).setMaxResults(maxResult).getSingleResult();
Path<?> path = PathBuilder.buildFromFieldName(fieldName, rootEntity);
public static <T> Path<?> buildFromFieldName(String fieldName, Root<T> entity) throws IllegalArgumentException {
    Path<?> path = entity;
    List<String> fieldNames = Arrays.asList(fieldName.split("\\."));
    for (String fieldNamePath : fieldNames) {
        path = path.get(fieldNamePath);
    }
    return path;
}

在下面的示例中,嵌套字段将出现,例如命名为mychild.myset

@Entity
@Table(name = "T_SAMPLE")
public class SampleEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Embedded
    private SampleChildEntity myChild;
}

@Embeddable
public class SampleChildEntity {

    @Convert(converter = CommaSeparatedSetConverter.class, attributeName = "mySet")
    private Set<String> mySet = new HashSet<>();

}

在此示例中,当调用CriteriaBuilder.ismember(filterValue,path)时,会引发以下异常(“filterValue”是要比较的值,例如搜索字符串)。

原因:在方法buildFromFieldName中,首先从根实体(SampleEntity)创建路径。然后它的类型为org.hibernate.query.criteria.internal.path.rootimpl。当在for循环中处理fieldNamePathMyChild时,将重新创建路径。然后,它的类型为org.hibernate.query.criteria.internal.path.SingularAttributePath,并且在处理最后一个fieldNamePathMySet时保持不变。只有当删除@convert时,类型才会更改为org.hibernate.query.criteria.internal.path.PluralAttributePath,因为它是集合类型。

java.lang.IllegalArgumentException: unknown collection expression type 
        [org.hibernate.query.criteria.internal.path.SingularAttributePath]

    at org.hibernate.query.criteria.internal.CriteriaBuilderImpl.isMember(CriteriaBuilderImpl.java:1324)
    [... stack trace contains further local classes ...]

所以原因是SampleChildEntity中的@converton字段MySet。Hibernate看到类型set ,但不使用pluralattributePath,而是使用singularattributePath,这会导致问题。如果没有@convert,它就可以工作,但删除转换器不是一个选项。

有什么办法能奏效吗?路径是否可以以不同的方式创建?

共有1个答案

仲智
2023-03-14

通过@convert使用转换器的持久属性是一个基本属性,因此是SingularAttribute,所以看到SingularAttributePath是完全正确的。假设可以对这样一个单数属性使用复数谓词是错误的。Hibernate无法将其转换为SQL,因为它不知道转换器的功能。我猜列代表一个逗号分隔的列表?在这种情况下,您将使用例如like谓词来编写过滤器。类似于这样:

WHERE alias.myChild.mySet = :filterValue 
   OR alias.myChild.mySet LIKE CONCAT(:filterValue, ';%') 
   OR alias.myChild.mySet LIKE CONCAT(CONCAT('%;', :filterValue), ';%') 
   OR alias.myChild.mySet LIKE CONCAT('%;', :filterValue)

将此转换为JPA标准应该很容易。

 类似资料:
  • 问题内容: 我有一个名为的表,我想对它们进行排序,以表最填写的顺序。每个列都是JSONB列或TEXT列。我并不需要很确定,因此通常我按以下顺序订购: 但是,这很慢,因此我想创建一个索引。但是,这不起作用: 也没有 不能说我很惊讶。声明此索引的正确方法是什么? 问题答案: 要测量文本表示形式中行的大小,您可以将整个行都转换为文本,这比连接单个列要快得多: 但是索引中的此表达式存在3(或4)个问题:

  • 路径文字是指沿着开放或封闭的路径排列的文字。当您水平输入文本时,字符的排列会与基线平行。当您垂直输入文本时,字符的排列会与基线垂直。无论是哪种情况,文本都会沿路径点添加到路径上的方向来排列 沿路径输入文本 1执行下列操作之一: •要沿路径创建横排文本,请选择文字工具 或路径文字工具 。 •要沿路径创建直排文本,请选择直排文字工具 或直排路径文字工具 。 2(可选)在 “控制 ”面板、 “字符 ”面

  • 问题内容: 这是具有3列(ID,UNIQUE_VALUE,UNIQUE_GROUP_ID)的示例表 我希望下面的记录可以被允许: 或者 或( 注:这种情况是不允许的,也不) 并且这些是不允许的: 我在最后2列上创建了唯一索引,但是仅允许前2个示例。 仅当两者都不为null时,才可以让db检查这两列的唯一性吗? 问题答案: 您只想对和都不为空的行实施唯一性。为此,您可以使用基于函数的唯一索引:

  • 问题内容: 我需要为一个表创建一个timestamp字段,该表的行在一定时间后需要过期。如果我使用以下内容: 它以一种人类可读的格式显示时间,如果我可以将时间设置为纪元时间,则可以轻松得多,这样我就可以用几秒钟的时间进行计算。有没有一种方法可以创建一个字段,当默认情况下以纪元时间创建行时,该字段将显示当前时间?谢谢! 问题答案: 您可能希望在语句中使用该函数,如以下示例所示:

  • 问题内容: 在hibernate状态下使用sqlserver方言。 我希望hibernate在创建表时使用带引号的标识符。 除了重命名字段外,还有其他任何处理方法的想法吗? 问题答案: 遇到相同的问题,但表名为。如果你设定 然后所有数据库标识符将被引用。 在这里找到我的答案 表名称中的特殊字符hibernate给出错误 并在这里找到所有可用的设置 https://docs.jboss.org/hi

  • 路径文字是指沿着开放或封闭的路径排列的文字。当您水平输入文本时,字符的排列会与基线平行。当您垂直输入文本时,字符的排列会与基线垂直。无论是哪种情况,文本都会沿路径点添加到路径上的方向来排列。 在路径上输入文本 执行下列操作之一: 要沿路径创建横排文本,请选择文字工具 或路径文字工具 。 要沿路径创建直排文本,请选择直排文字工具 或直排路径文字工具 。 (可选)在“控制”面板、“字符”面板或“段落”