1

在检索对象列表时,我想根据我只有 ID 的另一个表过滤结果。对象未链接到 ORM 模型中,而是只包含一个 UUID。

IE:

@Entity
class A {
    @Id
    private UUID id;
    private UUID refB; // links to B
}

@Entity
class B {
    @Id
    private UUID id;
    private boolean visible;
}

我想检索 B.hidden 为假或 B 不存在的所有 A。

在 SQL 中,我会做类似的事情

SELECT t0.* FROM a_table t0 LEFT JOIN b_table t1 ON (t0.ref_b = t1.id)
    WHERE t1.hidden IS NULL OR t1.hidden = 0;

我不只是使用 RawSql 的原因是我找不到在选择中使用通配符的任何方法,因此必须在选择中维护和手动添加所有属性。

我也试过

List<A> listA = Ebean.find(A.class).where()
     .join("LEFT JOIN b_table t1 ON (t0.ref_b = t1.id)")
     .where().in("t1.hidden", "0", "NULL");

但后来我收到一个错误,因为 WHERE 放在“LEFT JOIN”之前。

我认为“正确”的方法是将“private UUID refB”替换为“private B refB”。但这样做会更容易规避某些安全措施。

这是可能的还是我必须在 RawSql 中添加所有属性?

4

1 回答 1

5

Ebean 中的过滤不仅用于操作WHERE子句,还有其他目的,请查看其他问题中的比较。

在这里,您有一个正确的方法(我更改了模型以显示完整的工作示例)

楷模

@Entity
public class A extends Model {

    @Id
    public Integer id;

    @ManyToOne
    public B b;

    public static Finder<Integer, A> find
                = new Finder<Integer, A>(Integer.class, A.class);

}

@Entity
public class B extends Model {

    @Id
    public Integer id;
    public Boolean hidden;

    public static Finder<Integer, B> find
            = new Finder<Integer, B>(Integer.class, B.class);

}

控制器

public static Result index() {

    // Insert some data one every request
    B bFalse = new B();
    bFalse.hidden = false;
    bFalse.save();

    B bTrue = new B();
    bTrue.hidden = true;
    bTrue.save();

    A a1 = new A();
    a1.b = bFalse;
    a1.save();

    A a2 = new A();
    a2.b = bTrue;
    a2.save();

    A a3 = new A();
    a3.b = bTrue;
    a3.save();

    // Let's search...
    List<A> aListOfNotHidden = A.find.where().and(Expr.eq("b.hidden", false), Expr.isNotNull("b.hidden")).findList();
    for (A a : aListOfNotHidden) {
        Logger.info("NOT hidden " + a.id);
    }

    List<A> aListOfHidden = A.find.where().eq("b.hidden", true).findList();
    for (A a : aListOfHidden) {
        Logger.warn("HIDDEN " + a.id);
    }

    return ok("check logs in your console");
}

H2的结果SQL

-- all NOT hidden
select t0.id c0, t0.b_id c1
from a t0
left outer join b t1 on t1.id = t0.b_id
where (t1.hidden = false  and t1.hidden is not null ) 

-- all hiden
select t0.id c0, t0.b_id c1 
from a t0
left outer join b t1 on t1.id = t0.b_id  
where t1.hidden = true 

或者,您也可以使用SqlQuery仅获取SqlRows(不是对象)检查链接的 API 以获取使用示例、设置命名参数等:

List<SqlRow> rows = Ebean.createSqlQuery("select t0.*  " +
        "from a t0 left outer join b t1 on t1.id = t0.b_id " +
        "where (t1.hidden = false  and t1.hidden is not null ) ").findList();


for (SqlRow row : rows) {
    // do something with each row here, use methods such 
    // as getString("fieldname") for retrieving data  
    // (from SqlRow API)
}
于 2012-11-24T15:54:43.717 回答