1

假设这些是我的实体:

表1.java

@Entity
public class Table1 {

    // Many to one
    private Table2 table2;

    // Raw attributes
    // ...

}

表2.java

@Entity
public class Table2 {

    // Many to one
    private Table3 table3;

    // Raw attributes
    // ...

}

表3.java

@Entity
public class Table3 {

    // Raw attributes
    private String lang; // "fr", "en", "de"...

}

当我想列出属性为的所有行时Table1,我这样做:table2.table3.langen

Query query = entityManager.createQuery("SELECT t1 FROM Table1 t1 WHERE t1.table2.table3.lang = :lang");
query.setParameter("lang", "en");

也就是说,我怎样才能对先前填充的查询执行该查询Iterable<Table1>?只有可行吗?如果不使用 Hibernate,那么使用什么?例如,即使我知道下面的代码不起作用,例如:

Set<Table1> set = new HashSet<Table1>();
set.add(new Table1(INIT_DEFAULT_VALUES));
set.add(new Table2(INIT_DEFAULT_VALUES));
set.add(new Table3(INIT_DEFAULT_VALUES));

Query query = entityManager.createQuery("SELECT t1 FROM :set t1 WHERE t1.table2.table3.lang = :lang");
query.setParameter("set", set);
query.setParameter("lang", "en");

对于那些想知道为什么我需要这样的东西的人,我正在使用Apache Lucene在行中执行用户的搜索,这些Table1行之前也由 Lucene 索引。一旦我得到一些结果,我必须在返回的列表上提出一些过滤器/排序,例如选择链接Table3实体的语言。

任何建议将不胜感激:)

4

1 回答 1

1

Hibernate 查询被翻译成 SQL 查询并在数据库中执行。如果该集合包含不在数据库中的实体实例,则 Hibernate 无法查询它们。

如果这些实体实际上是数据库中的实体,正如您所指出的,那么您可能只使用一个IN子句:

Set<Long> ids = createSetOfIdsFromEntities(set);
String hql = select t1 FROM Table1 t1 WHERE t1. id in (:ids) and t1.table2.table3.lang = :lang";
...

但是请确保您没有太多的 ID,并且您没有达到数据库施加的限制(例如,Oracle 将 IN 子句的元素限制为 1000)。

如果这些实体已经加载到内存中,您也可以遍历它们:

Set<Table1> found = new HashSet<Table1>();
for (Table1 t1 : set) {
    if (t1.getTable2().getTable3().getLang().equals(theLang)) {
        found.add(t1);
    }
}
于 2012-06-06T10:19:01.950 回答