【问题标题】:eclipselink jpa criteria reference unmapped columneclipselink jpa 标准参考未映射列
【发布时间】:2015-06-13 02:13:59
【问题描述】:

在编写 jpql 查询时,我可以使用 COLUMN() 引用未映射的列(我知道它是特定于 eclipselink 的)。 在使用 javax.persistence.criteria.CriteriaBuilder、javax.persistence.criteria.Predicate 等构建标准时,有什么方法可以引用未映射的列?

我面临的问题:我有带有全文搜索列的 postgresql 表。我不希望它映射到实体对象,但我希望在查询中使用 is(我还需要使用 CriteriaBuilder 进行查询)。


编辑:代码示例

我有一个表:X (id integer, name varchar, fts tsvector)

“fts”列是全文搜索索引数据。 我需要没有“fts”属性的实体类,比如:

@Entity class X {
    @Id Integer id;
    @Column String name;
}

因此永远不会获取 fts 数据(出于性能考虑),但我需要能够查询该列。我可以用 jpql 做到这一点: SELECT t FROM X t WHERE COLUMN('fts', t) IS NOT NULL;

但在构建标准时如何引用此类列:

Specification<Fts> spec = new Specification<Fts>() {
        @Override
        public Predicate toPredicate(Root<Fts> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
            return builder.notNull(root.<String>get("fts"));
        }
    };

其他选择: 如何在实体类中添加引用表列但从未获取的属性?我尝试添加 @Basic(fetchType = FetchType.LAZY) 但它不起作用并且在查询时获取值...

【问题讨论】:

  • 请输入代码。你是什​​么意思,“未映射的列” - 标有@Transient的那些?
  • @transient 是相反的情况 - 实体中的属性未映射到数据库列。
  • 不要误会我的意思,但对我来说,您的问题看起来更像是糟糕的设计问题。将您的 fts 放在单独的实体/表中,然后将您的获取类型定义为惰性。这意味着关系另一端的类将仅在请求时加载。
  • 我认为在表中包含我不想被获取的列并没有错,但我仍然想在查询中使用它们。 FTS 数据是一种情况,空间数据是另一种情况 - 您不需要获取该数据,但您想查找与某个区域匹配的记录...考虑如下查询:SELECT (all but 'fts' and 'spatial' columns) FROM表 WHERE fts 匹配 'xxx' AND 空间匹配 'area';

标签: java eclipselink jpa-2.0


【解决方案1】:

好的。我设法通过这种方式解决了它:

Specification<Fts> spec = new Specification<Fts>() {
        @Override
        public Predicate toPredicate(Root<Fts> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
            JpaCriteriaBuilder cb = (JpaCriteriaBuilder) builder;
            List<String> args = new ArrayList();
            args.add("FTS query");

            javax.persistence.criteria.Expression<Boolean> expr = cb.fromExpression(
              cb.toExpression(
                cb.function("", Boolean.class, cb.fromExpression(((RootImpl) root).getCurrentNode().getField("fts")))
              )
              .sql("? @@ to_tsquery(?)", args)
            );
            // getField() allows to reference column not mapped to Entity

            query.where(expr);

            return null; // or return cb.isTrue(expr); and then not need to set query.where()
        }
    };

【讨论】:

  • 您应该可以使用cb.toExpression(root) 而不是((RootImpl) root).getCurrentNode(),这会产生更简洁的代码恕我直言
猜你喜欢
  • 1970-01-01
  • 2011-04-27
  • 1970-01-01
  • 2013-05-08
  • 2012-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多