Guía de aprendizaje del gestor de entidades: esquema de entidades Order

Crear cuatro clases de entidades utilizando relaciones unidireccionales y bidireccionales, listas ordenadas y relaciones de claves foráneas. Las API de EntityManager se utilizan para persistir y encontrar las entidades. Basándose en las entidades Order y Customer que se encuentran en las partes anteriores de la guía de aprendizaje, este paso de la guía de aprendizaje añade dos entidades adicionales: las entidades Item y OrderLine.

Acerca de esta tarea

Figura 1. Esquema de entidades Order. Una entidad Order tiene una referencia a un cliente y cero o más OrderLines. Cada entidad OrderLine tiene una referencia a un sólo artículo e incluye la cantidad solicitada.
Esquema de entidades Order

Procedimiento

  1. Cree la entidad de cliente, que es parecida a los ejemplos anteriores.
    Customer.java
    @Entity
    public class Customer
    {
        @Id String id;
        String firstName;
        String surname;
        String address;
        String phoneNumber;
    }
  2. Cree la entidad Item, que mantiene información sobre un producto incluido en el inventario de la tienda como, por ejemplo, la descripción del producto, la cantidad y el precio.
    Item.java
    @Entity
    public class Item
    {
        @Id String id;
        String description;
        long quantityOnHand;
        double price;
    }
  3. Cree una entidad OrderLine. Cada Order tiene cero o más OrderLines, que identifican la cantidad de cada artículo en el pedido. La clave para OrderLine es una clave compuesta que consta del Order que es propietario de la OrderLine y un entero que asigna un número a el elemento de línea. Añada el modificador de persistencia en cascada a cada relación de sus entidades.
    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. Cree el objeto Order final, que tiene una referencia a Customer para el pedido y una colección de objetos 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; 
    } 

    Las cascada ALL se utiliza como modificador para líneas. Este modificador indica a EntityManager conectar en cascada la operación PERSIST y la operación REMOVE. Por ejemplo, si la entidad Order se mantiene o elimina, también se mantiene o eliminan todas las entidades OrderLine.

    Si una entidad OrderLine se elimina de la lista de líneas del objeto Order, la referencia se rompe. Sin embargo, la entidad OrderLine no se elimina de la memoria caché. Debe utilizar la API de supresión de EntityManager para eliminar entidades de la memoria caché. La operación REMOVE no se utiliza en la entidad de cliente o la entidad de artículo de OrderLine. Como resultado, la entidad de cliente permanece incluso si se elimina el pedido o el artículo cuando se elimina OrderLine.

    El modificador mappedBy indica una relación inversa con la entidad de destino. El modificador identifica qué atributo en la entidad de destino hace referencia a la entidad de origen, y el lado propietario de una relación uno con uno o muchos con muchos. En general podrá omitir el modificador. Si embargo, se visualiza un error para indicar que debe especificarse si WebSphere eXtreme Scale no puede descubrirlo automáticamente. Una entidad OrderLine que contiene dos tipos de atributos Order en una relación de muchos con uno, normalmente, genera el error.

    La anotación @OrderBy especifica el orden en el que cada entidad OrderLine debe aparece en la lista de líneas. Si la anotación no se especifica, las líneas aparecen en un orden arbitrario. Aunque las líneas se añaden a la entidad Order emitiendo ArrayList, que conserva el pedido, EntityManager no reconoce necesariamente el pedido. Cuando se emite el método find para recuperar el objeto Order de la memoria caché, el objeto de lista no es un objeto ArrayList.

  5. Cree la aplicación. En el siguiente ejemplo se muestra el objeto Order final, que tiene una referencia a Customer para el pedido y una colección de objetos OrderLine.
    1. Busque los artículos a solicitar, que luego se convierten en entidades gestionadas.
    2. Cree el elemento de línea y adjúntelo a cada artículo.
    3. Cree un pedido y asócielo a cada elemento de línea y el cliente.
    4. Persiste el pedido, que persiste automáticamente cada elemento de línea.
    5. Compromete la transacción, que desconecta cada entidad y sincroniza el estado de las entidades con la memoria caché.
    6. Imprimir la información del pedido. Las entidades OrderLine se clasifican automáticamente por el ID de OrderLine.
    Application.java
    
    static public void main(String [] args)
            throws Exception
        {
            ...
    
            // Añadir algunos elementos al inventario.
            em.getTransaction().begin();
            createItems(em);
            em.getTransaction().commit();
    
            // Crear un nuevo cliente con los artículos en su carro.
            em.getTransaction().begin();
            Customer cust = createCustomer();
            em.persist(cust);
    
            // Crear nuevo pedido y añadir un elemento de línea para cada artículo.
            // Cada elemento de línea se persiste automáticamente ya que la opción
    				// Cascade=ALL está establecida.
            Order order = createOrderFromItems(em, cust, "ORDER_1", 
    					new String[]{"1", "2"}, new int[]{1,3});
            em.persist(order);
            em.getTransaction().commit();
    
            // Imprimir el resumen de pedido
            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;
        }
    El paso siguiente será suprimir una entidad. La interfaz EntityManager tiene un método remove que marca un objeto como suprimido. La aplicación debe eliminar la entidad de todas las colecciones de relaciones antes de llamar al método remove. Edite las referencias y emita el método remove, o em.remove(object), como último paso.