Eclipse+JSF+JPAで作るアプリ(5)―JPAのエンティティ
前回までに、Glassfishの設定、DBの設定、web.xml、persistence.xmlと設定ばかりでしたが、今回から数回に分けてJPAの実装を行います。
さて、早速ですが仕様を変更しました。
『本』をやめて、『映画』にしました。サムネイルやレィティングなどのGUIの要素を追加しやすいからです。
通常の業務系Webアプリケーションでは、ログインする仕組みがあるでしょうから、ユーザから作り出します。しかし、
- ユーザのエンティティから作成しようとすると、
- ユーザは、映画の貸出履歴の参照を持つため、そのエンティティも作成する必要があります。貸出履歴は、映画とユーザを参照を持つので、映画も必要です。
- 結局、映画のエンティティも作ります。
JPAについては、詳しくは説明せず、少し駆け足で記述していきます。
詳細は、寺田佳央さんのはじめての Java Persistence API | 寺田 佳央 - Yoshio Terada がわかりやすいでしょう。
今回の範囲では、
がメインです。
JPAのエンティティの作成
JPAでのエンティティとは、ER図のEや、BCE分析でのEを指し、データベースに保存するためのオブジェクトを指します。
『ユーザ』(User)には、以下の属性を持たせます。
属性 | 内容 |
---|---|
id | アプリケーションで一意となるID。 |
account | アカウント名。ユニークなキー。null禁止 |
password | パスワード |
name | 名前、null禁止 |
メールアドレス | |
isAdmin | 管理者か否か |
lendHistories | ユーザが借りた『貸出履歴』コレクション |
『貸出履歴』(LendHistory)には、以下の属性を持たせます。
属性 | 内容 |
---|---|
id | アプリケーションで一意となるID。 |
lend-user | 借りた『ユーザ』への参照 |
movie | 借りられた『映画』への参照 |
lend-date | 借りた日 |
due-date | 返却締切日。超えても特にペナルティはないです。 |
return-date | 返却日 |
review | レビュー(感想) |
starRating | 5つ星までの評価。GUIがあります。それを使いたいための属性です。 |
貸出履歴は、親に、UserとMovieを持つためライフサイクルが特殊になります。ここでは、簡略化しMovieとライフサイクルを共にするよう実装します。
簡単に言えばUserを削除しても、履歴は残ります。Movieを削除すると履歴は消えます。
『映画』(Movie)には、以下の属性を持たせます。
属性 | 内容 |
---|---|
id | アプリケーションで一意となるID。 |
title | タイトル、ユニークとする(厳密には違うかも)。null禁止 |
outline | あらすじ |
category | 映画のカテゴリ |
isLent | 貸出中か否か |
lendHistories | ユーザが借りた『貸出履歴』コレクション。親のオブジェクトの操作は伝播させます |
Eclipseには、この属性を記述し、getter/setterを自動生成させればほぼEntityクラスは完成です。
それでは実際のコードを見てみましょう。
エンティティはすべてsample.yourlibrary.entityパッケージです。
Userクラス
@Entity @Table(name="USERTBL") public class User { @Id @Column(name="ID") @GeneratedValue( strategy=GenerationType.TABLE) private long id; @Column(name="ACCOUNT", nullable=false, unique=true) private String account; @Column(name="PASSWORD") private String password; @Column(name="NAME", nullable=false) private String name; @Column(name="E_MAIL") private String email; @Column(name="IS_ADMIN") private boolean isAdmin = false; @OneToMany(mappedBy="lendUser") List<LendHistory> lendHistories; //setter, getter
- @Table(name="USERTBL") テーブル名の指定です。USERというテーブルは予約語なので当然作成できません。
- @Id @GeneratedValue( strategy=GenerationType.TABLE) @IdでJPAが勝手にIDを振ってくれます。strategyでどのように番号を振るかのロジックが変わります。SEQUENCEなどもありますが、RDBによってはサポートしていません。
- @Column(name="ACCOUNT", nullable=false, unique=true) カラム名、NULL禁止、ユニーク制約などを設定できます。
- @OneToMany(mappedBy="lendUser") 1対多の関係を定義します。
OneToManyは簡単です。
後ほどManyToOneが出てきますがそちらのJoinColumnと合わせて覚えてください。
多対多の定義はかなり複雑ですので機会があれば紹介します。
LendHistoryクラス
@Entity @Table( name= "LEND_HISTORY") public class LendHistory { @Id @GeneratedValue( strategy=GenerationType.TABLE) private long id; @Temporal(TemporalType.DATE) @Column(name="LEND_DATE") private Date lendDate; @Temporal(TemporalType.DATE) @Column(name="DUE_DATE") private Date dueDate; @Temporal(TemporalType.DATE) @Column(name="RETURN_DATE") private Date returnDate; @Column(name="REVIEW") private String review; @Column(name="STAR_RATING") private double starRating; @ManyToOne @JoinColumn(name = "MOVIE_ID", referencedColumnName = "ID") private Movie movie; @ManyToOne @JoinColumn(name = "LENDUSER_ID", referencedColumnName = " ID") private User lendUser; //setter, getter
- @ManyToOneです。OneToManyの定義でmappedByで指定した属性にマップされます。
- @JoinColumn(name = "LENDUSER_ID", referencedColumnName = "ID") このManyToOneとJoinColumnの2つの定義で、LendHistoryクラスのlendUserという参照は、LENDUSER_IDというフィールドを相手テーブルのIDの外部キーとして使うという意味になります。
Movieクラス
@Entity @Table( name="MOVIE" ) public class Movie { @Id @GeneratedValue( strategy=GenerationType.TABLE) private long id; @Column(name="TITLE", nullable=false) private String title; @Column(name="OUTLINE") private String outline; @Column(name="CATEGORY") private String category; @Column(name="IS_LENT") private boolean isLent = false; @OneToMany(mappedBy="movie", cascade=CascadeType.ALL ) List<LendHistory> lendHistories; //setter, getter
- CascadeTypeが出てきています。ALLでは次回で触れるEntityManger.persist,removeなどのすべての操作を子に伝播させます。