1

オブジェクトのリストを取得するときに、IDのみを持つ別のテーブルに基づいて結果をフィルタリングしたいと思います。オブジェクトはORMモデルでリンクされておらず、代わりにUUIDのみが含まれています。

すなわち:

@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がfalseであるか、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が「LEFTJOIN」の前に置かれているため、エラーが発生します。

「正しい」方法は、「privateUUIDrefB」を「privateBrefB」に置き換えることだと思います。ただし、そうすることで、特定のセキュリティ対策を回避しやすくなります。

これは可能ですか、それともRawSqlにすべての属性を追加する必要がありますか?

4

1 に答える 1

5

WHEREEbeanでのフィルタリングは、単に句を操作する以外の目的です。他の質問の比較を見てください。

ここに適切な方法があります(完全な動作サンプルを表示するようにモデルを変更しました)

モデル

@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 に答える