Lernprogramm zum EntityManager: Schema für die Entität "Order"

Erstellen Sie vier Entitätsklassen mit unidirektionalen und bidirektionalen Beziehungen, sortierten Listen und Fremdschlüsselbeziehungen. Die EntityManager-APIs werden verwendet, um die Entitäten zu suchen und persistent zu speichern. Aufbauend auf den Entitäten"Order" und "Customer", die in den verschiedenen Teilen des Lernprogramms verwendet werden, werden in diesem Schritt des Lernprogramms zwei weitere Entitäten hinzugefügt: Item und OrderLine.

Informationen zu diesem Vorgang

Abbildung 1. Schema für die Entität "Order". Eine Entität "Order" (Auftrag) hat eine Referenz auf einen Kunden (Customer) und keiner oder mehreren Auftragspositionen (OrderLine). Jede Entität "OrderLine" hat eine Referenz auf einen einzelnen Artikel (Item) und enthält die bestellte Menge.
Entitätsschema Order

Vorgehensweise

  1. Erstellen Sie die Entität "Customer", ähnlich wie in den vorherigen Beispielen.
    Customer.java
    @Entity
    public class Customer
    {
        @Id String id;
        String firstName;
        String surname;
        String address;
        String phoneNumber;
    }
  2. Erstellen Sie die Entität "Item", die Informationen zu einem Produkt enthält, das im Lagerbestand enthalten ist, z. B. Produktbeschreibung, Menge oder Preis.
    Item.java
    @Entity
    public class Item
    {
        @Id String id;
        String description;
        long quantityOnHand;
        double price;
    }
  3. Erstellen Sie die Entität "OrderLine". Jeder Auftrag hat keine oder mehrere Auftragspositionen, die die Menge jedes Artikels im Auftrag angeben. Der Schlüssel für die Auftragspositionen ist ein Verbundschlüssel, der sich aus dem Auftrag zusammensetzt, der Eigner der Auftragsposition ist, und eine ganze Zahl, die der Auftragsposition eine Nummer zuweist. Fügen Sie den Modifikator "cascade persist" jeder Beziehung in Ihren Entitäten hinzu.
    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. Erstellen Sie das endgültige Auftragsobjekt (Order), das eine Referenz auf den Kunden (Customer) für den Auftrag und eine Sammlung von Auftragspositionsobjekten (OrderLine) enthält.
    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;  } 

    Der Modifikator "cascade ALL" wird als Modifikator für Positionen verwendet. Dieser Modifikator signalisiert dem EntityManager, sowohl die Operation to PERSIST als auch die Operation REMOVE zu kaskadieren. Wenn beispielsweise die Entität "Order" persistent gespeichert oder entfernt wird, werden auch alle OrderLine-Entitäten persistent gespeichert bzw. entfernt.

    Wenn eine OrderLine-Entität aus der Positionsliste im Order-Objekt entfernt wird, ist die Referenz ungültig. Die OrderLine-Entität wird jedoch nicht aus dem Cache entfernt. Sie müssen die EntityManager-API "remove" verwenden, um Entitäten aus dem Cache zu entfernen. Die Operation REMOVE wird nicht für die Customer-Entität und die Item-Entität aus dem OrderLine-Objekt verwendet. Deshalb bleibt die Customer-Entität erhalten, obwohl der Auftrag bzw. der Artikel entfernt wird, wenn die Auftragsposition entfernt wird.

    Der Modifikator "mappedBy" gibt eine Umkehrbeziehung mit der Zielentität an. Der Modifikator gibt an, welches Attribut in der Zielentität auf die Quellenentität und die Eignerseite einer 1:1- oder N:N-Beziehung verweist. Gewöhnlich können Sie den Modifikator weglassen. Es wird jedoch ein Fehler angezeigt, in dem Sie darauf hingewiesen werden, dass der Modifikator angegeben werden muss, wenn WebSphere eXtreme Scale den Modifikator nicht automatisch erkennen kann. Eine OrderLine-Entität, die zwei Attribute vom Typ "Order" in einer N:1-Beziehung enthält, ist gewöhnlich für diesen Fehler verantwortlich.

    Die Annotation "@OrderBy" gibt die Reihenfolge an, in der die OrderLine-Entitäten in der Positionsliste aufgeführt werden sollen. Wenn die Annotation nicht angegeben wird, werden die Positionen in beliebiger Reihenfolge angezeigt. Obwohl die Positionen der Order-Entität über das Absetzen von ArrayList hinzugefügt werden, bei dem die Reihenfolge eingehalten wird, erkennt der EntityManager die Reihenfolge nicht zwingenderweise. Wenn Sie die Methode "find" ausführen, um das Order-Objekt aus dem Cache abzurufen, ist das Listenobjekt kein ArrayList-Objekt.

  5. Erstellen Sie die Anwendung. Im folgenden Beispiel wird das endgültige Auftragsobjekt (Order) veranschaulicht, das eine Referenz auf den Kunden (Customer) für den Auftrag und eine Sammlung von Auftragspositionsobjekten (OrderLine) enthält.
    1. Suchen Sie die zu bestellenden Artikel, die dann zu verwalteten Entitäten werden.
    2. Erstellen Sie die Auftragsposition, und ordnen Sie sie jedem Artikel zu.
    3. Erstellen Sie den Auftrag, und ordnen Sie ihn jeder Auftragsposition und dem Kunde zu.
    4. Speichern Sie den Auftrag persistent, woraufhin automatisch alle Auftragspositionen persistent gespeichert werden.
    5. Schreiben Sie die Transaktion fest, woraufhin alle Entitäten freigegeben werden und der Status der Entitäten mit dem Cache synchronisiert wird.
    6. Geben Sie die Auftragsdaten aus. Die OrderLine-Entitäten werden automatisch nach OrderLine-ID sortiert.
    Application.java
    
    static public void main(String [] args)
            throws Exception
        {
            ...
    
            // Dem Bestand einige Artikel hinzufügen.
            em.getTransaction().begin();
            createItems(em);
            em.getTransaction().commit();
            // Neuen kunden mit den Artikeln im Einkaufskorb erstellen.
            em.getTransaction().begin();
            Customer cust = createCustomer();
            em.persist(cust);
    
            // Neuen Auftrag erstellen und für jeden Artikel eine Auftragsposition hinzufügen.
            // Jede Position wird automatisch persistent gespeichert, da die Option
        				// Cascade=ALL definiert ist.
                    Order order = createOrderFromItems(em, cust, "ORDER_1",
    					new String[]{"1", "2"}, new int[]{1,3});
            em.persist(order);
            em.getTransaction().commit();
            // Auftragszusammenfassung ausgeben
            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;
        }
    Der nächste Schritt ist das Löschen einer Entität. Die Schnittstelle "EntityManager" enthält eine Methode "remove", die ein Objekt als gelöscht markiert. Die Anwendung muss die Entität aus allen Beziehungssammlungen entfernen, bevor sie die Methode "remove" aufruft. Als letzten Schritt bearbeiten Sie die Referenzen und führen die Methode "remove" oder "em.remove(object)" aus.