0

Play Framework 2.0.1 内で JPA と Ebean を調べて、ローカルのリレーショナル データベースで何が生成されるかを調べています。私のテストでは、MySQL のフォークである MariaDB を使用しています。

これまでのところ、モデル内の JPA アノテーションを使用して、データベース内にテーブルを正常に生成できました。別のエンティティとの OneToOne 関係、および別のエンティティとの OneToMany 関係を持つエンティティを設定する方法を確実に学びたいと思いました。

OneToOne:Employee持っているAddress

OneToMany: (s)Employeeを持っていますPet

テーブルにデータをすばやく入力し、情報の一部を表示し、テーブルから行を削除できる小さなアプリケーションをセットアップしました。私のセットアップを見たい人のための以下のコードは次のとおりです。

ルート

GET     /                   controllers.Application.index()
GET     /add                controllers.Application.addEmployee()
GET     /delete/:id         controllers.Application.deleteEmployee(id: Long)
GET     /employee/:id       controllers.Application.showEmployee(id: Long)

コントローラ

アプリケーション.java

public class Application extends Controller {

    public static Result index() {
        return ok(index.render("entry point"));
    }

    public static Result addEmployee() {
        // Create an employee.
        Employee employee = new Employee();     
        employee.firstName = "John";
        employee.lastName = "Doe";
        employee.salary = new BigDecimal(123456);

        // Create an address for the employee.
        Address address = new Address();
        address.city = "West Chester";
        address.country = "United States of America";
        address.postalCode = "19380";
        address.province = null;
        address.street = "45 Jingleheimer Drive";

        // Create pets for the employee.
        Pet pet = new Pet();
        pet.petString = "dog";
        Pet pet2 = new Pet();
        pet2.petString = "cat";

        employee.address = address;
        employee.pets.add(pet);
        employee.pets.add(pet2);
        employee.save();

        return ok(index.render("added an employee"));
    }

    public static Result showEmployee(Long id) {
        Employee e = Employee.get(id);
        //String s = e.address.street;
        return ok(employee.render(e));
    }

    public static Result deleteEmployee(Long id) {
        Employee.delete(id);
        return ok(index.render("deleted employee " + id));
    }
}

モデル

従業員.java

@Entity
public class Employee extends Model {
    @Id
    public Long employee_id;

    public String firstName;

    public String lastName;

    public BigDecimal salary;

    @OneToOne(cascade=CascadeType.ALL)
    @JoinColumn(name="owner_id")
    public Address address;

    @OneToMany(cascade=CascadeType.ALL)
    @JoinColumn(name="owner_id", referencedColumnName="employee_id")
    public List<Pet> pets;

    public static Employee get(Long id) {
        return find.byId(id);
    }

    public static void delete(Long id) {
        find.byId(id).delete();
    }

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

アドレス.java

@Entity
public class Address extends Model {
    @Id
    public Long address_id;

    public String street;

    public String city;

    public String province;

    public String country;

    public String postalCode;
}

Pet.java

@Entity
public class Pet extends Model {
    @Id
    public Long pet_id;
    public String petString;    
}

ビュー

employee.scala.html

@(employee: models.Employee)

@import helper._

@main("employee view") {

    <p>@employee.firstName</p>
    <p>@employee.lastName</p>
    <p>@employee.salary</p>
    <p>@employee.address.country</p>

    <p>@employee.pets(1).petString</p>

    @for(pet <- employee.pets) {
        <p>@pet.petString</p>
    }
}

localhost:9000/employee/1 のような URL を使用して上記のビューをレンダリングすると、ブラウザーに次のように表示されます。

John

Doe

123456

cat

dog

cat

住所の国が表示されないことに注意してください。また、コントローラーでアクセスして、NULL を出力するコマンド ウィンドウに出力しようとしました。

Addressただし、クラスにゲッターを追加すると、scala テンプレートで取得できることがわかりました。

追加する

public String getCity() {
    return city;
}

...

Address.java への結果は

John

Doe

123456

United States of America

cat

dog

cat

そのため、住所を設定して従業員に割り当てることができます (DB に表示されます)。また、従業員を削除すると、データベース内の住所が正しくカスケードされて削除されます。同様に、これは である Pet クラスでも機能しOneToManyます。Addressでは、プロパティにアクセスするためにゲッターを追加する必要があるのはなぜPetですか? Java アノテーションで 1 対 1 の関係が正しく設定されていませんか?

4

1 に答える 1

1

EBean は、プロパティへの直接アクセスによる遅延読み込みをサポートしていません。Java-Controller-Code 内では、ステートメントemployee.address.countryは のようなものに拡張されますemployee.getAddress().getCountry()。残念ながら、これはScala コード、特にテンプレートでは行われません

employee.pets(1).petString一方、 は に変換されemployee.pets.get(1).petStringます。これは、EBean LazyList が関係しているため、EBean が遅延ロードするのに十分です。

ゲッター/セッターに固執しないでください! 遊び!人々は、コントローラーで必要なデータを知り、クエリ時にそれを取得する必要があると主張しています。

public static Employee get(Long id) {
  return find.fetch("address").where().idEq(id).findUnique();
}
于 2012-05-26T14:18:14.430 に答える