Enterprise JavaBean 3.0 & Java Persistence APIs: Simplifying Persistence   Carol McDonald Java Architect Sun Microsystems
Speaker’s Qualifications Carol  cDonald:  Java Architect at Sun Microsystems Before Sun, worked on software development of:  Application to  manage car Loans  for  Toyota  (>10 million loans)  Pharmaceutical  Intranet  ( Roche  Switzerland)  Telecom  Network Mgmt  ( Digital  France)  X.400  Email Server  ( IBM  Germany)
JPA: Simplifying/Unifying/Standardizing Persistence Simpler, easier and smarter Easy  to develop POJO  based programming/persistence model Simple Java classes –  not  EJB components , only 1 file instead of 3 Entities  usable outside  the  container No need for  D ata  T ransfer  O bjects  Facilitates  testability Most  configuration  is  defaulted  – configure by exception only (configure only to override default)
Simplifying/Unifying Persistence cont. Standardized   o bject/ r elational  m apping Standardized  annotations @  and  XML  configuration files xml for mapping is optional Support for  pluggable  3 rd  party  Persistence provider s Usable in Java  EE , Enterprise JavaBeans 3.0 and Java  SE  environments
Entities P lain  O ld  J ava  O bjects (not an EJB) Created  by means of  new No  required   interfaces (home, ejb, callback..) Have  persistent  identity May have both  persistent  and non-persistent   state Simple  types (e.g., primitives, wrappers, enums, serializables) Composite  dependent object types (e.g., Address) Non-persistent state ( transient  or @Transient) Can  extend   other  Entity  and  non-Entity  classes Serializable; usable as  detached objects  in other tiers No  need for  d ata  t ransfer  o bjects
Entity Annotated as “Entity” @Id denotes primary key @Entity public class Customer implements Serializable { @Id  protected Long id; protected String name; public Customer() {} public Long getId() {return id;} public String getName() {return name;} public void setName(String name) {this.name = name;} … }
Data Model  and O-R Mapping Basic and Relationship Entity Inheritance Entity Identity
An Example Data Model Maps entity states to data store Maps relationship to other entities Customer int id String name int c_rating Image photo Set<Order> orders Collection<Phone> phones ... Order int id Customer cust ... Phone int id Collection<Customer> custs ... 1 M M N
Simple Mapping Mapping defaults  to matching  column name . Only  configure   if  entity field and table column names are  different   public class Customer {    int id;   String name;    int c_rating;   Image   photo; } @Entity(access=FIELD) @Column(name=“CREDIT”) @Id @Lob CUSTOMER ID NAME CREDIT PHOTO
Entity Annotated as “Entity” @Id denotes primary key @Entity public class Customer implements Serializable { @Id  protected Long id; protected String name; @Transient  protected int reservationCount; public Customer() {} public Long getId() {return id;} public String getName() {return name;} public void setName(String name) {this.name = name;} … }
Entity Class for Customer @Entity(access=FIELD)  @Table(name = “customer”) public class Customer { @Id  public int id; ... public String name; @Column(name=”CREDIT”)  public int c_rating; @LOB  public Image photo; ... } Annotated as “Entity” Data are accessed as fields @Id denotes primary key Maps to “customer” table Specify the table column to map to
Relationships
Entity Relationships One-to-one, one-to-many, many-to-many, many-to-one, relationships among entities bi-directional  or  uni-directional Support for Collection, Set, List and Map Need to specify  owning  side  in  relationships Owning side table has the  foreign key OneToOne  relationship – the side with the   foreign key OneTo Many ,  Many ToOne  –  many   side
Relationship Mappings – OneToMany Bidirectional   public class Order {   int id; ... Customer   cust ; } public class Customer {   int id;   ... Set<Order> orders; } @Entity(access=FIELD) @Entity(access=FIELD) @ManyToOne @OneToMany(mappedBy=“ cust ”) @Id @Id 1 n has to say  where the foreign key is  using  mappedBy CUSTOMER ID . . . ORDER CUST_ID ID . . .
Example ManyToOne bi-directional Order is the  owner must call  order.setCustomer (cust) whenever order added  to customer.  @Entity  public class  Order  { @Id protected Long id; … @ManyToOne  protected  Customer cust; … public Customer getCustomer() {return cust;} public void  setCustomer (Customer cust) { this.cust = cust; } } @Entity  public class  Customer  { @Id protected Long id; … @OneToMany(mappedBy=“cust”) protected Set<Order>  orders = new HashSet(); … public void  addOrder (Order order) { this.orders.add (order); order.setCustomer (this); } }
Relationship Mappings – ManyToOne Automatically creates a ADDR_ID field for mapping. Can be overridden via @ManyToOne annotation public class  Customer  {  int id;   Address addr ; } CUSTOMER ADDR_ID ID ADDRESS . . . ID @Entity(access=FIELD) @ManyToOne @Id ADDR_ID
Relationship Mappings – ManyToMany public class  Customer  {   int id;   ... Collection<Phone>   phones ; } @Entity(access=FIELD) @Entity(access=FIELD) @Id @Id @ManyToMany @ManyToMany(mappedBy=“phones”) public class  Phone  {   int id; ...   Collection<Customer>   custs ; } Join table name is made up of the 2 entities. Field name is the name of the  entity  plus the name of the  PK  field PHONES _ID CUSTS _ID CUSTOMER ID . . . PHONE ID . . . CUSTOMER_PHONE ID
Relationship Mappings – ManyToMany Can override the default column names PHONES_ID CUST_ID CUSTOMER ID . . . PHONE ID . . . CUST_PHONE @Entity(access=FIELD) public class Customer {   ... @ManyToMany @ JoinTable (table=@Table(name=“CUST_PHONE”), joinColumns =@JoinColumn(name=“CUST_ID”), inverseJoinColumns =@JoinColumn(name=“PHONES_ID”)) Collection<Phone> phones; }
Example ManyToMany bi-directional customer   is the  owning  side:  must add/remove  the phone from the  customer's  phones property. @Entity  public class  Phone  { @Id protected Long id; … @ManyToMany(mappedBy=“phones”)   protected Set<Customer>  customers  = new HashSet(); … } @Entity  public class  Customer  { @Id protected Long id; … @ManyToMany protected  Set<Phone>  phones  = new HashSet(); … private Set<Phone> getPhones() {return phones;} public void  addPhone (Phone phone) { this .getPhones(). add (phone); } public void  removePhone (Phone phone) { this .getPhones(). remove (phone); } }
Mapping of Embedded Objects @Entity(access=FIELD) @Embedded @Id @Embeddable(access=FIELD) public class  CustomerInfo  {  String name; int credit; @Lob Image   photo; } public class Customer {    int  id ; CustomerInfo info; } Embedded objects  have  no identity of their own . Takes on the identity of the container object CUSTOMER ID NAME CREDIT PHOTO
Entity Inheritance: 3 possibilities: Concrete/Abstract entity class Annotated with  @Entity Behaves like an entity Mapped superclass Non entity class Entity can extend
Entity Inheritance – (Abstract) Entity Class @Entity  public   abstract   class  Person { @Id  protected Long id; protected String name; @Embedded  protected Address address; } @Entity  public class  Customer  extends  Person  { @Transient  protected int orderCount; @OneToMany   protected Set<Order> orders = new HashSet(); } @Entity  public class  Employee  extends  Person  { @ManyToOne   protected Department dept; }
Entity Inheritance Concrete/Abstract entity class Mapped superclass Contains  common fields  for all entities Provides  common  entity  state Mapped superclass is  NOT  an  entity Annotated with  @MappedSuperclass Non entity class Entity can extend:
Entity Inheritance – Mapped Superclass @MappedSuperclass  public class  Person { @Id  protected Long id; protected String name; @Embedded  protected Address address; } @Entity  public class  Customer extends Person  { @Transient  protected int orderCount; @OneToMany   protected Set<Order> orders = new HashSet(); } @Entity  public class  Employee extends Person  { @ManyToOne   protected Department dept; }
Entity Inheritance Concrete/Abstract entity class Mapped superclass Non entity class State of non entity super class is  not persisted Can  not  contain  O/R mapping  annotations Entity can extend
Entity Inheritance – Non Entity Class public class Person { protected String name; } @Entity  public class  Customer extends Person  { //Inherits name but not persisted @Id  public int id; @Transient  protected int orderCount; @OneToMany   protected Set<Order> orders = new HashSet(); } @Entity  public class  Employee extends Person  { //Inherits name but not persisted @Id  public int id; @ManyToOne   protected Department dept; }
Mapping Entity Inheritance to DB Table Inheritance mapping strategies: Single table   Joined subclass   Table per class
Inheritance mapping strategies Object Model AirAnimal  wingSpan: int LandAnimal  legCount: int Animal  id: int name: String
Inheritance mapping strategies Data Models Single table: each class  is stored in a  separate table each   concrete  class  is stored in a  separate table all classes stored in the  same table ANIMAL ID NAME LAND_ANML ID LEG_COUNT AIR_ANML ID WING_SPAN Joined Subclass: Table per Class: LAND_ANML ID LEG_COUNT AIR_ANML ID WING_SPAN NAME NAME ANIMAL LEG_CNT ID DISC NAME WING_SPAN
Discriminator Column and Value for Single Table @Entity @Table(name=&quot;ANIMAL&quot;)  @Inheritance(strategy=SINGLE_TABLE) @DiscriminatorColumnName(name=”DISC”) @DiscriminatorValue(“ANIMAL”) public class Animal { @Id protected int id; protected String name; ... } @Entity @DiscriminatorValue(&quot;LANDANIMAL&quot;) public class LandAnimal  extends Animal  { @Column(name=”LEG_CNT”) protected int legCount; ... ANIMAL LEG_CNT ID DISC NAME WING_SPAN
Discriminator Value for SingleTable
Identity Every entity has a  persistence identity Uniquely identifies  that entity Maps to  primary key  in the database Identity can be application or database  generated Must be defined on the  ROOT of entity  hierarchy or  mapped superclass
Types of Identity Simple @Id  – single field/property in entity class @GeneratedValue User defined:  @EmbeddedId – single field/property in entity class @IdClass – corresponds to  multiple id field  in entity class @Id  @GeneratedValue(strategy=SEQUENCE) private int id; @EmbeddedId   private  EmployeePK  pk; @Entity   @IdClass (EmployeePK.class) public class Employee { @Id  private String empName; @Id  private int dept; Class must be @Embeddable
Using orm.xml for Mapping Can put  some  or  all  the mapping metadata in XML mapping files orm.xml located in META-INF directory of JAR Can use orm.xml to specify entity mappings Annotations not required At runtime, orm.xml  override  annotations
Example of orm.xml File <entity-mappings> <entity class=”Customer”> <id name=”id”> <generated-value/> </id> <basic name=”c_rating”> <column name=”ratings”/> </basic> ... <one-to-many name=”orders” mapped-by=”cust”/> </entity> ... </entity-mappings> Overriding the default annotations in source
Persistence EntityManager Persistence Unit Persistence Context Entity Lifecycle Application Managed Persistence Transactions
Persistence – Key Concepts Persistence unit Entity manager Persistence context Transactions
Persistence Unit Persistence Context Persistence Context Primary interface to interact with underlying persistence engine A set of entities associated with a particular transaction Configuration for entities mapped to a single data store Persistence Unit MyApp Employee e = new Employee(); e.setName(“Lucas”); em.persist(e); persistence.xml
Persistence Unit Persistence Unit  Configuration  to  map   Entity  classes in an  application  to a relational  database persistence.xml defines one or more persistence units the  JAR  file that contains persistence.xml will be  scanned   for any  classes  annotated with  @Entity   < persistence  version=&quot;1.0&quot;  xmlns =&quot; http://java.sun.com/xml/ns/persistence &quot;> < persistence-unit  name=&quot; OrderPU &quot; transaction-type=&quot;JTA&quot;> < provider > org.hibernate.HibernatePersistence </provider> < jta-data-source > jdbc/order </jta-data-source>   < jar-file >../lib/order.jar</jar-file> < class >com.acme.Order</class> </persistence-unit> </persistence> Optional to define entity classes
Persistence – Key Concepts Persistence unit Entity manager Primary interface to  interact  with underlying  persistence engine Persistence context A  set of entities managed by Entity Manager Transactions
EntityManager Persistence Context Persistence Context Primary interface to interact with underlying persistence engine A set of managed entities associated with a particular transaction Configuration for entities mapped to a single data store Persistence Unit MyApp Employee e = new Employee(); e.setName(“Lucas”); em.persist(e); persistence.xml
Persistence Context and EntityManager EntityManager API  to  manage  the  entity  instance lifecycle Allows your program to interact with underlying persistence engine Provides the following functionalities Lifecycle  operations –  persist(), remove(), refresh(), merge() Finder  –  find(), getReference() Factory  for  query  objects –  createNamedQuery(), createQuery(), createNativeQuery() Managing persistence context  –  flush(), clear(), close(), getTransaction(), ... Persistence Context Set of  managed entities , belonging to a single  persistence unit
Persistence Context and EntityManager Persistence  Context EntityManager persist() remove() refresh() merge() find() createQuery() createNamedQuery() contains() flush() SessionBean JavaBean Servlet
Persistence – Key Concepts creates creates Configured by Manages
EntityManager Example @Stateless  public ShoppingCartBean implements ShoppingCart { @PersistenceContext   EntityManager entityManager; public OrderLine createOrderLine(Product product , Order order) { OrderLine orderLine = new OrderLine(order, product); entityManager.persist (orderLine) ; return (orderLine); } public OrderLine updateOrderLine(OrderLine orderLine) { return ( entityManager.merge ( orderLine ) ); } } Dependency injection
EJB 3.0: Dependency Injection Dependency  Injection Bean  specifies what it  needs  through  @ References to resources  are  injected  when instance is constructed: @Resource :  for   connection factories, EJBContext,  UserTransaction , etc. @EJB :  For EJB References @PersistenceContext :  For container-managed EntityManager @PersistenceUnit :  For EntityManagerFactory
Entity Lifecycle State Diagram New entity instance is created Entity is  not  yet  managed  or  persistent Entity becomes   managed Entity becomes   persistent  in database on  transaction commit new() Entity is removed Entity is deleted from database on transaction commit State of detached entity is merged back into managed entity no longer associated with persistence context New Detached Removed Managed persist() merge () remove () Updates PC ends
Entity Lifecycle Illustrated – The Code @Stateless  public ShoppingCartBean implements ShoppingCart { @PersistenceContext   EntityManager entityManager; public OrderLine createOrderLine(Product product , Order order) { OrderLine orderLine = new OrderLine(order, product); entityManager.persist(orderLine); return (orderLine); } public OrderLine updateOrderLine(OrderLine orderLine) {   OrderLine newOL= entityManager.merge(orderLine) return ( newOL ) ); } } New entity Managed entity Detached entity
Entity Manager Persist:  Insert a  new  instance of the  entity  into the database (when transaction commits) The entity instance becomes “managed” in the persistance context Persist operation  optionally  cascades  to related  objects public Customer createCustomer(intid, String name) { Customer cust=  new  Customer(id, name); entityManager.persist(cust); return cust; }
Cascading Persist example: ManyToOne public class Order {   int id; ... Customer  cust ; } public class Customer {   int id;   ... Set<Order> orders; } @Entity(access=FIELD) @Entity(access=FIELD) @ManyToOne @OneToMany(mappedBy=“cust”) @Id @Id CUSTOMER ID . . . ORDER CUST_ID ID . . .
Persist  OneToMany bi-directional  Not Cascading em.persist to persist the order  @Stateless  public class OrderManagementBean implements OrderManagement { … @PersistenceContext EntityManager em; … public Order  addNewOrder (Long id,Product product){ Customer cust =  em.find (Customer.class,   id);   Order order = new Order(product);   customer.getOrders().add(order); order.setCustomer(cust);   em.persist(order);   return order; } }
Cascading Persist cascade=Persist  Order persisted automatically, when added to Customer @Entity public class Customer { @Id protected Long id; … @OneToMany(cascade=PERSIST) protected Set<Order> orders = new HashSet(); } … public Order addNewOrder(Customer customer, Product product) { Order order = new Order(product); customer.getOrders().add(order); order.setCustomer(cust); return order; }
Entity Manager Find, Remove:  Find Get  a managed  entity  instance with a given persistent  identity Return null if not found Remove Delete entity  with the given persistent identity from the database (deleted when transaction commits) Optionally cascades to related objects public void removeCustomer(Long custId) { Customer cust= entityManager.find (Customer.class, custId); entityManager.remove (cust); }
Remove When order is removed, the lineItems are  removed with it @Entity public class  Order  { @Id protected Long orderId; … @OneToMany(cascade={PERSIST,REMOVE}) protected Set<LineItem>  lineItems  = new HashSet(); } … @PersistenceContext EntityManager em; … public void deleteOrder(Long orderId) { Order order =  em.find(Order.class, orderId); em.remove(order); }
Merge:  State of  detached entity  gets merged into a  managed copy  of entity Managed entity  is  returned   Merge operation optionally  cascades  to related objects public Customer storeUpdatedCustomer(Customer cust) { Customer  customer  =entityManager.merge( cust ); return customer; }   Managed Not managed
Merge When order is merged, the  lineItems  are  merged with it @Entity public class Order { @Id protected Long orderId; … @OneToMany(cascade={PERSIST, REMOVE, MERGE}) protected Set<LineItem>  lineItems  = new HashSet(); } … @PersistenceContext EntityManager em; … public Order updateOrder(Order changedOrder) { return em.merge(changedOrder); }
Detached Objects as DTOs public  OrderLine  updateOrderLine( OrderLine orderLine) { OrderLine  newOL = em.merge(orderLine)   return(newOL ); }  Entity beans may be passed by value as  detached  objects Must implement  Serializable  interface if detached object is to be sent across the wire Returned to caller as  Detached Detached Managed Detached after return
Types of Persistence Context and  Entity Managers Persistence Context Entity Manager Persistence Context Entity Manager Data source same entity
Entity Manager & Persistence Context  Types Two  types of EntityManagers: Container-managed  EntityManager – intended for Java EE  Application-managed  EntityManager – intended for Java SE/EE Two types of persistence context: transaction-scoped  persistence context extended persistence  context
Container Managed Entity Manager Container-managed  entity manager EntityManager  Lifecycle  managed by the Java EE  container   EntityManager obtained via  resource injection  or JNDI lookup: @PersistenceContext  EntityManager entityManager;
Types of Persistence Context Persistence Context 2 Types: lifetime maybe transaction-scoped or extended Transaction-scoped persistence context bound to a JTA transaction— starts  and  ends  at  transaction boundaries Propagated  across EJB components  within JTA  transactions entities are  detached  from the persistence context when  transaction ends
Java™ Transaction Service Application Server Transaction Service Application UserTransaction  interface Resource Manager XAResource   interface Transactional operation TransactionManager Interface Resource EJB Transaction context
Transactions with  Container Managed EntityManager JTA  Transactions are controlled through JTA Container-managed   entity manager  always JTA transactions
EJB & Container-Managed Entity Manager &  Transaction-scoped Persistence Context @Stateless  public ShoppingCartBean implements ShoppingCart { @PersistenceContext(unitName=”orderPU”)   EntityManager entityManager; public OrderLine  createOrderLine (Product product , Order order) { OrderLine orderLine = new OrderLine(order, product); entityManager.persist(orderLine); return (orderLine); } public OrderLine updateOrderLine(OrderLine orderLine) { return ( entityManager.merge(orderLine) ); } } Persistence context
Spring 2.0  & JPA @Repository @Transactional public class CatalogDAO implements  CatalogService  { @PersistenceContext (unitName=&quot;PetCatalogPu&quot;) private  EntityManager em; public List<Item>  getItems (int firstItem,int batchSize) {    Query q =    em. createQuery(&quot;select object(o) from Item as o&quot;);   q.setMaxResults(batchSize);   q.setFirstResult(firstItem);   List<Item> items= q.getResultList();   return items;  }
Java EE JTA Transactions Session Bean: Container-managed  transaction  is  default Specify declaratively Annotation:  @TransactionAttribute Values:  REQUIRED (default) , REQUIRES_NEW, MANDATORY,  NEVER, NOT_SUPPORTED, SUPPORTS On method  or class Session Bean: Bean-managed  transactions @Resource  UserTransaction  to get UserTransaction API Servlet:  uses   @Resource  UserTransaction  to get  JTA UserTransaction API
Stateless Session Bean in Java EE 5.0 @Stateless public class AirlineReservationBean  implements AirlineReservation { . . .  @TransactionAttribute(MANDATORY) public boolean  book (int passId, int flightId) {  Flight flight = em.find(Flight.class, flightId); Passenger pgr = em.find(Passenger.class, passId); return flight.addPassenger(pgr); } .. } NEW!  Java EE 5 Container Managed Transaction Container Managed Transaction
Declarative Transaction Management Example TX_REQUIRED TX_REQUIRED TX_REQUIRED PC PC PC Session Facade Inventory Service Order Service Check Out 1. Update Inventory New Persistence Context Persistence Context  Propagated Transaction Attributes 2. Create Order and   send JMS  message   to Warehouse Application
Persistence Context Propagation @Stateless  public class  ControllerBean  implements ControllerService { @EJB InventoryService inv ; @EJB  OrderService  ord ; public void manageOrderInventory(Item i, Product p) { inv.createOrder (item);  ord.updateInventory (Product p) } }
Persistence Context Propagation @Stateless  public class  OrderServiceBean  implements OrderService { @PersistenceContext   EntityManager em1; public void  createOrder (Item item) { em1.persist (new Order(item)); } } @Stateless  public class InventoryServiceBean implements InventoryService { @PersistenceContext   EntityManager em2; public void  updateInventory (Product p) { Product product =  em2.merge (p); . . . } }
Transaction Example  Application Server Transaction  Manager Transaction context DataBase Server and  JMS Provider Resource Client Controller Inventory Order 1) Check Out TX_REQUIRED TX_REQUIRED BEGIN 4)   Update Inventory 7) createOrder 11) Check context x to see if  updates will work 12) Commit or  rollback Start Prepare 10) END
Web & Container-Managed EM Servlet  Resource injection  and  Thread safety : EntityManager  instance is  not  thread safe Servlets are  multi-threaded Entity Manager Can be obtained using  JNDI Lifecyle managed by the  container So still less code than application managed
Beware of Injected Objects public class ShoppingCartServlet extends HttpServlet { @PersistenceContext EntityManager em ; protected void doPost(HttpServlet req, ...) { Order order order = ...; em.persist(order) ; } public class ShoppingCartServlet extends HttpServlet { @PersistenceUnit (name=&quot; PetstorePu &quot;) protected void doPost(HttpServlet req, ...) { EntityManager em = (EntityManager) new    InitialContext().lookup(&quot;java:comp/env/PetstorePu&quot;); Order order order = ...; em.persist(order); } WRONG CORRECT EntityManager  instance is  not  thread safe,  Servlets are  multi-threaded
Web and JTA Transactions must be  managed by the developer  Unlike with EJBs where they can be  managed by the container Use  @Resource UserTransaction utx ; Begin(), Commit (),  rollback ()
Web JTA Transaction and Container EM protected void buyBook(String book, int custId, String creditCard) throws … { utx.begin(); Customer customer =    new  CustomerHelper (). getCustomer (custId); Order order =    new  OrderHelper (). create (book, creditCard, customer); utx.commit(); } JTA
Web JTA Transaction and Container EM EM public Order  create (String book, String creditCard, Customer customer) { EntityManager em = (EntityManager)   new InitialContext() .lookup(“java:comp/env/persistence/bookStore”); Order order = new Order(customer); order.setCreditCard(creditCard); order.setBook(book); em.persist (order); } //CustomerHelper public Customer  getCustomer (int id) { EntityManager em = (EntityManager)   new InitialContext().lookup( “ java:comp/env/persistence/bookStore”); return  em.find (Customer.class, id); } // OrderHelper
Recommendation: Stateless Session Beans In our business logic bean, we had to deal with transactions explicitly Consider using a stateless session bean (EJB) Transactions  managed by the  container EM injected by container Also get other benefits: No more  thread safety  concerns Scalability  (across server instances) Participate in  cross-resource transactions
Web component using Stateless Session  @EJB CustomerMgr  customerMgr ; @EJB OrderMgr  orderMgr ; protected void buyBook(String book, int custId, String creditCard) throws … { Customer customer = customerMgr .getCustomer(custId); Order order =  orderMgr .create(book, creditCard, customer); } No need for Transaction Management
Stateless Session and Container EM No need for JNDI lookup of EM   No need for Transaction Management @Stateless public class OrderMgrBean implements OrderMgr { @PersistenceContext EntityManager em; create(String book, String creditCard, Customer cust) { Order order = new Order(cust); order.setCreditCard(creditCard); order.setBook(book); em.persist(order); } } @Stateless  public class CustomerMgrBean implements CustomerMgr { @PersistenceContext EntityManager em; public Customer getCustomer(int id) { return em.find(Customer.class, id); } }
Types of Persistence Context Persistence Context lifetime maybe transaction-scoped or extended Transaction-scoped persistence context Extended persistence context spans   multiple  transactions exists  from the time the EntityManager instance is  created  until it is  closed Defined when the EntityManager instance is  created
Extended Persistence Context @Stateful  public class ShoppingCart { //Specify that we want an EXTENDED   @PersistenceContext (type=PersistenceContextType.EXTENDED) EntityManager em ; //Cached order private Order  order ; //Find and cache order public void lookupOrder(String id) { //order remains managed for the lifetime of the bean order  = em.find(Order.class, id); }
Persistence Context- Transactional vs. Extended @Stateless public class OrderSessionStateless implements OrderService { @PersistenceContext(unitName=”java_one”) EntityManager em;  public void  addLineItem (OrderLineItem li){  // First, look up the order. Order order = em.find(Order.class, orderID); order.lineItems.add(li); } @Stateful public class OrderSessionStateful implements OrderService { @PersistenceContext(type = PersistenceContextType. EXTENDED )) EntityManager em;   // Order is a member variable Loaded from the db in lookupOrder   Order order public void  addLineItem (OrderLineItem li){ // No em.find invoked for the order object  order.lineItems.add(li); }
Extended Persistence Context – When?  to keep and reuse  managed entities  that are the subject of the  conversation workflow HTTPSession, stateful session bean Entities remain  managed  and  cached  over  multiple transactions Become  detached  when  EntityManager is closed  or when  Stateful   session bean is  removed
Conversation @Stateful  public class OrderBean { @PersistenceContext(type=EXTENDED) EntityManager em ; public void add(String itemCode, int qty) { ... } public void confirmOrder() { ... } ... } ________________________________________________________________ protected void doPost(HttpServletRequest req, ...) throws ... { String cmd = req.getParameter(“cmd”); if (cmd.equals(“NEW”)) { //Create  stateful  session bean, hold in HttpSession req.getSession().setAttribute(“order”, orderBean); } else if (cmd.equals(“ADD_ITEM”)) { //Add item to order bean orderBean.add(...); } else if (cmd.equals(“CONFIRM”)) { orderBean.confirmOrder(); order.remove(); req.getSession().removeAttribute(“order”); }
Persistence Context Source: Internal benchmarks Does it affect performance? Micro benchmark with lots of lookups
Entity Manager 2 Types Container-managed entity manager  Application-managed  entity manager Created by  EntityManagerFactory : EntityManager em = emf.createEntityManager(); Life cycle  managed by the  application Also available in Java  SE  environments Must use  extended  persistence context May use  JTA (Web)  or  RESOURCE_LOCAL (Java SE)  transaction type
Transaction Demarcation Appication managed entity manager  Transactions Web  are either  JTA  or  Resource local   JavaSE  are always  resource local JTA transaction UserTransaction API is injected
Data Base Transaction Management Transaction Manager EJB Container Resource Manager Data Base JTA A S EJB Local Servlet JDBC  Transactions JTA Transactions servlet Resource Manager EJB servlet servlet servlet Java SE
Application managed Entity Manager and  JTA Transaction ( Web ) @Resource UserTransaction utx; @PersistenceUnit EntityManagerFactory factory; public void createDistributor(String n) { //Begin transaction utx.begin(); EntityManager em  =  emf.createEntityManager() ; //Create entity Distributor dist = new Distributor(); dist.setName(n); //Save it em.persist( dist ) ; //Commit transaction and close EntityManager utx.commit(); em.close() ; }
Application Managed EM Extended Persistence Context Helper public class ExtendedPersistenceContextServlet  extends  HttpServlet  { @PersistenceUnit EntityManagerFactory emf; public EntityManager  getEntityManager (HttpSession s) {   EntityManager em = s.getAttribute(“entityManager”);   if (em==null) {   em = emf.createEntityManager();   s.setAttribute(“entityManager”, em);   }   em.joinTransaction();   return em; } public void  endConversation (HttpSession s) {   getEntityManager().close();   s.removeAttribute(“entityManager”); }
EntityManager in JavaSE Application must use  javax.persistence.Persistence  class  to obtain an instance of EntityManagerFactory No propagation  of persistence context
Transaction Demarcation Appication managed entity manager Transactions  JavaSE are always resource local Resource local transactions Use EntityTransaction from EntityManager
Example EntityManager in JavaSE public class SalaryChanger { public static void main(String[] args) { EntityManagerFactory emf =  Persistence .createEntityManagerFactory(“HRSystem”); EntityManager em =  emf.createEntityManager(); try { EntityTransaction tx = em.getTransaction(); Employee empl =  em.find (Employee.class, new Integer(args[0])); empl.setSalary(new Integer(args[1])); tx.commit(); } finally { em.close(); emf.close(); } }
RESOURCE_LOCAL Transaction  Java SE // Create EntityManagerFactory for a persistence unit  // called manager1 EntityManagerFactory emf =  Persistence.createEntityManagerFactory(&quot;manager1&quot;); EntityManager em = emf.createEntityManager(); // Get a transaction instance and start the transaction EntityTransaction tx = em.getTransaction(); // Create a new customer,persist and commit it. tx.begin(); Distributor dist = new Distributor(); dist.setName(&quot;Joe Smith&quot;); em.persist(dist); tx.commit(); em.close(); emf.close();
Summary EntityManager Types Container managed  Entity Manager   Obtained by  Injection   or  JNDI  lookup,   don't  need to  close Always JTA   Persistence Context   Transaction Scoped Entities detached at end of transaction Or  Extended   Persistence Context Entities stay managed beyond transaction only for  Stateful Session Bea n Application managed   Entity Manager Created using  EntityManagerFactory ,  must  close   May be either  JTA  or  RESOURCE_LOCAL   Must use  extended  persistence context : created when the entity manager is created and kept until the entity manager is closed No propagation  of  persistence context
Queries EJB Query Syntax Named, Dynamic, Native Queries Polymorphic Queries
Java Persistence Query Language SQL-like  query language Queries expressed in terms of  Entities Provides  functionality  like  select, update  and  delete Portable  across databases
Projection SELECT  e.name, d.name FROM Employee e JOIN e.department d WHERE e.status = ‘FULLTIME’ SELECT new  com.example.EmployeeInfo (e.id, e.name, e.salary, e.status, d.name) FROM Employee e JOIN e.department d WHERE e.address.state = ‘CA’
Subqueries SELECT DISTINCT emp FROM Employee emp WHERE EXISTS ( SELECT mgr FROM Manager mgr WHERE emp.manager = mgr AND emp.salary > mgr.salary)
Joins SELECT DISTINCT o FROM Order o JOIN o.lineItems l JOIN l.product p WHERE p.productType = ‘shoes’ SELECT DISTINCT c FROM Customer c LEFT  JOIN FETCH c.orders WHERE c.address.city = ‘San Francisco’
Queries Dynamic queries Query  string  is specified at  runtime EntityManager is factory for Query objects createQuery
Dynamic Queries public List findWithName (String name) { Query query =  em.createQuery  ( “ SELECT c FROM Customer c” + “ WHERE c.name LIKE  :custName ”) query.setParameter(“ custName ”, name); query.setMaxResults(10); return (query.getResultList()); }
Queries Static queries Defined with Java language  metadata  or  XML Annotations:  @NamedQuery , @NamedNativeQuery EntityManager is factory for Query objects createNamedQuery
Static NamedQuery @NamedQuery ( name=“findCustomersByName”, queryString= “ SELECT c FROM Customer c” + “WHERE c.name LIKE  :custName ” ) @PersistenceContext public EntityManager em;  Query query = em.createNamedQuery (“findCustomersByName”); query.setParameter(“ custName ”, “smith”) List customers = query.getResultList();
Native SQL vs JPQL Native SQL Returns raw data – field values for the entity Complex SQL for navigating relationships Java Persistence Query Language Returns entities Relationships can be navigated using a “.” Similar to SQL - small learning curve
Queries Query methods for controlling max results, pagination, flush mode
Advance Query API Scrolling through result set Query hints Query q = em.createQuery(“select e from Employee e”, Employee.class); //Set cursor to the 6 th  record q. setFirstResult (5); //Retrieve only 100 employess q. setMaxResult (100); Collection<Employee> emps = q.getResultList(); q. setHint (“ toplink.cache-usage ”,  &quot;DoNotCheckCache&quot; );
Stateful Session Scroller @Stateful public class ResultPagerBean implements ResultPager { @PersistenceContext (unitName=&quot;QueryPaging&quot;) private  EntityManager em ; private String reportQueryName; private int  currentPage, maxResults,pageSize ; public void  init (int pageSize, String countQueryName, String reportQueryName) { currentPage = 0; this.pageSize = pageSize; this.reportQueryName = reportQueryName; maxResults  = (Long)  em.createNamedQuery ( countQueryName ) .getSingleResult(); maxResults  = resultCount.longValue(); } public List  getCurrentResults () { return em.createNamedQuery(reportQueryName) . setFirstResult ( currentPage * pageSize ) . setMaxResults ( pageSize ) .getResultList(); } public void next() { currentPage++; }
Polymorphic Queries All Queries are polymorphic by default That is to say that the FROM clause of a query designates not only instances of the specific entity class(es) to which it explicitly refers but of subclasses as well select avg(e.salary) from  Employee e where e.salary > 80000 This example returns average salaries of all employees, including subtypes of Employee, such as Manager .
Best Practices and Gotchas
EJB 3.0 specification assumes Optimistic locking based on version consistency All relationships with @Version included in check Not used by application @Entity class Order { @Version public TimeStamp version; In highly concurrent environment, pessimistic locking may be a better option Optimistic locking may result in lots of rollbacks Vendor specific @QueryHint(name=TopLinkQueryHints.PESSIMISTIC_LOCK, value=PessimisticLock.LockNoWait); Locking
Transactions May not want a  transaction when browsing data For Session Bean use  @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
Executing a Query Outside of a Transaction @Stateless public class QueryServiceBean implements QueryService { @PersistenceContext(unitName=&quot;EmployeeService&quot;) EntityManager em; @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) public List  findAllDepartmentsDetached()  { return em.createQuery(&quot;SELECT d FROM Department d&quot;) .getResultList(); } // ... }
Transactions Propagation of EntityManagers between components Create EntityManager in JTA transaction If EntityManager created outside of JTA transaction, use joinTransaction() EntityManager em = factory.createEntityManager() ; utx.begin() ; em.joinTransaction() ; Join this transaction
Fetch Types Data fetching strategy EAGER  –  load  data all together  immediately LAZY  –  load  data only  when accessed Hint  when  FetchType  is  LAZY FetchType  LAZY  benefits  large  objects and  relationships  with deep hierarchies Use when field or relationship may not be used Default is  EAGER   except  for  1:m  and  m:n   relationships EAGER  required if accessing properties  outside a txn Accessing  unloaded  properties on  Detached Entity  throws an  exception
Example Lazy // Order Entity has a 1:M relationship with OrderLineItem. @Entity public class Order { @OneToMany(fetchType= FetchType.LAZY , ...)  public Collection<OrderLineItem> getLineItems(){ return lineItems; } } //  Stateless Session Bean @Stateless public class OrderSessionStateless { @PersistenceContext private EntityManager em; public Order loadOrder(String orderID){ em.find(orderID);  } }
Entity benchmark FetchType—Relationship Source: Internal benchmarks
Join Fetch to load relationship SELECT DISTINCT c FROM Customer c LEFT  JOIN FETCH c.orders WHERE c.address.city = ‘San Francisco’
Navigating Relationships Options… EAGER—Too many joins? SELECT d.id, ..., e.id, ...  FROM Department d left join fetch Employee e on e.deptid = d.id What will it look like if you need to join more  than two tables? LAZY—N +1 problem  SELECT d.id, ... FROM Department d // 1 time SELECT e.id, ... FROM Employee e  WHERE e.deptId = ? // N times How many trips to the database will it be if there are more relationships?
Navigating Relationships Solution is in the Query string Query q = em.createQuery( “ select d from Department d LEFT JOIN FETCH  d.employees”); Using FETCH JOIN Puts you in charge Needs careful consideration when to use No similar solution for non-relationship fields or properties (BLOB, CLOB) The solution
And detached entities… Navigating Relationships Accessing a LAZY relationship from a detached entity : Can get an exception Can get  null Can get a previously cached value—another problem Is there a portable solution? Use JOIN FETCH for queries or fetch type EAGER Access the collection before the entity is detached d.getEmployees().size(); Not flexible Can return too many instances
Parallel Updates to Same Object tx1.begin();   //Joe's employee id is 5  e1 = findPartTimeEmp(5);    //Joe's current rate is $9  e1.raiseByTwoDollar(); tx1.commit(); //Joe's rate will be $11 tx2.begin();   //Joe's employee id is 5  e1 = findPartTimeEmp(5);   ... ... //Joe's current rate is $9  if(e1.getRate() < 10)   e1.raiseByFiveDollar();   ... tx2.commit(); //Joe's rate will be $14 No parallel updates expected or detected
How to Guard Against  Parallel Updates? Use Optimistic concurrency Introduce Version attribute to Employee   public class Employee {   @ID int id;   ...   @Version int version;   ...   } Results in following SQL  “ UPDATE Employee SET ...,  version = version + 1     WHERE id = ? AND  version = readVersion ” OptimisticLockException if mismatch
Parallel Updates to Same Object tx1.begin();  //Joe's employee id is 5   //e1.version == 1  e1 = findPartTimeEmp(5);    e1.raiseByTwoDollar(); tx1.commit(); //e1.version == 2 in db tx2.begin();  //Joe's employee id is 5   //e1.version == 1  e1 = findPartTimeEmp(5);   ... ... //Joe's current rate is $9  if(e1.getRate() < 10)   e1.raiseByFiveDollar();   ... //e1.version == 1 in db? tx2.commit(); //Joe's rate will be $14 //OptimisticLockException @Version attribute enables detection of parallel updates
Using Stale Data for Computation tx1.begin();  d1 = findDepartment(dId);  //d1's original name is  //”Engrg”  d1.setName(“MarketEngrg”); tx1.commit();  tx2.begin();  e1 = findEmp(eId);  d1 = e1.getDepartment();   em.lock(d1, READ);  if(d1's name is “Engrg”)    e1.raiseByTenPercent(); //Check d1.version in db tx2.commit(); //e1 gets the raise he does //not deserve //Transaction rolls back Read lock ensures non-stable data at commit
Write lock prevents parallel updates Using Stale Data for Computation tx1.begin();  e1 = findDepartment(dId);  //d1's original name is  //”Engrg”  d1.setName(“MarketEngrg”); tx1.commit();  //tx rolls back tx2.begin();  e1 = findEmp(eId);  d1 = e1.getDepartment();   em.lock(d1, WRITE);  em.flush();  //version++ for d1  if(d1's name is “Engrg”)    e1.raiseByTenPercent(); tx2.commit();
Optimistic versus Pessimistic Concurrency Pessimistic Concurrency Lock the row when data is read in Issue “SELECT ... FOR UPDATE” SQL to read data Use different connection isolation level Pros—Simpler application code Cons—Database locks No portable support in this version of spec Suitable when application has many parallel updates Optimistic Concurrency Pros—No database locks held Cons—Requires a version attribute in schema   Databases are not optimized for rollback   Retries complicate application logic Suitable when application has few parallel updates
Cascade Type Specifies operations cascaded to associated entities Used for relationships ALL, PERSIST, MERGE, REMOVE, REFRESH Default is none If possible avoid MERGE in relationships with deep hierarchies Do it manually Limit the scope of MERGE @Entity public class Order { @OneToMany( cascade=PERSIST ,  fetch=LAZY ) Collection<LineItems> lineItems;
Entity merge  Don't @Entity public class Order { @OneToMany(cascade=CascadeType.ALL, ...)  public Collection<OrderLineItem> getLineItems(){ return lineItems; } } @Stateless public class OrderSessionStateless { @PersistenceContext  private EntityManager em; public void applyDiscount( Collection<OrderLineItem> lis){ applyDiscount(lis); em.merge(order); } }
Entity merge  DO @Entity public class Order { @OneToMany(cascade=CascadeType.ALL, ...)  public Collection<OrderLineItem> getLineItems(){ return lineItems; } } @Stateless public class OrderSessionStateless { @PersistenceContext  private EntityManager em; public void applyDiscount( Collection<OrderLineItem> lis){ for(OrderLineItem li : lis) { applyDiscount(li); em.merge(li); } } }
EJB 3.0 Persistence Summary All new Entities Simplifies persistence model Supports Light-weight persistence model Support both J2SE and J2EE environments Extensive querying capabilities
Enterprise JavaBean 3.0 and Java Persistence APIs: Simplifying Persistence   Carol McDonald [email_address] Sun Microsystems

Java Persistence API

  • 1.
    Enterprise JavaBean 3.0& Java Persistence APIs: Simplifying Persistence Carol McDonald Java Architect Sun Microsystems
  • 2.
    Speaker’s Qualifications Carol cDonald: Java Architect at Sun Microsystems Before Sun, worked on software development of: Application to manage car Loans for Toyota (>10 million loans) Pharmaceutical Intranet ( Roche Switzerland) Telecom Network Mgmt ( Digital France) X.400 Email Server ( IBM Germany)
  • 3.
    JPA: Simplifying/Unifying/Standardizing PersistenceSimpler, easier and smarter Easy to develop POJO based programming/persistence model Simple Java classes – not EJB components , only 1 file instead of 3 Entities usable outside the container No need for D ata T ransfer O bjects Facilitates testability Most configuration is defaulted – configure by exception only (configure only to override default)
  • 4.
    Simplifying/Unifying Persistence cont.Standardized o bject/ r elational m apping Standardized annotations @ and XML configuration files xml for mapping is optional Support for pluggable 3 rd party Persistence provider s Usable in Java EE , Enterprise JavaBeans 3.0 and Java SE environments
  • 5.
    Entities P lain O ld J ava O bjects (not an EJB) Created by means of new No required interfaces (home, ejb, callback..) Have persistent identity May have both persistent and non-persistent state Simple types (e.g., primitives, wrappers, enums, serializables) Composite dependent object types (e.g., Address) Non-persistent state ( transient or @Transient) Can extend other Entity and non-Entity classes Serializable; usable as detached objects in other tiers No need for d ata t ransfer o bjects
  • 6.
    Entity Annotated as“Entity” @Id denotes primary key @Entity public class Customer implements Serializable { @Id protected Long id; protected String name; public Customer() {} public Long getId() {return id;} public String getName() {return name;} public void setName(String name) {this.name = name;} … }
  • 7.
    Data Model and O-R Mapping Basic and Relationship Entity Inheritance Entity Identity
  • 8.
    An Example DataModel Maps entity states to data store Maps relationship to other entities Customer int id String name int c_rating Image photo Set<Order> orders Collection<Phone> phones ... Order int id Customer cust ... Phone int id Collection<Customer> custs ... 1 M M N
  • 9.
    Simple Mapping Mappingdefaults to matching column name . Only configure if entity field and table column names are different public class Customer { int id; String name; int c_rating; Image photo; } @Entity(access=FIELD) @Column(name=“CREDIT”) @Id @Lob CUSTOMER ID NAME CREDIT PHOTO
  • 10.
    Entity Annotated as“Entity” @Id denotes primary key @Entity public class Customer implements Serializable { @Id protected Long id; protected String name; @Transient protected int reservationCount; public Customer() {} public Long getId() {return id;} public String getName() {return name;} public void setName(String name) {this.name = name;} … }
  • 11.
    Entity Class forCustomer @Entity(access=FIELD) @Table(name = “customer”) public class Customer { @Id public int id; ... public String name; @Column(name=”CREDIT”) public int c_rating; @LOB public Image photo; ... } Annotated as “Entity” Data are accessed as fields @Id denotes primary key Maps to “customer” table Specify the table column to map to
  • 12.
  • 13.
    Entity Relationships One-to-one,one-to-many, many-to-many, many-to-one, relationships among entities bi-directional or uni-directional Support for Collection, Set, List and Map Need to specify owning side in relationships Owning side table has the foreign key OneToOne relationship – the side with the foreign key OneTo Many , Many ToOne – many side
  • 14.
    Relationship Mappings –OneToMany Bidirectional public class Order { int id; ... Customer cust ; } public class Customer { int id; ... Set<Order> orders; } @Entity(access=FIELD) @Entity(access=FIELD) @ManyToOne @OneToMany(mappedBy=“ cust ”) @Id @Id 1 n has to say where the foreign key is using mappedBy CUSTOMER ID . . . ORDER CUST_ID ID . . .
  • 15.
    Example ManyToOne bi-directionalOrder is the owner must call order.setCustomer (cust) whenever order added to customer. @Entity public class Order { @Id protected Long id; … @ManyToOne protected Customer cust; … public Customer getCustomer() {return cust;} public void setCustomer (Customer cust) { this.cust = cust; } } @Entity public class Customer { @Id protected Long id; … @OneToMany(mappedBy=“cust”) protected Set<Order> orders = new HashSet(); … public void addOrder (Order order) { this.orders.add (order); order.setCustomer (this); } }
  • 16.
    Relationship Mappings –ManyToOne Automatically creates a ADDR_ID field for mapping. Can be overridden via @ManyToOne annotation public class Customer { int id; Address addr ; } CUSTOMER ADDR_ID ID ADDRESS . . . ID @Entity(access=FIELD) @ManyToOne @Id ADDR_ID
  • 17.
    Relationship Mappings –ManyToMany public class Customer { int id; ... Collection<Phone> phones ; } @Entity(access=FIELD) @Entity(access=FIELD) @Id @Id @ManyToMany @ManyToMany(mappedBy=“phones”) public class Phone { int id; ... Collection<Customer> custs ; } Join table name is made up of the 2 entities. Field name is the name of the entity plus the name of the PK field PHONES _ID CUSTS _ID CUSTOMER ID . . . PHONE ID . . . CUSTOMER_PHONE ID
  • 18.
    Relationship Mappings –ManyToMany Can override the default column names PHONES_ID CUST_ID CUSTOMER ID . . . PHONE ID . . . CUST_PHONE @Entity(access=FIELD) public class Customer { ... @ManyToMany @ JoinTable (table=@Table(name=“CUST_PHONE”), joinColumns =@JoinColumn(name=“CUST_ID”), inverseJoinColumns =@JoinColumn(name=“PHONES_ID”)) Collection<Phone> phones; }
  • 19.
    Example ManyToMany bi-directionalcustomer is the owning side: must add/remove the phone from the customer's phones property. @Entity public class Phone { @Id protected Long id; … @ManyToMany(mappedBy=“phones”) protected Set<Customer> customers = new HashSet(); … } @Entity public class Customer { @Id protected Long id; … @ManyToMany protected Set<Phone> phones = new HashSet(); … private Set<Phone> getPhones() {return phones;} public void addPhone (Phone phone) { this .getPhones(). add (phone); } public void removePhone (Phone phone) { this .getPhones(). remove (phone); } }
  • 20.
    Mapping of EmbeddedObjects @Entity(access=FIELD) @Embedded @Id @Embeddable(access=FIELD) public class CustomerInfo { String name; int credit; @Lob Image photo; } public class Customer { int id ; CustomerInfo info; } Embedded objects have no identity of their own . Takes on the identity of the container object CUSTOMER ID NAME CREDIT PHOTO
  • 21.
    Entity Inheritance: 3possibilities: Concrete/Abstract entity class Annotated with @Entity Behaves like an entity Mapped superclass Non entity class Entity can extend
  • 22.
    Entity Inheritance –(Abstract) Entity Class @Entity public abstract class Person { @Id protected Long id; protected String name; @Embedded protected Address address; } @Entity public class Customer extends Person { @Transient protected int orderCount; @OneToMany protected Set<Order> orders = new HashSet(); } @Entity public class Employee extends Person { @ManyToOne protected Department dept; }
  • 23.
    Entity Inheritance Concrete/Abstractentity class Mapped superclass Contains common fields for all entities Provides common entity state Mapped superclass is NOT an entity Annotated with @MappedSuperclass Non entity class Entity can extend:
  • 24.
    Entity Inheritance –Mapped Superclass @MappedSuperclass public class Person { @Id protected Long id; protected String name; @Embedded protected Address address; } @Entity public class Customer extends Person { @Transient protected int orderCount; @OneToMany protected Set<Order> orders = new HashSet(); } @Entity public class Employee extends Person { @ManyToOne protected Department dept; }
  • 25.
    Entity Inheritance Concrete/Abstractentity class Mapped superclass Non entity class State of non entity super class is not persisted Can not contain O/R mapping annotations Entity can extend
  • 26.
    Entity Inheritance –Non Entity Class public class Person { protected String name; } @Entity public class Customer extends Person { //Inherits name but not persisted @Id public int id; @Transient protected int orderCount; @OneToMany protected Set<Order> orders = new HashSet(); } @Entity public class Employee extends Person { //Inherits name but not persisted @Id public int id; @ManyToOne protected Department dept; }
  • 27.
    Mapping Entity Inheritanceto DB Table Inheritance mapping strategies: Single table Joined subclass Table per class
  • 28.
    Inheritance mapping strategiesObject Model AirAnimal wingSpan: int LandAnimal legCount: int Animal id: int name: String
  • 29.
    Inheritance mapping strategiesData Models Single table: each class is stored in a separate table each concrete class is stored in a separate table all classes stored in the same table ANIMAL ID NAME LAND_ANML ID LEG_COUNT AIR_ANML ID WING_SPAN Joined Subclass: Table per Class: LAND_ANML ID LEG_COUNT AIR_ANML ID WING_SPAN NAME NAME ANIMAL LEG_CNT ID DISC NAME WING_SPAN
  • 30.
    Discriminator Column andValue for Single Table @Entity @Table(name=&quot;ANIMAL&quot;) @Inheritance(strategy=SINGLE_TABLE) @DiscriminatorColumnName(name=”DISC”) @DiscriminatorValue(“ANIMAL”) public class Animal { @Id protected int id; protected String name; ... } @Entity @DiscriminatorValue(&quot;LANDANIMAL&quot;) public class LandAnimal extends Animal { @Column(name=”LEG_CNT”) protected int legCount; ... ANIMAL LEG_CNT ID DISC NAME WING_SPAN
  • 31.
  • 32.
    Identity Every entityhas a persistence identity Uniquely identifies that entity Maps to primary key in the database Identity can be application or database generated Must be defined on the ROOT of entity hierarchy or mapped superclass
  • 33.
    Types of IdentitySimple @Id – single field/property in entity class @GeneratedValue User defined: @EmbeddedId – single field/property in entity class @IdClass – corresponds to multiple id field in entity class @Id @GeneratedValue(strategy=SEQUENCE) private int id; @EmbeddedId private EmployeePK pk; @Entity @IdClass (EmployeePK.class) public class Employee { @Id private String empName; @Id private int dept; Class must be @Embeddable
  • 34.
    Using orm.xml forMapping Can put some or all the mapping metadata in XML mapping files orm.xml located in META-INF directory of JAR Can use orm.xml to specify entity mappings Annotations not required At runtime, orm.xml override annotations
  • 35.
    Example of orm.xmlFile <entity-mappings> <entity class=”Customer”> <id name=”id”> <generated-value/> </id> <basic name=”c_rating”> <column name=”ratings”/> </basic> ... <one-to-many name=”orders” mapped-by=”cust”/> </entity> ... </entity-mappings> Overriding the default annotations in source
  • 36.
    Persistence EntityManager PersistenceUnit Persistence Context Entity Lifecycle Application Managed Persistence Transactions
  • 37.
    Persistence – KeyConcepts Persistence unit Entity manager Persistence context Transactions
  • 38.
    Persistence Unit PersistenceContext Persistence Context Primary interface to interact with underlying persistence engine A set of entities associated with a particular transaction Configuration for entities mapped to a single data store Persistence Unit MyApp Employee e = new Employee(); e.setName(“Lucas”); em.persist(e); persistence.xml
  • 39.
    Persistence Unit PersistenceUnit Configuration to map Entity classes in an application to a relational database persistence.xml defines one or more persistence units the JAR file that contains persistence.xml will be scanned for any classes annotated with @Entity < persistence version=&quot;1.0&quot; xmlns =&quot; http://java.sun.com/xml/ns/persistence &quot;> < persistence-unit name=&quot; OrderPU &quot; transaction-type=&quot;JTA&quot;> < provider > org.hibernate.HibernatePersistence </provider> < jta-data-source > jdbc/order </jta-data-source> < jar-file >../lib/order.jar</jar-file> < class >com.acme.Order</class> </persistence-unit> </persistence> Optional to define entity classes
  • 40.
    Persistence – KeyConcepts Persistence unit Entity manager Primary interface to interact with underlying persistence engine Persistence context A set of entities managed by Entity Manager Transactions
  • 41.
    EntityManager Persistence ContextPersistence Context Primary interface to interact with underlying persistence engine A set of managed entities associated with a particular transaction Configuration for entities mapped to a single data store Persistence Unit MyApp Employee e = new Employee(); e.setName(“Lucas”); em.persist(e); persistence.xml
  • 42.
    Persistence Context andEntityManager EntityManager API to manage the entity instance lifecycle Allows your program to interact with underlying persistence engine Provides the following functionalities Lifecycle operations – persist(), remove(), refresh(), merge() Finder – find(), getReference() Factory for query objects – createNamedQuery(), createQuery(), createNativeQuery() Managing persistence context – flush(), clear(), close(), getTransaction(), ... Persistence Context Set of managed entities , belonging to a single persistence unit
  • 43.
    Persistence Context andEntityManager Persistence Context EntityManager persist() remove() refresh() merge() find() createQuery() createNamedQuery() contains() flush() SessionBean JavaBean Servlet
  • 44.
    Persistence – KeyConcepts creates creates Configured by Manages
  • 45.
    EntityManager Example @Stateless public ShoppingCartBean implements ShoppingCart { @PersistenceContext EntityManager entityManager; public OrderLine createOrderLine(Product product , Order order) { OrderLine orderLine = new OrderLine(order, product); entityManager.persist (orderLine) ; return (orderLine); } public OrderLine updateOrderLine(OrderLine orderLine) { return ( entityManager.merge ( orderLine ) ); } } Dependency injection
  • 46.
    EJB 3.0: DependencyInjection Dependency Injection Bean specifies what it needs through @ References to resources are injected when instance is constructed: @Resource : for connection factories, EJBContext, UserTransaction , etc. @EJB : For EJB References @PersistenceContext : For container-managed EntityManager @PersistenceUnit : For EntityManagerFactory
  • 47.
    Entity Lifecycle StateDiagram New entity instance is created Entity is not yet managed or persistent Entity becomes managed Entity becomes persistent in database on transaction commit new() Entity is removed Entity is deleted from database on transaction commit State of detached entity is merged back into managed entity no longer associated with persistence context New Detached Removed Managed persist() merge () remove () Updates PC ends
  • 48.
    Entity Lifecycle Illustrated– The Code @Stateless public ShoppingCartBean implements ShoppingCart { @PersistenceContext EntityManager entityManager; public OrderLine createOrderLine(Product product , Order order) { OrderLine orderLine = new OrderLine(order, product); entityManager.persist(orderLine); return (orderLine); } public OrderLine updateOrderLine(OrderLine orderLine) { OrderLine newOL= entityManager.merge(orderLine) return ( newOL ) ); } } New entity Managed entity Detached entity
  • 49.
    Entity Manager Persist: Insert a new instance of the entity into the database (when transaction commits) The entity instance becomes “managed” in the persistance context Persist operation optionally cascades to related objects public Customer createCustomer(intid, String name) { Customer cust= new Customer(id, name); entityManager.persist(cust); return cust; }
  • 50.
    Cascading Persist example:ManyToOne public class Order { int id; ... Customer cust ; } public class Customer { int id; ... Set<Order> orders; } @Entity(access=FIELD) @Entity(access=FIELD) @ManyToOne @OneToMany(mappedBy=“cust”) @Id @Id CUSTOMER ID . . . ORDER CUST_ID ID . . .
  • 51.
    Persist OneToManybi-directional Not Cascading em.persist to persist the order @Stateless public class OrderManagementBean implements OrderManagement { … @PersistenceContext EntityManager em; … public Order addNewOrder (Long id,Product product){ Customer cust = em.find (Customer.class, id); Order order = new Order(product); customer.getOrders().add(order); order.setCustomer(cust); em.persist(order); return order; } }
  • 52.
    Cascading Persist cascade=Persist Order persisted automatically, when added to Customer @Entity public class Customer { @Id protected Long id; … @OneToMany(cascade=PERSIST) protected Set<Order> orders = new HashSet(); } … public Order addNewOrder(Customer customer, Product product) { Order order = new Order(product); customer.getOrders().add(order); order.setCustomer(cust); return order; }
  • 53.
    Entity Manager Find,Remove: Find Get a managed entity instance with a given persistent identity Return null if not found Remove Delete entity with the given persistent identity from the database (deleted when transaction commits) Optionally cascades to related objects public void removeCustomer(Long custId) { Customer cust= entityManager.find (Customer.class, custId); entityManager.remove (cust); }
  • 54.
    Remove When orderis removed, the lineItems are removed with it @Entity public class Order { @Id protected Long orderId; … @OneToMany(cascade={PERSIST,REMOVE}) protected Set<LineItem> lineItems = new HashSet(); } … @PersistenceContext EntityManager em; … public void deleteOrder(Long orderId) { Order order = em.find(Order.class, orderId); em.remove(order); }
  • 55.
    Merge: Stateof detached entity gets merged into a managed copy of entity Managed entity is returned Merge operation optionally cascades to related objects public Customer storeUpdatedCustomer(Customer cust) { Customer customer =entityManager.merge( cust ); return customer; } Managed Not managed
  • 56.
    Merge When orderis merged, the lineItems are merged with it @Entity public class Order { @Id protected Long orderId; … @OneToMany(cascade={PERSIST, REMOVE, MERGE}) protected Set<LineItem> lineItems = new HashSet(); } … @PersistenceContext EntityManager em; … public Order updateOrder(Order changedOrder) { return em.merge(changedOrder); }
  • 57.
    Detached Objects asDTOs public OrderLine updateOrderLine( OrderLine orderLine) { OrderLine newOL = em.merge(orderLine) return(newOL ); } Entity beans may be passed by value as detached objects Must implement Serializable interface if detached object is to be sent across the wire Returned to caller as Detached Detached Managed Detached after return
  • 58.
    Types of PersistenceContext and Entity Managers Persistence Context Entity Manager Persistence Context Entity Manager Data source same entity
  • 59.
    Entity Manager &Persistence Context Types Two types of EntityManagers: Container-managed EntityManager – intended for Java EE Application-managed EntityManager – intended for Java SE/EE Two types of persistence context: transaction-scoped persistence context extended persistence context
  • 60.
    Container Managed EntityManager Container-managed entity manager EntityManager Lifecycle managed by the Java EE container EntityManager obtained via resource injection or JNDI lookup: @PersistenceContext EntityManager entityManager;
  • 61.
    Types of PersistenceContext Persistence Context 2 Types: lifetime maybe transaction-scoped or extended Transaction-scoped persistence context bound to a JTA transaction— starts and ends at transaction boundaries Propagated across EJB components within JTA transactions entities are detached from the persistence context when transaction ends
  • 62.
    Java™ Transaction ServiceApplication Server Transaction Service Application UserTransaction interface Resource Manager XAResource interface Transactional operation TransactionManager Interface Resource EJB Transaction context
  • 63.
    Transactions with Container Managed EntityManager JTA Transactions are controlled through JTA Container-managed entity manager always JTA transactions
  • 64.
    EJB & Container-ManagedEntity Manager & Transaction-scoped Persistence Context @Stateless public ShoppingCartBean implements ShoppingCart { @PersistenceContext(unitName=”orderPU”) EntityManager entityManager; public OrderLine createOrderLine (Product product , Order order) { OrderLine orderLine = new OrderLine(order, product); entityManager.persist(orderLine); return (orderLine); } public OrderLine updateOrderLine(OrderLine orderLine) { return ( entityManager.merge(orderLine) ); } } Persistence context
  • 65.
    Spring 2.0 & JPA @Repository @Transactional public class CatalogDAO implements CatalogService { @PersistenceContext (unitName=&quot;PetCatalogPu&quot;) private EntityManager em; public List<Item> getItems (int firstItem,int batchSize) { Query q = em. createQuery(&quot;select object(o) from Item as o&quot;); q.setMaxResults(batchSize); q.setFirstResult(firstItem); List<Item> items= q.getResultList(); return items; }
  • 66.
    Java EE JTATransactions Session Bean: Container-managed transaction is default Specify declaratively Annotation: @TransactionAttribute Values: REQUIRED (default) , REQUIRES_NEW, MANDATORY, NEVER, NOT_SUPPORTED, SUPPORTS On method or class Session Bean: Bean-managed transactions @Resource UserTransaction to get UserTransaction API Servlet: uses @Resource UserTransaction to get JTA UserTransaction API
  • 67.
    Stateless Session Beanin Java EE 5.0 @Stateless public class AirlineReservationBean implements AirlineReservation { . . . @TransactionAttribute(MANDATORY) public boolean book (int passId, int flightId) { Flight flight = em.find(Flight.class, flightId); Passenger pgr = em.find(Passenger.class, passId); return flight.addPassenger(pgr); } .. } NEW! Java EE 5 Container Managed Transaction Container Managed Transaction
  • 68.
    Declarative Transaction ManagementExample TX_REQUIRED TX_REQUIRED TX_REQUIRED PC PC PC Session Facade Inventory Service Order Service Check Out 1. Update Inventory New Persistence Context Persistence Context Propagated Transaction Attributes 2. Create Order and send JMS message to Warehouse Application
  • 69.
    Persistence Context Propagation@Stateless public class ControllerBean implements ControllerService { @EJB InventoryService inv ; @EJB OrderService ord ; public void manageOrderInventory(Item i, Product p) { inv.createOrder (item); ord.updateInventory (Product p) } }
  • 70.
    Persistence Context Propagation@Stateless public class OrderServiceBean implements OrderService { @PersistenceContext EntityManager em1; public void createOrder (Item item) { em1.persist (new Order(item)); } } @Stateless public class InventoryServiceBean implements InventoryService { @PersistenceContext EntityManager em2; public void updateInventory (Product p) { Product product = em2.merge (p); . . . } }
  • 71.
    Transaction Example Application Server Transaction Manager Transaction context DataBase Server and JMS Provider Resource Client Controller Inventory Order 1) Check Out TX_REQUIRED TX_REQUIRED BEGIN 4) Update Inventory 7) createOrder 11) Check context x to see if updates will work 12) Commit or rollback Start Prepare 10) END
  • 72.
    Web & Container-ManagedEM Servlet Resource injection and Thread safety : EntityManager instance is not thread safe Servlets are multi-threaded Entity Manager Can be obtained using JNDI Lifecyle managed by the container So still less code than application managed
  • 73.
    Beware of InjectedObjects public class ShoppingCartServlet extends HttpServlet { @PersistenceContext EntityManager em ; protected void doPost(HttpServlet req, ...) { Order order order = ...; em.persist(order) ; } public class ShoppingCartServlet extends HttpServlet { @PersistenceUnit (name=&quot; PetstorePu &quot;) protected void doPost(HttpServlet req, ...) { EntityManager em = (EntityManager) new InitialContext().lookup(&quot;java:comp/env/PetstorePu&quot;); Order order order = ...; em.persist(order); } WRONG CORRECT EntityManager instance is not thread safe, Servlets are multi-threaded
  • 74.
    Web and JTATransactions must be managed by the developer Unlike with EJBs where they can be managed by the container Use @Resource UserTransaction utx ; Begin(), Commit (), rollback ()
  • 75.
    Web JTA Transactionand Container EM protected void buyBook(String book, int custId, String creditCard) throws … { utx.begin(); Customer customer = new CustomerHelper (). getCustomer (custId); Order order = new OrderHelper (). create (book, creditCard, customer); utx.commit(); } JTA
  • 76.
    Web JTA Transactionand Container EM EM public Order create (String book, String creditCard, Customer customer) { EntityManager em = (EntityManager) new InitialContext() .lookup(“java:comp/env/persistence/bookStore”); Order order = new Order(customer); order.setCreditCard(creditCard); order.setBook(book); em.persist (order); } //CustomerHelper public Customer getCustomer (int id) { EntityManager em = (EntityManager) new InitialContext().lookup( “ java:comp/env/persistence/bookStore”); return em.find (Customer.class, id); } // OrderHelper
  • 77.
    Recommendation: Stateless SessionBeans In our business logic bean, we had to deal with transactions explicitly Consider using a stateless session bean (EJB) Transactions managed by the container EM injected by container Also get other benefits: No more thread safety concerns Scalability (across server instances) Participate in cross-resource transactions
  • 78.
    Web component usingStateless Session @EJB CustomerMgr customerMgr ; @EJB OrderMgr orderMgr ; protected void buyBook(String book, int custId, String creditCard) throws … { Customer customer = customerMgr .getCustomer(custId); Order order = orderMgr .create(book, creditCard, customer); } No need for Transaction Management
  • 79.
    Stateless Session andContainer EM No need for JNDI lookup of EM No need for Transaction Management @Stateless public class OrderMgrBean implements OrderMgr { @PersistenceContext EntityManager em; create(String book, String creditCard, Customer cust) { Order order = new Order(cust); order.setCreditCard(creditCard); order.setBook(book); em.persist(order); } } @Stateless public class CustomerMgrBean implements CustomerMgr { @PersistenceContext EntityManager em; public Customer getCustomer(int id) { return em.find(Customer.class, id); } }
  • 80.
    Types of PersistenceContext Persistence Context lifetime maybe transaction-scoped or extended Transaction-scoped persistence context Extended persistence context spans multiple transactions exists from the time the EntityManager instance is created until it is closed Defined when the EntityManager instance is created
  • 81.
    Extended Persistence Context@Stateful public class ShoppingCart { //Specify that we want an EXTENDED @PersistenceContext (type=PersistenceContextType.EXTENDED) EntityManager em ; //Cached order private Order order ; //Find and cache order public void lookupOrder(String id) { //order remains managed for the lifetime of the bean order = em.find(Order.class, id); }
  • 82.
    Persistence Context- Transactionalvs. Extended @Stateless public class OrderSessionStateless implements OrderService { @PersistenceContext(unitName=”java_one”) EntityManager em; public void addLineItem (OrderLineItem li){ // First, look up the order. Order order = em.find(Order.class, orderID); order.lineItems.add(li); } @Stateful public class OrderSessionStateful implements OrderService { @PersistenceContext(type = PersistenceContextType. EXTENDED )) EntityManager em; // Order is a member variable Loaded from the db in lookupOrder Order order public void addLineItem (OrderLineItem li){ // No em.find invoked for the order object order.lineItems.add(li); }
  • 83.
    Extended Persistence Context– When? to keep and reuse managed entities that are the subject of the conversation workflow HTTPSession, stateful session bean Entities remain managed and cached over multiple transactions Become detached when EntityManager is closed or when Stateful session bean is removed
  • 84.
    Conversation @Stateful public class OrderBean { @PersistenceContext(type=EXTENDED) EntityManager em ; public void add(String itemCode, int qty) { ... } public void confirmOrder() { ... } ... } ________________________________________________________________ protected void doPost(HttpServletRequest req, ...) throws ... { String cmd = req.getParameter(“cmd”); if (cmd.equals(“NEW”)) { //Create stateful session bean, hold in HttpSession req.getSession().setAttribute(“order”, orderBean); } else if (cmd.equals(“ADD_ITEM”)) { //Add item to order bean orderBean.add(...); } else if (cmd.equals(“CONFIRM”)) { orderBean.confirmOrder(); order.remove(); req.getSession().removeAttribute(“order”); }
  • 85.
    Persistence Context Source:Internal benchmarks Does it affect performance? Micro benchmark with lots of lookups
  • 86.
    Entity Manager 2Types Container-managed entity manager Application-managed entity manager Created by EntityManagerFactory : EntityManager em = emf.createEntityManager(); Life cycle managed by the application Also available in Java SE environments Must use extended persistence context May use JTA (Web) or RESOURCE_LOCAL (Java SE) transaction type
  • 87.
    Transaction Demarcation Appicationmanaged entity manager Transactions Web are either JTA or Resource local JavaSE are always resource local JTA transaction UserTransaction API is injected
  • 88.
    Data Base TransactionManagement Transaction Manager EJB Container Resource Manager Data Base JTA A S EJB Local Servlet JDBC Transactions JTA Transactions servlet Resource Manager EJB servlet servlet servlet Java SE
  • 89.
    Application managed EntityManager and JTA Transaction ( Web ) @Resource UserTransaction utx; @PersistenceUnit EntityManagerFactory factory; public void createDistributor(String n) { //Begin transaction utx.begin(); EntityManager em = emf.createEntityManager() ; //Create entity Distributor dist = new Distributor(); dist.setName(n); //Save it em.persist( dist ) ; //Commit transaction and close EntityManager utx.commit(); em.close() ; }
  • 90.
    Application Managed EMExtended Persistence Context Helper public class ExtendedPersistenceContextServlet extends HttpServlet { @PersistenceUnit EntityManagerFactory emf; public EntityManager getEntityManager (HttpSession s) { EntityManager em = s.getAttribute(“entityManager”); if (em==null) { em = emf.createEntityManager(); s.setAttribute(“entityManager”, em); } em.joinTransaction(); return em; } public void endConversation (HttpSession s) { getEntityManager().close(); s.removeAttribute(“entityManager”); }
  • 91.
    EntityManager in JavaSEApplication must use javax.persistence.Persistence class to obtain an instance of EntityManagerFactory No propagation of persistence context
  • 92.
    Transaction Demarcation Appicationmanaged entity manager Transactions JavaSE are always resource local Resource local transactions Use EntityTransaction from EntityManager
  • 93.
    Example EntityManager inJavaSE public class SalaryChanger { public static void main(String[] args) { EntityManagerFactory emf = Persistence .createEntityManagerFactory(“HRSystem”); EntityManager em = emf.createEntityManager(); try { EntityTransaction tx = em.getTransaction(); Employee empl = em.find (Employee.class, new Integer(args[0])); empl.setSalary(new Integer(args[1])); tx.commit(); } finally { em.close(); emf.close(); } }
  • 94.
    RESOURCE_LOCAL Transaction Java SE // Create EntityManagerFactory for a persistence unit // called manager1 EntityManagerFactory emf = Persistence.createEntityManagerFactory(&quot;manager1&quot;); EntityManager em = emf.createEntityManager(); // Get a transaction instance and start the transaction EntityTransaction tx = em.getTransaction(); // Create a new customer,persist and commit it. tx.begin(); Distributor dist = new Distributor(); dist.setName(&quot;Joe Smith&quot;); em.persist(dist); tx.commit(); em.close(); emf.close();
  • 95.
    Summary EntityManager TypesContainer managed Entity Manager Obtained by Injection or JNDI lookup, don't need to close Always JTA Persistence Context Transaction Scoped Entities detached at end of transaction Or Extended Persistence Context Entities stay managed beyond transaction only for Stateful Session Bea n Application managed Entity Manager Created using EntityManagerFactory , must close May be either JTA or RESOURCE_LOCAL Must use extended persistence context : created when the entity manager is created and kept until the entity manager is closed No propagation of persistence context
  • 96.
    Queries EJB QuerySyntax Named, Dynamic, Native Queries Polymorphic Queries
  • 97.
    Java Persistence QueryLanguage SQL-like query language Queries expressed in terms of Entities Provides functionality like select, update and delete Portable across databases
  • 98.
    Projection SELECT e.name, d.name FROM Employee e JOIN e.department d WHERE e.status = ‘FULLTIME’ SELECT new com.example.EmployeeInfo (e.id, e.name, e.salary, e.status, d.name) FROM Employee e JOIN e.department d WHERE e.address.state = ‘CA’
  • 99.
    Subqueries SELECT DISTINCTemp FROM Employee emp WHERE EXISTS ( SELECT mgr FROM Manager mgr WHERE emp.manager = mgr AND emp.salary > mgr.salary)
  • 100.
    Joins SELECT DISTINCTo FROM Order o JOIN o.lineItems l JOIN l.product p WHERE p.productType = ‘shoes’ SELECT DISTINCT c FROM Customer c LEFT JOIN FETCH c.orders WHERE c.address.city = ‘San Francisco’
  • 101.
    Queries Dynamic queriesQuery string is specified at runtime EntityManager is factory for Query objects createQuery
  • 102.
    Dynamic Queries publicList findWithName (String name) { Query query = em.createQuery ( “ SELECT c FROM Customer c” + “ WHERE c.name LIKE :custName ”) query.setParameter(“ custName ”, name); query.setMaxResults(10); return (query.getResultList()); }
  • 103.
    Queries Static queriesDefined with Java language metadata or XML Annotations: @NamedQuery , @NamedNativeQuery EntityManager is factory for Query objects createNamedQuery
  • 104.
    Static NamedQuery @NamedQuery( name=“findCustomersByName”, queryString= “ SELECT c FROM Customer c” + “WHERE c.name LIKE :custName ” ) @PersistenceContext public EntityManager em; Query query = em.createNamedQuery (“findCustomersByName”); query.setParameter(“ custName ”, “smith”) List customers = query.getResultList();
  • 105.
    Native SQL vsJPQL Native SQL Returns raw data – field values for the entity Complex SQL for navigating relationships Java Persistence Query Language Returns entities Relationships can be navigated using a “.” Similar to SQL - small learning curve
  • 106.
    Queries Query methodsfor controlling max results, pagination, flush mode
  • 107.
    Advance Query APIScrolling through result set Query hints Query q = em.createQuery(“select e from Employee e”, Employee.class); //Set cursor to the 6 th record q. setFirstResult (5); //Retrieve only 100 employess q. setMaxResult (100); Collection<Employee> emps = q.getResultList(); q. setHint (“ toplink.cache-usage ”, &quot;DoNotCheckCache&quot; );
  • 108.
    Stateful Session Scroller@Stateful public class ResultPagerBean implements ResultPager { @PersistenceContext (unitName=&quot;QueryPaging&quot;) private EntityManager em ; private String reportQueryName; private int currentPage, maxResults,pageSize ; public void init (int pageSize, String countQueryName, String reportQueryName) { currentPage = 0; this.pageSize = pageSize; this.reportQueryName = reportQueryName; maxResults = (Long) em.createNamedQuery ( countQueryName ) .getSingleResult(); maxResults = resultCount.longValue(); } public List getCurrentResults () { return em.createNamedQuery(reportQueryName) . setFirstResult ( currentPage * pageSize ) . setMaxResults ( pageSize ) .getResultList(); } public void next() { currentPage++; }
  • 109.
    Polymorphic Queries AllQueries are polymorphic by default That is to say that the FROM clause of a query designates not only instances of the specific entity class(es) to which it explicitly refers but of subclasses as well select avg(e.salary) from Employee e where e.salary > 80000 This example returns average salaries of all employees, including subtypes of Employee, such as Manager .
  • 110.
  • 111.
    EJB 3.0 specificationassumes Optimistic locking based on version consistency All relationships with @Version included in check Not used by application @Entity class Order { @Version public TimeStamp version; In highly concurrent environment, pessimistic locking may be a better option Optimistic locking may result in lots of rollbacks Vendor specific @QueryHint(name=TopLinkQueryHints.PESSIMISTIC_LOCK, value=PessimisticLock.LockNoWait); Locking
  • 112.
    Transactions May notwant a transaction when browsing data For Session Bean use @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
  • 113.
    Executing a QueryOutside of a Transaction @Stateless public class QueryServiceBean implements QueryService { @PersistenceContext(unitName=&quot;EmployeeService&quot;) EntityManager em; @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) public List findAllDepartmentsDetached() { return em.createQuery(&quot;SELECT d FROM Department d&quot;) .getResultList(); } // ... }
  • 114.
    Transactions Propagation ofEntityManagers between components Create EntityManager in JTA transaction If EntityManager created outside of JTA transaction, use joinTransaction() EntityManager em = factory.createEntityManager() ; utx.begin() ; em.joinTransaction() ; Join this transaction
  • 115.
    Fetch Types Datafetching strategy EAGER – load data all together immediately LAZY – load data only when accessed Hint when FetchType is LAZY FetchType LAZY benefits large objects and relationships with deep hierarchies Use when field or relationship may not be used Default is EAGER except for 1:m and m:n relationships EAGER required if accessing properties outside a txn Accessing unloaded properties on Detached Entity throws an exception
  • 116.
    Example Lazy //Order Entity has a 1:M relationship with OrderLineItem. @Entity public class Order { @OneToMany(fetchType= FetchType.LAZY , ...) public Collection<OrderLineItem> getLineItems(){ return lineItems; } } // Stateless Session Bean @Stateless public class OrderSessionStateless { @PersistenceContext private EntityManager em; public Order loadOrder(String orderID){ em.find(orderID); } }
  • 117.
    Entity benchmark FetchType—RelationshipSource: Internal benchmarks
  • 118.
    Join Fetch toload relationship SELECT DISTINCT c FROM Customer c LEFT JOIN FETCH c.orders WHERE c.address.city = ‘San Francisco’
  • 119.
    Navigating Relationships Options…EAGER—Too many joins? SELECT d.id, ..., e.id, ... FROM Department d left join fetch Employee e on e.deptid = d.id What will it look like if you need to join more than two tables? LAZY—N +1 problem SELECT d.id, ... FROM Department d // 1 time SELECT e.id, ... FROM Employee e WHERE e.deptId = ? // N times How many trips to the database will it be if there are more relationships?
  • 120.
    Navigating Relationships Solutionis in the Query string Query q = em.createQuery( “ select d from Department d LEFT JOIN FETCH d.employees”); Using FETCH JOIN Puts you in charge Needs careful consideration when to use No similar solution for non-relationship fields or properties (BLOB, CLOB) The solution
  • 121.
    And detached entities…Navigating Relationships Accessing a LAZY relationship from a detached entity : Can get an exception Can get null Can get a previously cached value—another problem Is there a portable solution? Use JOIN FETCH for queries or fetch type EAGER Access the collection before the entity is detached d.getEmployees().size(); Not flexible Can return too many instances
  • 122.
    Parallel Updates toSame Object tx1.begin(); //Joe's employee id is 5 e1 = findPartTimeEmp(5); //Joe's current rate is $9 e1.raiseByTwoDollar(); tx1.commit(); //Joe's rate will be $11 tx2.begin(); //Joe's employee id is 5 e1 = findPartTimeEmp(5); ... ... //Joe's current rate is $9 if(e1.getRate() < 10) e1.raiseByFiveDollar(); ... tx2.commit(); //Joe's rate will be $14 No parallel updates expected or detected
  • 123.
    How to GuardAgainst Parallel Updates? Use Optimistic concurrency Introduce Version attribute to Employee public class Employee { @ID int id; ... @Version int version; ... } Results in following SQL “ UPDATE Employee SET ..., version = version + 1 WHERE id = ? AND version = readVersion ” OptimisticLockException if mismatch
  • 124.
    Parallel Updates toSame Object tx1.begin(); //Joe's employee id is 5 //e1.version == 1 e1 = findPartTimeEmp(5); e1.raiseByTwoDollar(); tx1.commit(); //e1.version == 2 in db tx2.begin(); //Joe's employee id is 5 //e1.version == 1 e1 = findPartTimeEmp(5); ... ... //Joe's current rate is $9 if(e1.getRate() < 10) e1.raiseByFiveDollar(); ... //e1.version == 1 in db? tx2.commit(); //Joe's rate will be $14 //OptimisticLockException @Version attribute enables detection of parallel updates
  • 125.
    Using Stale Datafor Computation tx1.begin(); d1 = findDepartment(dId); //d1's original name is //”Engrg” d1.setName(“MarketEngrg”); tx1.commit(); tx2.begin(); e1 = findEmp(eId); d1 = e1.getDepartment(); em.lock(d1, READ); if(d1's name is “Engrg”) e1.raiseByTenPercent(); //Check d1.version in db tx2.commit(); //e1 gets the raise he does //not deserve //Transaction rolls back Read lock ensures non-stable data at commit
  • 126.
    Write lock preventsparallel updates Using Stale Data for Computation tx1.begin(); e1 = findDepartment(dId); //d1's original name is //”Engrg” d1.setName(“MarketEngrg”); tx1.commit(); //tx rolls back tx2.begin(); e1 = findEmp(eId); d1 = e1.getDepartment(); em.lock(d1, WRITE); em.flush(); //version++ for d1 if(d1's name is “Engrg”) e1.raiseByTenPercent(); tx2.commit();
  • 127.
    Optimistic versus PessimisticConcurrency Pessimistic Concurrency Lock the row when data is read in Issue “SELECT ... FOR UPDATE” SQL to read data Use different connection isolation level Pros—Simpler application code Cons—Database locks No portable support in this version of spec Suitable when application has many parallel updates Optimistic Concurrency Pros—No database locks held Cons—Requires a version attribute in schema Databases are not optimized for rollback Retries complicate application logic Suitable when application has few parallel updates
  • 128.
    Cascade Type Specifiesoperations cascaded to associated entities Used for relationships ALL, PERSIST, MERGE, REMOVE, REFRESH Default is none If possible avoid MERGE in relationships with deep hierarchies Do it manually Limit the scope of MERGE @Entity public class Order { @OneToMany( cascade=PERSIST , fetch=LAZY ) Collection<LineItems> lineItems;
  • 129.
    Entity merge Don't @Entity public class Order { @OneToMany(cascade=CascadeType.ALL, ...) public Collection<OrderLineItem> getLineItems(){ return lineItems; } } @Stateless public class OrderSessionStateless { @PersistenceContext private EntityManager em; public void applyDiscount( Collection<OrderLineItem> lis){ applyDiscount(lis); em.merge(order); } }
  • 130.
    Entity merge DO @Entity public class Order { @OneToMany(cascade=CascadeType.ALL, ...) public Collection<OrderLineItem> getLineItems(){ return lineItems; } } @Stateless public class OrderSessionStateless { @PersistenceContext private EntityManager em; public void applyDiscount( Collection<OrderLineItem> lis){ for(OrderLineItem li : lis) { applyDiscount(li); em.merge(li); } } }
  • 131.
    EJB 3.0 PersistenceSummary All new Entities Simplifies persistence model Supports Light-weight persistence model Support both J2SE and J2EE environments Extensive querying capabilities
  • 132.
    Enterprise JavaBean 3.0and Java Persistence APIs: Simplifying Persistence Carol McDonald [email_address] Sun Microsystems