Object Relational Mapping - ORM Tutor: Ing. Juan E. Talavera Horn 2010
ORM - Concepto Conversión automática de objetos de aplicación a filas en tablas relacionales y viceversa
ORM - Objetivos Reducir la codificación de código SQL trivial para mantenimiento de objetos en la base de datos Facilitar la navegación entre datos y sus relaciones en término de objetos de aplicación
ORM - Frameworks Hibernate - Java TopLink - Java Enterprise Java Beans - Java Zend – php NHibernate –.NET Rails – Ruby
Hibernate - Introducción package events; import java.util.Date; public class Event { private Long id; private String title; private Date date; public Event() {} public Long getId() { return id; } private void setId(Long id) { this.id = id; } public Date getDate() { return date; } public void setDate(Date date) { this.date = date; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } POJO: Plain Old Java Object
Configuración de mapeo <property name="date" type="timestamp" column="EVENT_DATE"/>
Crear y almacenar nuevo objeto Session session = HibernateUtil.getSessionFactory().getCurrentSession(); //Iniciar transacción session.beginTransaction(); Event theEvent = new Event(); theEvent.setTitle(title); theEvent.setDate(theDate); session.save(theEvent); //Confirmar transacción session.getTransaction().commit();
Obtener lista de objetos desde BD //Método en clase EventManager private List listEvents() { Session session = HibernateUtil.getSessionFactory().getCurrentSession(); List result = session.createQuery("from Event").list(); return result; } //Desde algún cliente de EventManager List events = mgr.listEvents(); for (int i = 0; i < events.size(); i++) { Event theEvent = (Event) events.get(i); System.out.println("Event: " + theEvent.getTitle() + " Time: " + theEvent.getDate()); }
Mapear asociaciones package events; public class Person { private Long id; private int age; private String firstname; private String lastname; private Set events = new HashSet(); public Person() {} // getters y setters para todos los atributos }
<many-to-many column="EVENT_ID" class="events.Event"/> Mapear asociaciones
Accediendo a las relaciones private void addPersonToEvent(Long personId, Long eventId) { Session session = HibernateUtil.getSessionFactory().getCurrentSession(); session.beginTransaction(); Person aPerson = (Person) session.load(Person.class, personId); Event anEvent = (Event) session.load(Event.class, eventId); aPerson.getEvents().add(anEvent); session.getTransaction().commit(); }
Annotations Sustituir configuración XML por annotations Annotations estándares de EJB 3.0 Annotations específicos de Hibernate POJO + Annotations EJB 3.0 = Entity Java Beans Hibernate cumple con especificación JPA JPA puede ejecutarse fuera de contenedor EJB, ejemplo Apache Tomcat
POJO + public class Flight implements Serializable { Long public Long getId() { return id; } public void setId(Long id) { this.id = id; } } Anotaciones sobre los getters o declaraci ó n de los atributos
@Table(…) public class Sky implements Serializable {... }
Optimistic public class Flight implements Serializable { private public Integer getVersion() { return version; } EJB 3 requiere soporte para bloqueo optimista, pero no así para bloqueo pesimista.
Mapeo de propiedades simples public transient int counter; //transient property private String firstname; //persistent String getLengthInMeter() {... } //transient property String getName() {... } // persistent int getLength() {... } // persistent java.util.Date getDepartureTime() {... } // persistent property
public class Flight implements Serializable = "flight_name", nullable = false, length=50) public String getName() {... }
“ SEQ_STORE",sequenceName= “ SQ_IDSTORE") public Integer getId() {... } AUTO: Uno de los siguientes dependiendo de la BD TABLE: Valor almacenado en una tabla IDENTITY: Auto incrementado por la BD (si soporta) SEQUENCE: A partir de secuencia
Claves primarias compuestas Anotar la propiedad y la clase de la clave Anotar la propiedad Anotar la clase y anotar cada propiedad que conforma la clase
Anotar la propiedad y la clase de la public class DetalleFactura DetalleFacturaKey id;... public class DetalleFacturaKey { private Integer idCabeceraFactura; private Integer nroDetalle; }
Anotar la public class DetalleFactura DetalleFacturaKey id;... } public class DetalleFacturaKey { private Integer idCabeceraFactura; private Integer nroDetalle; }
Anotar la clase y anotar cada propiedad que conforma la @IdClass(DetalleFacturaKey.class) public class DetalleFactura private Integer Integer nroDetalle;... public class DetalleFacturaKey { private Integer idCabeceraFactura; private Integer nroDetalle; }
Asociación 1 a 1 Las entidades asociadas tienen las mismas claves primarias Una de las entidades tiene un foreign key a la otra Existe una tabla intermedia que mantiene la relación entre las 2 entidades
Las entidades asociadas tienen las mismas claves public class Body public Long getId() { return id; = public Heart getHeart() { return heart; }... public class Heart public Long getId() {...} }
Una de las entidades tiene un foreign key a la public class Customer = public Passport getPassport() {}... public class Passport = "passport") public Customer getOwner() {}... } En relación bidireccional, owner class es la encargada del mantenimiento de la relación
Tabla intermedia mantiene la relación entre las 2 public class Customer implements Serializable = = "CustomerPassports", joinColumns inverseJoinColumns public Passport getPassport() {}... public class Passport implements Serializable = "passport") public Customer getOwner() {}... }
Asociación muchos a public class Flight implements Serializable public Company getCompany() { return company; }... }
public class Company implements Serializable { public String getName() { … “ company") public List getFlights() { return flights; }... }
Invertir el “owner” de la public class public Set getSoldiers() {}... public class insertable=false, updatable=false) public Troop getTroop() {}... }
Foreign key public class Parent implements Serializable public ParentPk id; public referencedColumnName = referencedColumnName = referencedColumnName = "firstName") }) public Set children;... }
Named Query select p from query="select n from Night n where n.date >= :date") public class Night {... } public class MyDao { doStuff() { Query q = s.getNamedQuery("night.moreRecentThan"); q.setDate( "date", aMonthAgo ); List results = q.list();... }... }
Criteria Query List cats = sess.createCriteria(Cat.class).add( Restrictions.like("name", "Fritz%") ).add( Restrictions.between("weight", minWeight, maxWeight) ).list(); List cats = sess.createCriteria(Cat.class).add( Restrictions.like("name", "Fritz%") ).add( Restrictions.or( Restrictions.eq( "age", new Integer(0) ), Restrictions.isNull("age") ) ).list();
Conceptos de la plataforma Session Factory Session Persistent objects Transient and detached objects Transaction Connection Provider Transaction Factory First Level Cache Second Level Cache