エンティティー・マネージャーのチュートリアル: Order エンティティー・スキーマ

単一方向と双方向の両方のリレーションシップ、順序リスト、および外部キー・リレーションシップを使用して、4 つのエンティティー・クラスを作成します。 エンティティーの永続化と検索には、EntityManager API を使用します。このチュートリアルの前の部分にある Order および Customer エンティティーを前提として、このチュートリアル・ステップでは、Item および OrderLine という 2 つのエンティティーをさらに追加します。

このタスクについて

図 1. Order エンティティー・スキーマ. Order エンティティーは、1 人のカスタマーへの参照と 0 個以上の OrderLine を持っています。 各 OrderLine エンティティーは、単一の Item を参照し、 オーダーされた数量を含みます。
Order エンティティー・スキーマ

手順

  1. Customer エンティティーを作成します。このエンティティーは、これまでの例と類似しています。
    Customer.java
    @Entity
    public class Customer
    {
        @Id String id;
        String firstName;
        String surname;
        String address;
        String phoneNumber;
    }
  2. Item エンティティーを作成します。このエンティティーには、ストアのインベントリーにある製品の情報 (製品説明、数量、価格など) が保持されています。
    Item.java
    @Entity
    public class Item
    {
        @Id String id;
        String description;
        long quantityOnHand;
        double price;
    }
  3. OrderLine エンティティーを作成します。 各 Order は、オーダー内の各品目の数量を示す 0 個以上の OrderLine を持っています。 OrderLine のキーは、OrderLine を所有する Order とオーダー行に数値を割り当てる整数から構成される複合キーです。 エンティティーの すべてのリレーションシップにカスケード永続化修飾子を追加します。
    OrderLine.java
    @Entity
    public class OrderLine
    {
        @Id @ManyToOne(cascade=CascadeType.PERSIST) Order order;
        @Id int lineNumber;
        @OneToOne(cascade=CascadeType.PERSIST) Item item;
        int quantity;
        double price;
    }
  4. 最終の Order オブジェクトを作成します。このオブジェクトは、オーダーに対応した Customer と OrderLine オブジェクトの集合を参照します。
    Order.java
    @Entity
    public class Order
    {
        @Id String orderNumber;
        java.util.Date date;
        @ManyToOne(cascade=CascadeType.PERSIST) Customer customer;
        @OneToMany(cascade=CascadeType.ALL, mappedBy="order") 
    			@OrderBy("lineNumber") List<OrderLine> lines; 
    } 

    cascade ALL は、行に対する修飾子として使用されます。この修飾子は、PERSIST 操作と REMOVE 操作をカスケードするように EntityManager に指示します。例えば、Order エンティティーを永続化または削除すると、 すべての OrderLine エンティティーも永続化または削除されます。

    Order オブジェクトの行リストから OrderLine エンティティーを削除すると、参照は破損されます。 ただし、OrderLine エンティティーはキャッシュからは削除されません。 キャッシュからエンティティーを削除するには、EntityManager remove API を使用する必要があります。REMOVE 操作は、OrderLine から Customer エンティティーまたは Item エンティティーで使用されることはありません。したがって、OrderLine を削除するときに Order または Item を削除しても、Customer エンティティーは残ります。

    mappedBy 修飾子は、ターゲット・エンティティーとの逆のリレーションシップを示しています。この修飾子は、 ソース・エンティティーを参照するターゲット・エンティティーの属性、 および 1 対 1 リレーションシップまたは多対多リレーションシップの所有側を指定します。通常、この修飾子は省略できます。ただし、WebSphere eXtreme Scale で自動的に検出できなかった場合、この修飾子を指定する必要があることを示すエラーが表示されます。 OrderLine エンティティーが、多対 1 リレーションシップにある型 Order 属性を 2 つ含む場合、通常はエラーが発生します。

    @OrderBy アノテーションは、各 OrderLine エンティティーが行リストに表示される順序を指定します。 このアノテーションを 指定しない場合は、行は任意の順序で表示されます。ArrayList を指定すると、行が Order エンティティーに追加されて、 順序が維持されますが、EntityManager では必ずしもこの順序が認識されるわけではありません。find メソッドを 実行して、キャッシュから Order オブジェクトを取得する場合、ArrayList オブジェクトはリスト・オブジェクトにはなりません。

  5. アプリケーションを作成します。 以下の例は、最終の Order オブジェクトを示し、オーダーに対応した Customer と OrderLine オブジェクトの集まりを参照します。
    1. オーダー対象であり、管理エンティティーとなる Item を検索します。
    2. OrderLine を作成し、各 Item に付加します。
    3. Order を作成し、各 OrderLine とそのカスタマーに関連付けます。
    4. オーダーを永続化します。この場合、各 OrderLine も自動的に永続化されます。
    5. トランザクションをコミットします。各エンティティーが切り離され、 エンティティーの状態がキャッシュと同期化されます。
    6. オーダー情報を出力します。OrderLine エンティティーは、OrderLine ID 別に自動的に分類されます。
    Application.java
    
    static public void main(String [] args)
            throws Exception
        {
            ...
    
            // Add some items to our inventory.
            em.getTransaction().begin();
            createItems(em);
            em.getTransaction().commit();
    
            // Create a new customer with the items in his cart.
            em.getTransaction().begin();
            Customer cust = createCustomer();
            em.persist(cust);
    
            // Create a new order and add an order line for each item.
            // Each line item is automatically persisted since the 
    				// Cascade=ALL option is set.
            Order order = createOrderFromItems(em, cust, "ORDER_1", 
    					new String[]{"1", "2"}, new int[]{1,3});
            em.persist(order);
            em.getTransaction().commit();
    
            // Print the order summary
            em.getTransaction().begin();
            order = (Order)em.find(Order.class, "ORDER_1");
            System.out.println(printOrderSummary(order));
            em.getTransaction().commit();
        }
    
        public static Customer createCustomer() {
            Customer cust = new Customer();
            cust.address = "Main Street";
            cust.firstName = "John";
            cust.surname = "Smith";
            cust.id = "C001";
            cust.phoneNumber = "5555551212";
            return cust;
        }
    
        public static void createItems(EntityManager em) {
            Item item1 = new Item();
            item1.id = "1";
            item1.price = 9.99;
            item1.description = "Widget 1";
            item1.quantityOnHand = 4000;
            em.persist(item1);
    
            Item item2 = new Item();
            item2.id = "2";
            item2.price = 15.99;
            item2.description = "Widget 2";
            item2.quantityOnHand = 225;
            em.persist(item2);
    
        }
    
        public static Order createOrderFromItems(EntityManager em, 
    			Customer cust, String orderId, String[] itemIds, int[] qty) {
    
            Item[] items = getItems(em, itemIds);
    
            Order order = new Order();
            order.customer = cust;
            order.date = new java.util.Date();
            order.orderNumber = orderId;
            order.lines = new ArrayList<OrderLine>(items.length);          
    			 for(int i=0;i<items.length;i++){
    						OrderLine line = new OrderLine();
                line.lineNumber = i+1;
                line.item = items[i];
                line.price = line.item.price;
                line.quantity = qty[i];
                line.order = order;
                order.lines.add(line);
            }
            return order;
        }
    
        public static Item[] getItems(EntityManager em, String[] itemIds) {
            Item[] items = new Item[itemIds.length];
            for(int i=0;i<items.length;i++){
    			 items[i] = (Item) em.find(Item.class, itemIds[i]);
            }
            return items;
        }
    次のステップでは、エンティティーを削除します。EntityManager インターフェースは、 削除対象にするオブジェクトにマークを付ける remove メソッドを備えています。アプリケーションでは、remove メソッドを呼び出す前に、 すべてのリレーションシップのコレクションからエンティティーを削除する必要があります。最終ステップとして、 参照を編集し、remove メソッド em.remove(object) を実行します。