今回はエンティティを作るまで。次回はテストケースを書いて実行します。

Product(商品)とProductStock(商品在庫)は、お互いが誘導可能なコンポジション(商品が消えれば商品在庫も消える)。ProductStockのスーパークラスStock(在庫)を用意しておきました。
エンティティクラスは、EntityManagerのコンテキストに入れない限り、ただのPOJOですから、普通のDTOとして利用できます。しかし反対に、DTOとして設計したPOJOを、簡単にエンティティに変換できるとは限りません。
エンティティのルールに基づいて、DTOを作る。という手順が、上手な方法ではないでしょうか。POJOをキレイに設計すれば、煩雑なアクセサは激減するハズ!です(←狙いはココ)。
以下、エンティティのソースコードとコメントの羅列です。
Product.java
@Entity
public class Product implements Serializable {
private int id;
private String name;
private ProductStock productStock;
//アクセサにアノテーションを書く方法(property-based)が一般的だが、
//フィールドにアノテーションを書く方法(field-based)もある。
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
//↑この場合、システム全体でユニークな値になる。
// (と思う。hibernateの場合は、hibernate_sequence という
// デフォルトシーケンスから取得する。)
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
@Column(length=64)
//↑カラム属性を定義するときに使う。無ければ全部デフォルト。
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@OneToOne(
cascade=CascadeType.ALL, //カスケード
fetch=FetchType.EAGER //1対多ならLAZYの方が良いかも
)
public ProductStock getProductStock() {
return productStock;
}
public void setProductStock(ProductStock productStock) {
this.productStock = productStock;
}
//以下、NetBeansが生成するコードに習って。
@Override
public int hashCode() {
return (int)getId();
}
@Override
public boolean equals(Object object) {
if (!(object instanceof Product)) {
return false;
}
Product other = (Product)object;
if (this.getId() != other.getId()) return false;
return true;
}
}
ProductStock.java
@Entity
@SequenceGenerator(name="PRODUCT_STOCK_SEQ_GEN",
sequenceName="PRODUCT_STOCK_SEQ",
initialValue=1,allocationSize=1)
//↑利用するシーケンスを定義。
public class ProductStock extends Stock implements Serializable {
//ここでは、field-basedで書いてみた。この書き方にすると、
// persistence provider は、アクセサを経由しない。
@Id
@GeneratedValue(
strategy=GenerationType.SEQUENCE,
generator="PRODUCT_STOCK_SEQ_GEN")
//↑任意のシーケンスからIdを取得する。
private int id;
@OneToOne(mappedBy="productStock")
//↑ Product.productStockにマップ
//エンティティ名と違う名前にマップする場合に必要。
private Product product;
@Temporal(TemporalType.TIMESTAMP)
//↑java.util型を java.sql型に変換する方法
private Date updatedAt;
//以下、単なるアクセサ
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
public Product getProduct() {
return product;
}
public void setProduct(Product product) {
this.product = product;
}
public Date getUpdatedAt() {
return updatedAt;
}
public void setUpdatedAt(Date updatedAt) {
this.updatedAt = updatedAt;
}
@Override
public int hashCode() {
:
}
@Override
public boolean equals(Object object) {
:
}
}
Stock.java
@MappedSuperclass
//↑@Entityのスーパークラスであることを宣言
// このクラスを継承したエンティティは、
// このクラスのプロパティもテーブルカラムにマップする。
public class Stock {
private int amount;
private String status;
public int getAmount() {
return amount;
}
public void setAmount(int amount) {
this.amount = amount;
}
@Transient
//↑テーブルには入れたくないときに宣言する。
public String getStatus() {
if( this.amount <= 0 )
this.status = "在庫切れ";
else if( this.amount <= 10 )
this.status = "残少";
else
this.status = "在庫アリ";
return this.status;
}
public void setStatus(String status){
this.status = status;
}
}