3

Javaでplay 2.0.4を使用しています。play が提供するメモリ内データベースから値を保存して取得しようとしています (Ebean は基礎となる JPA 実装です)。サンプルコードは次のとおりです。

@NoobDisclaimer ("I'm fairly new to Play and JPA")
@Entity
public class User extends Model {

@Id
public Long id;

public String name;

// Does not fetch eagerly.
@ManyToOne(fetch=FetchType.EAGER)
private Role role; // Role extends Model { has id and name}

public static Finder<Long, User> find = new Finder<Long, User>(Long.class, User.class);

public static List<User> all() {
    List<User> allUsers = find.all();
    for (User u : allUsers) {
        System.out.println("User:" + u.id + "|" + u.name); // SOP1
        // System.out.println("Assoc Role:" + u.role.name); //SOP2
    }
    return allUsers;
}

public static void create(User user) {
    user.save();
}

}

index.scala.html では、@(users: List[User]、userForm: Form[User])

<h2>@users.size() user(s) found!</h2>
        <ul>
            @for(usr <- users) {
                <li>Name: @usr.name</li> <!-- Displayed -->
                <li>Role: @usr.role.name</li> <!-- Displays blank value -->
            }
        </ul>

問題は、コントローラーで User.all() を実行してそれをビューに送信すると、user.role がロードされない、つまり @usr.role.name が空白になることです。例外はありません。SQL デバッグをオンに設定し、Role テーブルへの外部キーが User テーブルに保存されていることを確認しました。User.all() メソッド (SOP2 を参照) でロール名を出力すると、クエリが起動され、ロール名が出力されます。ビューにも表示されます。

デフォルトでは、ロールは遅延ロードされ、テンプレートで PersistenceContext を使用してユーザーに関連付けられたロールをロードできないことを理解しています。しかし、熱心なフェッチは、オブジェクトに関連付けられたすべてのエンティティを取得するべきではありませんか? 私は Play と JPA にかなり慣れていないので、何かをロードするときに関連する各エンティティを経由せずにこれを機能させる方法を理解できません。足りないものはありますか?

関連するメモとして、遅延フェッチを使用する必要がある場合、ユーザーをフェッチするときにビューで user.role を使用できるようにするにはどうすればよいですか?

4

1 に答える 1

4

Ebean は基礎となる JPA 実装です

Ebean は JPA 実装ではありません。Ebean は、JPA 標準と少し共通点があります。アノテーションが JPA のものに似ているため、少し似ています。

問題の原因: Ebean は @ManyToMany アノテーションの fetch=... 属性をサポートしていません。

2 つの解決策:

  1. 注釈から fetch=... を削除し、代わりにplay.db.ebean.Model.Finder<I,T>オブジェクト ( を実装com.avaje.ebean.Query<T>) または com.avaje.ebean.Ebean オブジェクトのいずれかで fetch() メソッドを使用します。

    問題は、ここに 2 つの別個の永続ライブラリ (play.db.ebean と com.avaje.ebean) があり、それらの間の統合が課題であり問題であることです。
    たとえば、play.db.ebean.Model.Finder.fetch() メソッドはcom.avaje.ebean.Query<T> 、play.db.ebean.Model.Finder ではなく戻り値を返します。これは、play API モデル ヘルパーから離れてしまうため、役に立たないと思います。fetch() を呼び出した後は、Model.Finder メソッドを使用できなくなったようです。その時点では「ヘルパー」クラスはあまり使用されていません。
    正直なところ、フェッチ機能はまだ Play API のファーストクラスの機能ではないと思います。Avaje API に任せるのが最善です。

    Avaje API 内から fetch() を使用する 2 つの例:

    // single SQL query with a fetch join
    List<Order> l0 = Ebean.find(Order.class)
    .fetch("customer")
    .findList();
    

    // two separate SQL queries
    List<Order> l0 = Ebean.find(Order.class)
    .fetch("customer", new FetchConfig().query())
    .findList();
    

    注: Ebean の最後のリリース/更新 (バグ修正以外) は 2010 年 11 月 6 日で、丸 2 年前です。Ebean の取り込み率は非常に低いです。

  2. Play 内で JPA 2.0 実装を使用するように切り替えます。JPA の 2.0 リリースは非常に強力で、使いやすく、非常に広くサポートされています。それはおそらくイービーンの死を意味するでしょう。Play は次の構成機能を 2.0 に追加したことに注意してください (1.1 にはありませんでした) - Play が任意のプロバイダーからの JPA をより完全にサポートする方向に進んでいることを示唆しています。 http://www.playframework.org/documentation/2.0/JavaJPA

    これを行ったら、play.db クラスと com.avaje クラスの使用をやめてください。100% javax.persistence クラスを使用することをお勧めします。

于 2012-11-02T08:42:27.083 に答える