DEPARTAMENTO DE SISTEMAS Arquitecturas de Software Entity Beans Agenda DEPARTAMENTO DE SISTEMAS Generalidades de las entidades JEE Propósito Conceptos Características Mapeo con la BD Administración de Entidades Apoyo al desarrollo de aplicaciones Helpers Listener Finders Configuración Generalidades DEPARTAMENTO DE SISTEMAS Simplificar el modelo de persistencia: modelos livianos en términos de Programación Deployment Ejecución Modelo del polimorfismo Mapeo O/R Uso extensivo de las capacidades de consulta Mezcla de experiencias reunidas en un API (Java Persistence API) dominio en términos Hibernate, JDO, TopLink, EJB objetos: herencia, Generalidades DEPARTAMENTO DE SISTEMAS • Enterprise Java Beans 3.0 Persistence o o o o Especificación creada por SUN Persistencia de POJOs a cualquier RDBMS Requiere Java 5 Uso de anotaciones y generics Tomado de: http://edocs.bea.com/kodo/docs41/full/html/ejb3_overview_arch.html Generalidades DEPARTAMENTO DE SISTEMAS • EntityManagerFactory o • Persistence o • o Objetos persistentes EntityTransaction o • Interface usada para persistencia de EJBs Fábrica para instancia de queries Entity o • Contiene métodos de clase (estáticos) para obtener instancias de EntityManagerFactory EntityManager o • Factory para EntityManagers Manejo de transacciones entre entities Query o Interface implementada por cada fabricante para encontrar objetos persistente EJB Query Language (JPQL) Structured Query Language (SQL) Conceptos DEPARTAMENTO DE SISTEMAS Entidad es un POJO Plain Old Java Object + anotaciones @Entity public class miEntidadBean { ... } Conceptos (cont.) DEPARTAMENTO DE SISTEMAS Objetos de negocio representados por un componente que facilita su administración y búsqueda Representan una visión orientada-objetos de una colección de entidades persistentes Se encuentran en algún repositorio de datos o son proveídos por un sistema de información externo El bean de entidad sobrevive a la sesión y a fallas en el sistema Cada instancia de un bean de entidad tiene una identificación única que corresponde a la llave primaria en el repositorio Ejemplo DEPARTAMENTO DE SISTEMAS @Entity public class Customer implements Serializable { private Long id; private String name; private Address address; // No argument constructor public Customer() {} @Id public Long getID() { return id; } private void setID (Long id) { this.id = id; }… Clase de Entidad DEPARTAMENTO DE SISTEMAS Debe tener la anotación javax.persistence.Entity y en ciertos casos implementar Serializable @Entity(access=AccessType.FIELD) public class miEntidadBean implements Serializable Lugar donde se utiliza la anotación para indicar el manejo de persistencia de atributos Field access—Se especifica en los atributos. Todos los atributos no transcientes persisten Property access— Se especifica en los métodos getter. Todas las propiedades públicas, protegidas y no transcientes persisten. Este es el valor por defecto Pueden extender clases de entidad o no entidad, una clase que no es de entidad puede extender una clase de entidad Debe tener un constructor público sin parámetros No debe tener campos, atributos ni métodos finales Todo atributo persistente debe ser privado y ofrecer métodos get/set Los atributos de tipo colección deben usar las interfaces del framework java.util.Collection con genéricos de Java 5 (Collection, Set, Map, etc.) Identificación de Instancias DEPARTAMENTO DE SISTEMAS Cada instancia de una entidad tiene una llave primaria que lo identifica Las llaves primarias simples usan la anotación javax.persistence.Id en el método get (o en el atributo) para señalar que un atributo es la llave primaria @Id @GeneratedValue public Long getId() { return id;} Tipos válidos: primitivos, wrappers, String, Date Es posible definir clases compuestas para llaves primarias (deben ser serializables) @IdClass(com.example.PersonPK.class) @Entity(access=AccessType.FIELD) class Person { @Id String firstName; @Id String lastName; Relaciones entre entidades DEPARTAMENTO DE SISTEMAS Una de las principales innovaciones de JEE es la definición de relaciones entre entidades Existen 4 tipos de relaciones Uno a Uno Uno a Muchos Muchos a Uno Muchos a Muchos La dirección de una relación puede ser bidireccional o unidireccional Una relación tiene un lado dueño (owner): determina como se podrán propagar las modificaciones Las relaciones bidireccionales tienen además un lado inverso Relaciones entre entidades DEPARTAMENTO DE SISTEMAS Una relación es marcada en un atributo usando las anotaciones javax.persistence.OneToOne javax.persistence.OneToMany javax.persistence.ManyToOne javax.persistence.ManyToMany Carga en memoria de las relaciones: indica el momento en el cual los datos asociados al campo relacionado con otra entidad son cargados en memoria EAGER: cuando se carga la clase dueña que tiene la relación LAZY: cuando se utiliza el campo que representa la relación Ejemplos @ManyToMany (fetch = FetchType.EAGER) public Collection<Producto> getProductos() @OneToOne public Usuario getUsuario() Relaciones Bidireccionales DEPARTAMENTO DE SISTEMAS Se puede navegar en ambas direcciones Deben cumplir las siguientes reglas El lado inverso de la relación debe referenciar el lado dueño usando el elemento mappedBy en la anotación de la relación En la relación muchos a uno o muchos a muchos el lado dueño es el lado de muchos En las relaciones uno a uno el dueño corresponde al lado que tiene la llave foránea Ejemplos Customer.java @OneToMany (mappedBy = “customer”) public Collection<Order> getOrders() Order.java private Customer customer; @ManyToOne public Customer getCustomer() Relaciones DEPARTAMENTO DE SISTEMAS Las entidades relacionadas pueden tener dependencias de existencia Las operaciones a propagar corresponden a eliminación, actualización, inserción Las relaciones candidatas a especificar la propagación son @OneToOne y @OneToMany Las entidades inversas especifican en la relación el valor de propagación utilizando el elemento cascade=javax.persistence.CascadeType.ALL Customer.java @OneToMany(cascade=javax.persistence.CascadeType.ALL, mappedBy=“customer") public Collection<LineItem> getItems(){ return items;} Relaciones DEPARTAMENTO DE SISTEMAS • @OneToOne @Target({METHOD, FIELD}) @Retention(RUNTIME) public @interface OneToOne { Class targetEntity() default void.class; CascadeType[] cascade() default {}; FetchType fetch() default EAGER; boolean optional() default true; String mappedBy() default ""; } Relaciones DEPARTAMENTO DE SISTEMAS @Entity public class User { @Id protected String userId; protected String email; @OneToOne protected BillingInfo billingInfo; } @Entity public class BillingInfo { @Id protected Long billingId; protected String creditCardType; protected String creditCardNumber; protected String nameOnCreditCard; @OneToOne(mappedBy=”billingInfo”, optional=”false”); protected User user; } Ejemplo tomado de: EJB 3.0 in Action Relaciones DEPARTAMENTO DE SISTEMAS • @OneToMany / @ManyToOne @Target({METHOD, FIELD}) @Retention(RUNTIME) public @interface OneToMany { Class targetEntity() default void.class; CascadeType[] cascade() default {}; FetchType fetch() default LAZY; String mappedBy() default ""; } @Target({METHOD, FIELD}) @Retention(RUNTIME) public @interface ManyToOne { Class targetEntity() default void.class; CascadeType[] cascade() default {}; FetchType fetch() default EAGER; boolean optional() default true; } Relaciones DEPARTAMENTO DE SISTEMAS @Entity public class Item { @Id protected Long itemId; protected String title; @OneToMany(mappedBy="item") protected Set<Bid> bids; } @Entity public class Bid { @Id protected Long bidId; protected Double amount; @ManyToOne protected Item item; } Ejemplo tomado de: EJB 3.0 in Action Relaciones DEPARTAMENTO DE SISTEMAS • @ManyToMany @Target({METHOD, FIELD}) @Retention(RUNTIME) public @interface ManyToMany { Class targetEntity() default void.class; CascadeType[] cascade() default {}; FetchType fetch() default LAZY; String mappedBy() default ""; } Relaciones DEPARTAMENTO DE SISTEMAS @Entity public class Category { @Id protected Long categoryId; protected String name; @ManyToMany protected Set<Item> items; } @Entity public class Item { @Id protected Long itemId; protected String title; @ManyToMany(mappedBy=”items”) protected Set<Category> categories; } Ejemplo tomado de: EJB 3.0 in Action Agenda DEPARTAMENTO DE SISTEMAS Generalidades de las entidades JEE Mapeo con la BD Administración de Entidades Apoyo al desarrollo de aplicaciones Helpers Listener Finders Configuración Ejemplo de mapeo DEPARTAMENTO DE SISTEMAS @Entity @table(name=customer) public class Customer implements Serializable { private Long id; @Column(name=“FirstName”, nullable=false) private String name; @Id @GeneratedValue public Long getId() {…} }… Customer Id PK,SA FirstName Entidades DEPARTAMENTO DE SISTEMAS Una entidad puede corresponder a una o más tablas ... @Entity @Table(name="EJB_ORDER_PART") @SecondaryTable(name="EJB_ORDER_PART_DETAIL", pkJoinColumns={ @PrimaryKeyJoinColumn( name="PARTNUMBER", referencedColumnName="PARTNUM"), @PrimaryKeyJoinColumn( name="REVISION", referencedColumnName="REVISION") }) public class Part { ... } EJB_ORDER_PART PartNum Revision PK PK 1 2 20000101 20000102 EJB_ORDER_PART_DETAIL PartNum Revision PK,FK1 PK,FK1 1 2 20000101 20000102 Mapeo de relaciones a la BD DEPARTAMENTO DE SISTEMAS El mapeo de las relaciones a campos en la base de datos depende del tipo de relación Ejemplo de relaciones bidireccionales 1 a 1: EntityBean Empleado Codigo Nombre Empleado Codigo PK EntityBean Departamento <<Owner>> Numero Jefe 0..1 Nombre Departamento Numero Jefe_Codigo PK FK,ND Mapeo de la herencia DEPARTAMENTO DE SISTEMAS Soporta varias estrategias : Una tabla, tabla por clase concreta, tabla por clase Una tabla SuperClase @Entity @Table(name = "record") @Inheritance(discriminatorValue="B") @DiscriminatorColumn(name="record_type") public class Record implements Serializable { protected int id; protected double saving; protected double result; SubClase @Entity @Inheritance(discriminatorValue = "T") public class TimeRecord extends Record { private Timestamp ts; Record recordType Varchar(10) Id Int saving Double result Double Ts Datetime Mapeo de la herencia DEPARTAMENTO DE SISTEMAS Una tabla por clase concreta: la tabla principal no existe necesariamente (e.g., clase abstracta) y se duplican los atributos comunes en las distintas tablas subtipo SuperClase @Entity(access=AccessType.FIELD) @Inheritance(strategy=InheritanceType.TABLE_PER_CLASS) public abstract class Animal {@Id protected Integer id; … protected String name; … protected Integer age; } SubClase @Entity(access=AccessType.FIELD) public class Bird extends Animal { … protected Integer nbPlume; } @Entity(access=AccessType.FIELD) public class Dog extends Animal { … protected String race; } Mapeo de la herencia DEPARTAMENTO DE SISTEMAS Subclases con Joins SuperClase @Entity(access=AccessType.FIELD) @Inheritance(strategy=InheritanceType.JOINED) public abstract class Employee { @Id protected Integer id; @Version protected Integer version; protected String name; SubClase1 @Entity(access=AccessType.FIELD) @Inheritance(discriminatorValue="PT") @PrimaryKeyJoinColumn(name="PT_EMPID") public class PartTimeEmployee extends Employee { protected Float hourlyWage; SubClase2 @Entity(access=AccessType.FIELD) @Inheritance(discriminatorValue="FT") @PrimaryKeyJoinColumn(name="FT_EMPID") public class FullTimeEmployee extends Employee { protected Integer salary; Agenda DEPARTAMENTO DE SISTEMAS Generalidades de las entidades JEE Mapeo con la BD Administración de Entidades Apoyo al desarrollo de aplicaciones Helpers Listener Finders Configuración Administración de Entidades DEPARTAMENTO DE SISTEMAS Las entidades son administradas por el Entity Manager El Entity Manager es representado por instancias de la interfaz javax.persistence.EntityManager Cada instancia está asociada a un contexto persistente Contexto Persistente: conjunto de entidades administradas que existen en un repositorio de datos específico La interfaz del EntityManager define métodos para interactuar con el contexto persistente Los componentes persistencia de @PersistenceContext EntityManager em; aplicación definen el contexto de Entity Manager DEPARTAMENTO DE SISTEMAS Similar en funcionalidad a un Session en Hibernate Session Un PersistenceManager en JDO Su API ofrece servicios para crear y remover instancias de una entidad buscarlas por su llave primaria ejecutar consultas sobre las entidades. Maneja el ciclo de vida de las entidades persist(): inserta una entidad en una BD remove(): borrar una entidad de la BD merge() : guardar las modificaciones hechas en la entidad en el contexto Otras funciones: flush(), refresh(), find() Fábrica de objetos de consulta createQuery() : crea un instancia de consulta para utilizar EJB QL createNamedQuery(): crea una instancia predefinida de consulta createNativeQuery(). crea instancias de consultas para utilizar SQL Ciclo de Vida DEPARTAMENTO DE SISTEMAS Ciclo de vida (cont.) DEPARTAMENTO DE SISTEMAS New Entity Managed Entity Tiene entidad persistente Asociada con un contexto de persistencia Detached Entity Creada utilizando “new” No tiene identidad persistente o estado Tiene identidad persistente No está asociada a un contexto de persistencia Removed Entity Tiene identidad persistente Asociada con un contexto de persistencia Está programada para ser borrada del repositorio de datos Ejemplo API Entity Manager DEPARTAMENTO DE SISTEMAS public Order createNewOrder(Customer customer) { Order order = new Order(customer); entityManager.persist(order); return order; } public void removeOrder(Long orderId) { Order order = entityManager.find(Order.class, orderId); entityManager.remove(order); } public List findWithName(String name) { return em.createQuery( "SELECT c FROM Customer c WHERE c.name LIKE :custName") .setParameter("custName", name) .setMaxResults(10) .getResultList(); } Persistencia DEPARTAMENTO DE SISTEMAS Mecanismos de persistencia La instancia de forma directa utiliza el método persist Si la instancia está asociada a otra instancia de entidad que invoca el método persist: si las relaciones de la entidad hacia otras son cascade=PERSIST o ALL. Llamar al Entity Manager para que persista LineItem li = new LineItem(...); order.getLineItems().add(li); em.persist(li); return li; El método persist es propagado a todas las entidades relacionadas al llamado de la entidad que tienen el elemento cascade en ALL o PERSIST en la anotación de la relación Order.java @OneToMany(cascade=ALL, mappedBy=“order") public Collection<LineItem> getLineItems(){return lineItems;} Borrado de entidades DEPARTAMENTO DE SISTEMAS Encontrar la entidad Llamar el método remove sobre el EntityManager Order order = em.find(...); em.remove(order); Al igual que para la creación, la operación de borrado es propagada Sincronización del estado DEPARTAMENTO DE SISTEMAS El estado de una instancia es sincronizado con la base de datos cuando la transacción asociada a la entidad hace commit Si una instancia administrada está en una relación bidireccional con otra instancia administrada, la información será persistida basada en el lado dueño de la relación Para forzar la sincronización de la entidad con la base de datos se puede invocar el método flush Consulta de entidades DEPARTAMENTO DE SISTEMAS createQuery em.createQuery("SELECT c FROM Customer c WHERE c.name LIKE :custName") .setParameter("custName", name) .setMaxResults (10).getResultList(); createNamedQuery Declaración @NamedQueries( value={@NamedQuery (name="findAllCustomersWithName", query="SELECT c FROM Customer c WHERE c.name LIKE :custName" ), Uso em.createNamedQuery("findAllCustomersWithName") .setParameter("custName", "Smith") .getResultList(); Tipos de Entity Manager DEPARTAMENTO DE SISTEMAS Container-Managed Entity Managers: el ciclo de vida del entityManager es manejado por el contenedor, el contexto es propagado automáticamente a todos los componentes de la aplicación que usan la instancia en una transacción @PersistentContext EntityManager em; Application-Managed Entity Managers: el ciclo de vida del entityManager es manejado por la aplicación el contexto no es propagado a los otros componentes @PersistentUnit EntityManagerFactory emf; EntityManager em = emf.createEntityManager() Agenda DEPARTAMENTO DE SISTEMAS Generalidades de las entidades JEE Mapeo con la BD Administración de Entidades Apoyo al desarrollo de aplicaciones Configuración Unidades de Persistencia DEPARTAMENTO DE SISTEMAS Conjunto de todas las clases administradas por el EntityManager instances en la aplicación Definidas en el archivo de configuración persistence.xml Pueden ser empacadas como parte de un EJB JAR file, o como un JAR incluido en un WAR o EAR. Estas unidades son copiadas al contenedor para ser desplegadas (deployed) Unidades de Persistencia (cont) DEPARTAMENTO DE SISTEMAS persistence.xml define una o más unidades de persistencia. Depende de un DataSource Unidades de Persistencia (cont) DEPARTAMENTO DE SISTEMAS Datasource: Define un pool de conexiones (p.e. a una BD ) Agenda DEPARTAMENTO DE SISTEMAS Generalidades de las entidades JEE Mapeo con la BD Administración de Entidades Configuración Apoyo al desarrollo de aplicaciones Helpers Listener Finders Clases de Ayuda (Helpers) DEPARTAMENTO DE SISTEMAS Una entidad puede tener clases de ayuda para Implementar métodos de callback (Listener) Declarar los queries estáticos sobre la entidad usando anotaciones (Finder) Ofrecer clases simples para pasar a las capas de usuario (Business Objects) Listener DEPARTAMENTO DE SISTEMAS Los métodos de callback permiten tener mayor control sobre el ciclo de vida de la entidad, por parte del desarrollador recibir notificaciones sobre hechos ocurridos sobre un objeto: carga, borrado o salvado El listener de una entidad implementa los métodos de callback Cada método de callback viene con la anotación que declara qué solicitud atenderá @prePersist public void doPrePersist ( ); Listener (cont.) DEPARTAMENTO DE SISTEMAS PrePersist, PreRemove: invocados por el EntityManager antes de hacer persistir o eliminar la instancia y son sincrónicos. PostPersist, PostRemove: Invocados por el EntityManager después de que se han ejecutado los métodos de persistencia o eliminación de la instancia. PreUpdate, PostUpdate: Son invocados antes y después de las operaciones de actualización de la instancia del bean de entidad. PostLoad: Es invocado después de que la instancia de la entidad ha sido cargada en el contexto de persistencia que le corresponde. Listener (cont.) DEPARTAMENTO DE SISTEMAS El listener de una entidad es declarado usando la anotación ‘@EntityListener’ @Entity @EntityListeners(<ListenerClass>) public class miEntidadBean ... Finders DEPARTAMENTO DE SISTEMAS Una clase Finder declara en anotaciones los named queries de una entidad @NamedQuery ( Name=”findMiEntidadByXX” queryString=”SELECT … FROM …” ) ... public class miEntidadFinderServices extends miEntidadBean { } Por problemas de la versión actual de Jboss incluiremos los Finders en la misma clase de la entidad Value Objects DEPARTAMENTO DE SISTEMAS POJOs Tienen los mismos atributos que la clase de entidad Ofrecen métodos get y set para cada atributo, no tienen NINGUNA lógica de negocio Son el tipo de objetos que se debe pasar entre las capas, an particular a la capa web solo deben llegar este tipo de objetos para presentar los datos al usuario Resumen de Patrones DEPARTAMENTO DE SISTEMAS Contenedor Web Business Objects Business Objects Delegado de Negocios (Helper) Filtros Value List Fachada Controlador Vistas Contenedor EJB Entidades Business Objects DAO Este material fue preparado por DEPARTAMENTO DE SISTEMAS Nicolás López Pilar Villamil Darío Correal Referencias DEPARTAMENTO DE SISTEMAS http://java.sun.com/javaee/5/docs/tutorial/doc/ http://www.jcp.org/en/jsr/detail?id=220 http://www.labo-sun.com/resource-fressentiels-836-4-java-j2ee-ejb-3-les-entreprise-javabean-version-3-javabeans-.htm http://www.solarmetric.com/resources/ejb-apiquickref.pdf