Java Persistence API: Best Practices Carol McDonald Java Architect
Agenda <ul><li>Entity Manager </li></ul><ul><li>Persistence Context </li></ul><ul><li>Entities </li></ul><ul><li>Schema & ...
Persistence  Context EntityManager persist() remove() refresh() merge() find() createQuery() createNamedQuery() contains()...
Catalog Java EE  Application DB Registration Application Managed Bean JSF Components Session Bean Entity Class Catalog Ite...
EJB EntityManager Example  @Stateless public class  Catalog  implements  CatalogService  { @PersistenceContext(unitName=”P...
Catalog Spring JPA Application DB Registration Application Managed Bean JSF Components Spring  Bean Entity Class Catalog I...
Spring  with JPA @Repository @Transactional public class CatalogDAO implements  CatalogService  { @PersistenceContext (uni...
Container vs Application Managed  <ul><li>Container managed entity managers (EJB, Spring Bean, Seam component) </li></ul><...
Agenda <ul><li>Entity Manager </li></ul><ul><li>Persistence Context </li></ul><ul><li>Entities </li></ul><ul><li>Queries <...
Persistence  Context EntityManager persist() remove() refresh() merge() find() createQuery() createNamedQuery() contains()...
Level1 and Level2 caches The terms “Java Virtual Machine” and “JVM” mean a Virtual Machine for the Java ™  Platform. Sourc...
Persistence Context <ul><ul><ul><li>Transaction commit </li></ul></ul></ul>new() persist() Updates remove() Merge() find()...
Entity Lifecycle Illustrated – The Code @Stateless  public ShoppingCartBean implements ShoppingCart { @PersistenceContext ...
Scope of Identity @Stateless  public ShoppingCartBean  implements ShoppingCart { @PersistenceContext   EntityManager entit...
Persistence Context <ul><li>Two types of persistence context </li></ul><ul><li>Transaction scoped </li></ul><ul><ul><li>Us...
Persistence Context Propagation <ul><li>@Stateless   public class  ShoppingCartBean  implements ShoppingCart { </li></ul><...
Persistence Context Propagation <ul><li>@Stateless  public class  OrderServiceBean  implements OrderService { </li></ul><u...
Declarative Transaction Management Example TX_REQUIRED TX_REQUIRED TX_REQUIRED PC PC PC Shopping Cart Inventory Service Or...
AuditServiceBean  @Stateless public class AuditServiceBean implements AuditService { @PersistenceContext private EntityMan...
Declarative Transaction Management Example 2 REQUIRED REQUIRED REQUIRES_NEW PC PC PC2 Shopping Cart Inventory Service Audi...
Persistence Provider PC Transaction Features <ul><li>Attribute-level change tracking </li></ul><ul><li>Only the minimal up...
Persistence Context Conversation with detached entity  Persistence Context merge() transaction-scoped  persistence context...
Conversation with detached entity @Stateless  public ShoppingCartBean  implements ShoppingCart  { @PersistenceContext   En...
Types of Persistence Context <ul><li>Persistence Context </li></ul><ul><ul><li>lifetime maybe transaction-scoped or extend...
Persistence Context Conversation with Exented Persistence Context request response request response Conversation extended ...
Extended Persistence Context @Stateful  public class  OrderMgr  { //Specify that we want an EXTENDED   @PersistenceContext...
Extended Persistence Context @Stateful  public class DeptMgr { @PersistenceContext (type=PersistenceContextType.EXTENDED) ...
Persistence Context- Transactional vs. Extended @Stateless public class  OrderMgr  implements OrderService { @PersistenceC...
Persistence Context Micro Benchmark <ul><li>Micro benchmark with lots of lookups </li></ul><ul><li>Persistence context is ...
SEAM Conversations  <ul><ul><li>@Name (&quot; shopper &quot;)‏ </li></ul></ul><ul><ul><li>@Scope ( CONVERSATION )‏ </li></...
Concurrency and Persistence Context  Object Identity  only  one  manage entity  in PC  represents a row  User  2 transacti...
Optimistic versus Pessimistic Concurrency <ul><li>Optimistic Concurrency </li></ul><ul><ul><li>Pros—No database locks held...
Preventing Parallel Updates <ul><li>use  @Version  for  optimistic  locking </li></ul><ul><li>Used by persistence manager ...
Preventing Parallel Updates – 1 <ul><li>tx1.begin();   //Joe's employee id is 5   //e1.version == 1  e1 = findPartTimeEmp(...
Preventing Stale Data JPA 1.0 <ul><li>Perform  read  or  write locks  on entities </li></ul><ul><li>Prevents non-repeatabl...
Preventing Stale Data <ul><li>tx1.begin();  d1  = findDepartment(dId);  //d1's original name is  //”Engrg”   d1 .setName(“...
<ul><ul><li>Write lock prevents parallel updates </li></ul></ul><ul><li>tx1.begin(); d1  = findDepartment(dId); </li></ul>...
Bulk Updates <ul><li>Update directly against the database, can be Faster But </li></ul><ul><ul><li>By pass  EntityManager ...
JPA 2.0 Locks <ul><li>JPA1.0 only supported optimistic locking, JPA 2.0 also supports pessimistic locks </li></ul><ul><li>...
<ul><li>//Read then lock: </li></ul><ul><li>Account  acct  = em. find (Account.class, acctId); </li></ul><ul><li>// Decide...
<ul><li>//  read  then  lock and refresh </li></ul><ul><li>Account  acct  = em. find (Account.class, acctId); </li></ul><u...
L2 cache shared across transactions and users Putting it all together User Session  User Session  User Session Persistence...
Second-level Cache <ul><li>L2 Cache shares entity state across various persistence contexts </li></ul><ul><ul><li>If cachi...
L2 Cache L2  Cache query that looks for a single object based on  Id  will go  1st  to  PC  then to  L2  cache, other quer...
L2 Caching <ul><li>Pros :  </li></ul><ul><ul><li>avoids database access for already loaded entities </li></ul></ul><ul><ul...
L2 Caching <ul><li>Configure L2 caching for entities that are  </li></ul><ul><ul><li>read often </li></ul></ul><ul><ul><li...
JPA 2.0 Shared Cache API <ul><li>entity cache shared across persistence unit </li></ul><ul><ul><li>Accessible from  Entity...
EclipseLink Caching Architecture EclipseLink caches Entities  in L2, Hibernate does not  EntityManager EntityManager Facto...
EclipseLink Extensions - L2 Caching <ul><li>Default : Entities read are L2  cached </li></ul><ul><li>Cache Configuration b...
<ul><li>@Entity </li></ul><ul><li>@Table(name=&quot;EMPLOYEE&quot;) </li></ul><ul><li>@Cache ( </li></ul><ul><li>type=Cach...
Hibernate  L2 Cache <ul><li>Hibernate L2 cache is  not configured by default   </li></ul><ul><li>Hibernate L2 does not cac...
Hibernate  L2 Cache <ul><li><!-- optional configuration file parameter --> </li></ul><ul><li>net.sf.ehcache.configurationR...
OpenJPA L2  Caching <ul><li>OpenJPA L2 caches object data and JPQL query results </li></ul><ul><li>Updated when data is lo...
Agenda <ul><li>Entity Manager </li></ul><ul><li>Persistence Context </li></ul><ul><li>Entities </li></ul><ul><li>Schema an...
Maintaining Relationship <ul><li>Application bears the responsibility of maintaining relationship between objects </li></u...
Example – Domain Model @Entity public class Employee { @Id private int id; private String firstName; private String lastNa...
Example – Managing Relationship public int addNewEmployee(...) { Employee e = new Employee(...); Department d = new Depart...
Example – Managing Relationship public int addNewEmployee(...) { Employee e = new Employee(...); Department d = new Depart...
Navigating Relationships <ul><li>Data fetching strategy </li></ul><ul><li>EAGER – immediate </li></ul><ul><li>LAZY – loade...
Lazy loading and JPA <ul><li>Default FetchType is LAZY for 1:m and m:n relationships </li></ul><ul><ul><li>benefits large ...
Lazy loading and JPA <ul><li>Relationship can be Loaded Eagerly </li></ul><ul><ul><li>But if you have several  related rel...
Lazy loading and JPA <ul><li>Capture generated SQL </li></ul><ul><ul><li>persistence.xml file: <property name=&quot; topli...
Navigating Relationships <ul><li>Accessing a  LAZY relationship  from a  detached  entity </li></ul><ul><ul><li>If not loa...
Navigating Relationships <ul><li>Data fetching strategy </li></ul><ul><li>Cascade specifies operations on relationships </...
Using Cascade @Entity public class Employee { @Id private int id; private String firstName; private String lastName; @Many...
Agenda <ul><li>Entity Manager </li></ul><ul><li>Persistence Context </li></ul><ul><li>Entities </li></ul><ul><li>Schema an...
Database design Basic foundation of performance <ul><li>Smaller tables use less disk, less memory, can give better perform...
Normalization <ul><li>Normalization Eliminates redundant data </li></ul><ul><ul><li>updates are usually   faster . </li></...
Mapping Inheritance Hierarchies Employee --------------------------- int id  String firstName String lastName  Department ...
Single Table Per Class <ul><li>Benefits </li></ul><ul><li>Simple </li></ul><ul><li>No joins   required </li></ul><ul><ul><...
Joined Subclass <ul><li>Benefits </li></ul><ul><li>Normalized  database </li></ul><ul><ul><li>Better for storage </li></ul...
Table Per Class <ul><li>Benefits </li></ul><ul><li>No need for joins to read  entities of same type </li></ul><ul><ul><li>...
vertical partitioning <ul><li>limit number of columns per table </li></ul><ul><li>split large, infrequently used columns i...
Vertical partitioning <ul><ul><li>split large, infrequently used columns into a separate  table </li></ul></ul>@Entity pub...
Scalability: Sharding - Application Partitioning <ul><ul><li>Sharding =Horizontal partitioning </li></ul></ul><ul><ul><ul>...
Know what SQL is executed  <ul><li>Capture generated SQL: </li></ul><ul><ul><li>persistence.xml file: </li></ul></ul><ul><...
MySQL Query  Analyser <ul><li>Find and fix problem SQL: </li></ul><ul><li>how long a query took </li></ul><ul><li>results ...
Agenda <ul><li>Entities </li></ul><ul><li>Entity Manager </li></ul><ul><li>Persistence Context </li></ul><ul><li>Queries <...
Query Types – 1  <ul><li>Named query </li></ul><ul><ul><li>Like  findByXXXX()  from  EntityBeans </li></ul></ul><ul><ul><l...
Query Types – 2  <ul><li>Native query </li></ul><ul><ul><li>Leverage the native database querying facilities </li></ul></u...
Flush Mode  <ul><li>Controls whether the state of managed entities are synchronized before a query </li></ul><ul><li>Types...
Agenda <ul><li>Entities </li></ul><ul><li>Entity Manager </li></ul><ul><li>Persistence Context </li></ul><ul><li>Queries <...
Transactions <ul><li>Do not perform expensive and unnecessary operations that are not part of a transaction </li></ul><ul>...
Carol McDonald Java Architect
Upcoming SlideShare
Loading in …5
×

Jpa buenas practicas

2,431 views

Published on

Jpa buenas practicas

Published in: Technology
0 Comments
8 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
2,431
On SlideShare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
0
Comments
0
Likes
8
Embeds 0
No embeds

No notes for slide
  • To obtain an container managed EntityManager instance, inject the entity manager into the application component: @PersistenceContext EntityManager em; you don&apos;t need any cm lifecycle methods With a container-managed entity manager, an EntityManager instance&apos;s persistence context is automatically propagated by the container to all application components that use the EntityManager instance within a single Java Transaction Architecture (JTA) transaction. JTA transactions usually involve calls across application components. To complete a JTA transaction, these components usually need access to a single persistence context. This occurs when an EntityManager is injected into the application components via the javax.persistence.PersistenceContext annotation. The persistence context is automatically propagated with the current JTA transaction, and EntityManager references that are mapped to the same persistence unit provide access to the persistence context within that transaction. By automatically propagating the persistence context, application components don&apos;t need to pass references to EntityManager instances to each other in order to make changes within a single transaction. The Java EE container manages the lifecycle of container-managed entity managers.
  • To obtain an container managed EntityManager instance, inject the entity manager into the application component: @PersistenceContext EntityManager em; you don&apos;t need any cm lifecycle methods With a container-managed entity manager, an EntityManager instance&apos;s persistence context is automatically propagated by the container to all application components that use the EntityManager instance within a single Java Transaction Architecture (JTA) transaction. JTA transactions usually involve calls across application components. To complete a JTA transaction, these components usually need access to a single persistence context. This occurs when an EntityManager is injected into the application components via the javax.persistence.PersistenceContext annotation. The persistence context is automatically propagated with the current JTA transaction, and EntityManager references that are mapped to the same persistence unit provide access to the persistence context within that transaction. By automatically propagating the persistence context, application components don&apos;t need to pass references to EntityManager instances to each other in order to make changes within a single transaction. The Java EE container manages the lifecycle of container-managed entity managers.
  • Here is how you could do this with a stateless session bean. We inject reference to a container managed EntityManager using the persistence context annotation. We create a new order and the entity has the state of new. We call persist, making this a managed entity. because it is a stateless session bean it is by default using container managed transactions , when this transaction commits , the order is made persistent in the database. When we return the serialiable orderline entity it is a detached entity
  • Here is how you could do this with a stateless session bean. We inject reference to a container managed EntityManager using the persistence context annotation. We create a new order and the entity has the state of new. We call persist, making this a managed entity. because it is a stateless session bean it is by default using container managed transactions , when this transaction commits , the order is made persistent in the database. When we return the serialiable orderline entity it is a detached entity
  • In a transaction-scoped container managed entity manager (common case in a Java EE environment), the JTA transaction propagation is the same as the persistence context resource propagation. In other words, container-managed transaction-scoped entity managers retrieved within a given JTA transaction all share the same persistence context.
  • In a transaction-scoped container managed entity manager (common case in a Java EE environment), the JTA transaction propagation is the same as the persistence context resource propagation. In other words, container-managed transaction-scoped entity managers retrieved within a given JTA transaction all share the same persistence context.
  • Here is how you could do this with a stateless session bean. We inject reference to a container managed EntityManager using the persistence context annotation. We create a new order and the entity has the state of new. We call persist, making this a managed entity. because it is a stateless session bean it is by default using container managed transactions , when this transaction commits , the order is made persistent in the database. When we return the serialiable orderline entity it is a detached entity
  • A persistence context can be either transaction scoped or extended scope. A transaction scope pc is one that is bound to a jta it starts and ends at transaction boundaries. At the end of the transaction the entities become detached. An extended pc spans multiple transactios, and it exists from the time the em is created until it is closed. An extended pc can be useful in web apps when you have conversations that span multiple requests. So the em can remain open between requests and you can close the em when done. Components like Stateful session can hold references to managed instances. It avoids flushing the database between requests and then re-finding entities so in some cases can improve performance. The type of pc is defined when you create the entity manager Persistence contexts may live as long as a transaction and be closed when a transaction completes. This is called a transaction-scoped persistence context . When the transaction completes, the transaction-scoped persistence context will be destroyed and all managed entity object instances will become detached. Persistence contexts may also be configured to live longer than a transaction. This is called an extended persistence context . Entity object instances that are attached to an extended context remain managed even after a transaction is complete. This feature is extremely useful in situations where you want to have a conversation with your database but not keep a long-running transaction
  • In this example the sb looks up an order, adds a line items. The stateless session bean does the workflow with a lookup and merge in each operation as needed, whereas the stateful session bean does the same by caching the references.
  • Optimistic locking permits all users to read and attempt to update the same data, concurrently. It does not prevent others from changing the same data, but it does guarantee the database will not be updated based on stale data. Pessimistic locking is the most restrictive form of locking but guarantees no changes are performed on the data during your transaction. The database physically locks the row upon a select (SELECT . . . FOR UPDATE [NOWAIT]) and prevents others from altering that row. This reassurance comes at a cost as pessimistic locks cannot be held across transactions and only one user can access the underlying data. Pessimistic locking should be used carefully as it limits concurrent access to the data and may cause deadlocks.
  • The spec mendates that a persistence application operates at “read committed” level that is no dirty reads (or uncommitted data) is read.
  • The spec mendates that a persistence application operates at “read committed” level that is no dirty reads (or uncommitted data) is read.
  • The spec mendates that a persistence application operates at “read committed” level that is no dirty reads (or uncommitted data) is read.
  • An application might want to share entity state across various persistence contexts This is the domain of second level (L2) cache If caching is enabled, entities not found in persistence context, will be loaded from L2 cache, if found JPA does not specify support of a second level cache However, most of the persistence providers provide in-built or integrated support for second level cache(s) Basic support for second level cache in GlassFish-TopLink Essentials is turned on by default No extra configuration is needed
  • The spec mendates that a persistence application operates at “read committed” level that is no dirty reads (or uncommitted data) is read.
  • Lazy loading and JPA With JPA many-to-one and many-to-many relationships lazy load by default , meaning they will be loaded when the entity in the relationship is accessed. Lazy loading is usually good, but if you need to access all of the &amp;quot;many&amp;quot; objects in a relationship, it will cause n+1 selects where n is the number of &amp;quot;many&amp;quot; objects. You can change the relationship to be loaded eagerly as follows : public class Employee{ @OneToMany(mappedBy = &amp;quot;employee&amp;quot;, fetch = FetchType.EAGER) private Collection&lt;Address&gt; addresses; ..... } However you should be careful with eager loading which could cause SELECT statements that fetch too much data. It can cause a Cartesian product if you eagerly load entities with several related collections. If you want to temporarily override the LAZY fetch type, you could use Fetch Join. For example this query would eagerly load the employee addresses: @NamedQueries({ @NamedQuery(name=&amp;quot;getItEarly&amp;quot;, query=&amp;quot;SELECT e FROM Employee e JOIN FETCH e.addresses&amp;quot;)}) public class Employee{ ..... }
  • Lazy loading and JPA With JPA many-to-one and many-to-many relationships lazy load by default , meaning they will be loaded when the entity in the relationship is accessed. Lazy loading is usually good, but if you need to access all of the &amp;quot;many&amp;quot; objects in a relationship, it will cause n+1 selects where n is the number of &amp;quot;many&amp;quot; objects. You can change the relationship to be loaded eagerly as follows : However you should be careful with eager loading which could cause SELECT statements that fetch too much data. It can cause a Cartesian product if you eagerly load entities with several related collections. If you want to temporarily override the LAZY fetch type, you could use Fetch Join. For example this query would eagerly load the employee addresses: Cartiesian product is the set of all possible ordered pairs
  • Lazy loading and JPA With JPA many-to-one and many-to-many relationships lazy load by default , meaning they will be loaded when the entity in the relationship is accessed. Lazy loading is usually good, but if you need to access all of the &amp;quot;many&amp;quot; objects in a relationship, it will cause n+1 selects where n is the number of &amp;quot;many&amp;quot; objects. You can change the relationship to be loaded eagerly as follows : public class Employee{ @OneToMany(mappedBy = &amp;quot;employee&amp;quot;, fetch = FetchType.EAGER) private Collection&lt;Address&gt; addresses; ..... } However you should be careful with eager loading which could cause SELECT statements that fetch too much data. It can cause a Cartesian product if you eagerly load entities with several related collections. If you want to temporarily override the LAZY fetch type, you could use Fetch Join. For example this query would eagerly load the employee addresses: @NamedQueries({ @NamedQuery(name=&amp;quot;getItEarly&amp;quot;, query=&amp;quot;SELECT e FROM Employee e JOIN FETCH e.addresses&amp;quot;)}) public class Employee{ ..... }
  • In a normalized database, each fact is represented once and only once. Conversely, in a denormalized database, information is duplicated, or stored in multiple places. People who ask for help with performance issues are frequently advised to normalize their schemas, especially if the workload is write-heavy. This is often good advice. It works well for the following reasons: Normalized updates are usually faster than denormalized updates. When the data is well normalized, there&apos;s little or no duplicated data, so there&apos;s less data to change. Normalized tables are usually smaller, so they fit better in memory and perform better. The lack of redundant data means there&apos;s less need for DISTINCT or GROUP BY queries when retrieving lists of values. Consider the preceding example: it&apos;s impossible to get a distinct list of departments from the denormalized schema without DISTINCT or GROUP BY, but if DEPARTMENT is a separate table, it&apos;s a trivial query. The drawbacks of a normalized schema usually have to do with retrieval. Any nontrivial query on a well-normalized schema will probably require at least one join, and perhaps several. This is not only expensive, but it can make some indexing strategies impossible. For example, normalizing may place columns in different tables that would benefit from belonging to the same index.
  • single table means that all of those classes are being stored in the same table and all we need is a a discriminator column in that table . So the disc column tells what type. This leads to some wastage of space, if you have a rate then you don&apos;t have a salary . But it does make for quick querying because you can find through a single table scan all of the objects of a type.
  • joined hierarchy , great for storage a little more expensive for querying
  • finally table per class says that every concrete class gets its own table and it will repeat all the inherited state in that table.
  • An example of vertical partitioning might be a table that contains a number of very wide text or BLOB columns that aren&apos;t addressed often being broken into two tables that has the most referenced columns in one table and the seldom-referenced text or BLOB data in another. • limit number of columns per table • split large, infrequently used columns into a separate one-to-one table By removing the VARCHAR column from the design, you actually get a reduction in query response time. Beyond partitioning, this speaks to the effect wide tables can have on queries and why you should always ensure that all columns defined to a table are actually needed.
  • You need to understand the SQL queries your application makes and evaluate their performance To Know how your query is executed by MySQL, you can harness the MySQL slow query log and use EXPLAIN. Basically you want to make your queries access less data: is your application retrieving more data than it needs, are queries accessing too many rows or columns? is MySQL analyzing more rows than it needs? Indexes are a good way to reduce data access. When you precede a SELECT statement with the keyword EXPLAIN, MySQL displays information from the optimizer about the query execution plan. That is, MySQL explains how it would process the SELECT, including information about how tables are joined and in which order. With the help of EXPLAIN, you can see where you should add indexes to tables to get a faster SELECT that uses indexes to find rows. You can also use EXPLAIN to check whether the optimizer joins the tables in an optimal order. Developers should run EXPLAIN on all SELECT statements that their code is executing against the database. This ensures that missing indexes are picked up early in the development process and gives developers insight into how the MySQL optimizer has chosen to execute the query.
  • MySQL Query Analyzer The MySQL Query Analyzer is designed to save time and effort in finding and fixing problem queries. It gives DBAs a convenient window, with instant updates and easy-to-read graphics, The analyzer can do simple things such as tell you how long a recent query took and how the optimizer handled it (the results of EXPLAIN statements). But it can also give historical information such as how the current runs of a query compare to earlier runs. Most of all, the analyzer will speed up development and deployment because sites will use it in conjunction with performance testing and the emulation of user activity to find out where the choke points are in the application and how they can expect it to perform after deployment. The MySQL Query Analyzer saves time and effort in finding and fixing problem queries by providing: Aggregated view into query execution counts, run time, result sets across all MySQL servers with no dependence on MySQL logs or SHOW PROCESSLIST Sortable views by all monitored statisticsSearchable and sortable queries by query type, content, server, database, date/time, interval range, and &amp;quot;when first seen&amp;quot;Historical and real-time analysis of all queries across all serversDrill downs into sampled query execution statistics, fully qualified with variable substitutions, and EXPLAIN results The new MySQL Query Analyzer was added into the MySQL Enterprise Monitor and it packs a lot of punch for those wanting to ensure their systems are free of bad running SQL code. let me tell you the two things I particularly like about it from a DBA perspective: 1. It&apos;s Global: If you have a number of servers, you&apos;ll love what Query Analyzer does for you. Even Oracle and other DB vendors only provide single-server views of bad SQL that runs across their servers. Query Analyzer bubbles to the top the worst SQL across all your servers – which is a much more efficient way to work. No more wondering what servers you need to spend your time on or which have the worst code. 2. It&apos;s Smart: Believe it or not, sometimes it&apos;s not slow-running SQL that kills your system – it&apos;s SQL that executes way more times than you think it is. You really couldn&apos;t see this well before Query Analyzer, but now you can. One customer already shaved double-digits off their response time by finding queries that were running more much than they should have been. And that&apos;s just one area Query Analyzer looks at; there&apos;s much more intelligence there too, along with other stats you can&apos;t get from the general server utilities.
  • Jpa buenas practicas

    1. 1. Java Persistence API: Best Practices Carol McDonald Java Architect
    2. 2. Agenda <ul><li>Entity Manager </li></ul><ul><li>Persistence Context </li></ul><ul><li>Entities </li></ul><ul><li>Schema & Queries </li></ul><ul><li>Transaction </li></ul>
    3. 3. Persistence Context EntityManager persist() remove() refresh() merge() find() createQuery() createNamedQuery() contains() flush() EntityManager API for managing entities <ul><ul><ul><li>set of entities managed by </li></ul></ul></ul><ul><ul><ul><li>Entity Manager </li></ul></ul></ul>Servlets EJBs Java app
    4. 4. Catalog Java EE Application DB Registration Application Managed Bean JSF Components Session Bean Entity Class Catalog Item ManagedBean
    5. 5. EJB EntityManager Example @Stateless public class Catalog implements CatalogService { @PersistenceContext(unitName=”PetCatalogPu”) EntityManager em; @TransactionAttribute(NOT_SUPPORTED) public List<Item> getItems (int firstItem , int batchSize ) { Query q = em . createQuery (&quot; select i from Item as i &quot;); q. setMaxResults ( batchSize ); q. setFirstResult ( firstItem ); List<Item> items= q.getResultList(); return items; } }
    6. 6. Catalog Spring JPA Application DB Registration Application Managed Bean JSF Components Spring Bean Entity Class Catalog Item ItemController Spring Framework
    7. 7. Spring with JPA @Repository @Transactional public class CatalogDAO implements CatalogService { @PersistenceContext (unitName=&quot;PetCatalogPu&quot;) private EntityManager em; @Transactional(readOnly=true) 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; } Component Stereotype Spring transactions use aop
    8. 8. Container vs Application Managed <ul><li>Container managed entity managers (EJB, Spring Bean, Seam component) </li></ul><ul><li>Injected into application </li></ul><ul><li>Automatically closed </li></ul><ul><li>JTA transaction – propagated </li></ul><ul><li>Application managed entity managers </li></ul><ul><ul><li>Used outside of the JavaEE 5 platform </li></ul></ul><ul><ul><li>Need to be explicitly created </li></ul></ul><ul><ul><ul><li>Persistence.createEntityManagerFactory() </li></ul></ul></ul><ul><ul><li>RESOURCE_LOCAL transaction – not propagated </li></ul></ul><ul><ul><li>Need to explicitly close entity manager </li></ul></ul>
    9. 9. Agenda <ul><li>Entity Manager </li></ul><ul><li>Persistence Context </li></ul><ul><li>Entities </li></ul><ul><li>Queries </li></ul><ul><li>Transaction </li></ul>
    10. 10. Persistence Context EntityManager persist() remove() refresh() merge() find() createQuery() createNamedQuery() contains() flush() Persistence Context <ul><ul><ul><li>set of entities managed by </li></ul></ul></ul><ul><ul><ul><li>Entity Manager </li></ul></ul></ul><ul><li>Persistence context acts as a first level cache for entities </li></ul><ul><li>Two types of persistence context </li></ul><ul><ul><li>Transaction scoped </li></ul></ul><ul><ul><li>Extended scoped persistence context </li></ul></ul>
    11. 11. Level1 and Level2 caches The terms “Java Virtual Machine” and “JVM” mean a Virtual Machine for the Java ™ Platform. Source:http://weblogs.java.net/blog/guruwons/archive/2006/09/understanding_t.html Persistence Context is a Level 1 cache Transaction Transaction Transaction Persistence Context (EntityManager) Persistence Context (EntityManager) Persistence Context (EntityManager) L2 Cache (Shared Cache) Entity managers for a specific PersistenceUnit on a given Java Virtual Machine (JVM ™ )
    12. 12. Persistence Context <ul><ul><ul><li>Transaction commit </li></ul></ul></ul>new() persist() Updates remove() Merge() find() PC ends Entity Lifecycle Guaranteed Scope of Object Identity only one manage entity in PC represents a row
    13. 13. Entity Lifecycle Illustrated – The Code @Stateless public ShoppingCartBean implements ShoppingCart { @PersistenceContext EntityManager entityManager; public OrderLine createOrderLine(Product product , Order order) { O rderLine orderLine = new OrderLine(order, product); entityManager.persist(orderLine); return (orderLine); } } New entity Managed entity Detached entity Persistence context
    14. 14. Scope of Identity @Stateless public ShoppingCartBean implements ShoppingCart { @PersistenceContext EntityManager entityManager; public OrderLine createOrderLine( Product product,Order order) { O rderLine orderLine = new OrderLine(order, product); entityManager.persist(orderLine); OrderLine orderLine2 = entityManager.find (OrderLine, orderLine.getId()) ); ( orderLine == orderLine2 ) // TRUE return (orderLine); } } Persistence context Multiple retrievals of the same object return references to the same object instance
    15. 15. Persistence Context <ul><li>Two types of persistence context </li></ul><ul><li>Transaction scoped </li></ul><ul><ul><li>Used in stateless components </li></ul></ul><ul><ul><li>Typically begins/ends at request entry/exit points respectively </li></ul></ul><ul><li>Extended scoped persistence context </li></ul>
    16. 16. Persistence Context Propagation <ul><li>@Stateless public class ShoppingCartBean implements ShoppingCart { </li></ul><ul><li>@EJB InventoryService inv ; </li></ul><ul><li>@EJB OrderService ord ; </li></ul><ul><ul><li>public void checkout (Item i, Product p) { </li></ul></ul><ul><ul><ul><li>inv.createOrder (item); </li></ul></ul></ul><ul><ul><ul><li>ord.updateInventory (Product p) </li></ul></ul></ul><ul><ul><li>} </li></ul></ul><ul><li>} </li></ul>Persistence context
    17. 17. Persistence Context Propagation <ul><li>@Stateless public class OrderServiceBean implements OrderService { </li></ul><ul><li>@PersistenceContext EntityManager em1; </li></ul><ul><ul><li>public void createOrder (Item item) { </li></ul></ul><ul><ul><ul><li>em1.persist (new Order(item)); </li></ul></ul></ul><ul><ul><li>} </li></ul></ul><ul><li>} </li></ul><ul><li>@Stateless public class InventoryServiceBean implements InventoryService { </li></ul><ul><li>@PersistenceContext EntityManager em2; </li></ul><ul><ul><li>public void updateInventory (Product p) { </li></ul></ul><ul><ul><ul><li>Product product = em2.merge (p); </li></ul></ul></ul><ul><ul><ul><li>. . . </li></ul></ul></ul><ul><ul><li>} </li></ul></ul><ul><li>} </li></ul>
    18. 18. Declarative Transaction Management Example TX_REQUIRED TX_REQUIRED TX_REQUIRED PC PC PC Shopping Cart Inventory Service Order Service Check Out 1. Update Inventory New Persistence Context Persistence Context Propagated Transaction Attributes 2. Create Order
    19. 19. AuditServiceBean @Stateless public class AuditServiceBean implements AuditService { @PersistenceContext private EntityManager em; @TransactionAttribute(REQUIRES_NEW) public void logTransaction2(int id, String action) { LogRecord lr = new LogRecord(id, action); em.persist(lr); } NEW PC !
    20. 20. Declarative Transaction Management Example 2 REQUIRED REQUIRED REQUIRES_NEW PC PC PC2 Shopping Cart Inventory Service Audit Service Check Out 1. Update Inventory New Persistence Context Persistence Context Propagated Transaction Attributes 2. log transaction NEW PC !
    21. 21. Persistence Provider PC Transaction Features <ul><li>Attribute-level change tracking </li></ul><ul><li>Only the minimal updates are sent to the database </li></ul><ul><li>Orders INSERT, UPDATE and DELETE statements </li></ul><ul><li>Minimizes database interactions </li></ul><ul><li>EntityManager flush SQL prior to commit </li></ul>
    22. 22. Persistence Context Conversation with detached entity Persistence Context merge() transaction-scoped persistence context request response request response Conversation transaction-scoped persistence context
    23. 23. Conversation with detached entity @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 orderLine2 = entityManager.merge (orderLine) ); return orderLine2 ; } } Managed entity Detached entity Managed entity
    24. 24. Types of Persistence Context <ul><li>Persistence Context </li></ul><ul><ul><li>lifetime maybe transaction-scoped or extended </li></ul></ul><ul><li>Transaction-scoped persistence context </li></ul><ul><li>Extended persistence context </li></ul><ul><ul><li>spans multiple transactions </li></ul></ul>
    25. 25. Persistence Context Conversation with Exented Persistence Context request response request response Conversation extended persistence context
    26. 26. Extended Persistence Context @Stateful public class OrderMgr { //Specify that we want an EXTENDED @PersistenceContext (type=PersistenceContextType.EXTENDED) EntityManager em ; //Cached order private Order order ; //create and cache order public void createOrder(String itemId) { //order remains managed for the lifetime of the bean Order order = new Order(cust); em.persist( order ); } public void addLineItem (OrderLineItem li){ order. lineItems.add(li); } Managed entity Managed entity
    27. 27. Extended Persistence Context @Stateful public class DeptMgr { @PersistenceContext (type=PersistenceContextType.EXTENDED) EntityManager em ; private Department dept; @TransactionAttribute(NOT_SUPPORTED) public void getDepartment(int deptId) { dept = em.find(Department.class,deptId); } @TransactionAttribute(NOT_SUPPORTED) public void addEmployee (int empId){ emp = em.find(Employee.class,empId); dept.getEmployees().add(emp); emp.setDepartment(dept); } @Remove @TransactionAttribute(REQUIRES_NEW) public void endUpdate(int deptId) { dept = em.find(Department.class,deptId); }
    28. 28. Persistence Context- Transactional vs. Extended @Stateless public class OrderMgr implements OrderService { @PersistenceContext 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 OrderMgr implements OrderService { @PersistenceContext(type = PersistenceContextType. EXTENDED )) EntityManager em; // Order is cached Order order public void addLineItem (OrderLineItem li){ // No em.find invoked for the order object order.lineItems.add(li); } look up the order No em.find invoked Managed entity
    29. 29. Persistence Context Micro Benchmark <ul><li>Micro benchmark with lots of lookups </li></ul><ul><li>Persistence context is caching entities </li></ul>Source: Internal benchmarks
    30. 30. SEAM Conversations <ul><ul><li>@Name (&quot; shopper &quot;)‏ </li></ul></ul><ul><ul><li>@Scope ( CONVERSATION )‏ </li></ul></ul><ul><ul><li>public class BookingManager { </li></ul></ul><ul><ul><ul><li>@In EntityManager entityManager ; </li></ul></ul></ul><ul><ul><ul><li>private Booking booking ; </li></ul></ul></ul><ul><ul><ul><li>@Begin public void selectHotel(Hotel selectedHotel ){ </li></ul></ul></ul><ul><ul><ul><li>hotel = em.merge( selectedHotel ); </li></ul></ul></ul><ul><ul><ul><li>} </li></ul></ul></ul><ul><ul><ul><li>@End public void confirm() { </li></ul></ul></ul><ul><ul><ul><li>em.persist( booking ); </li></ul></ul></ul><ul><ul><ul><li>} </li></ul></ul></ul><ul><ul><li>} </li></ul></ul>SEAM injected SEAM conversation
    31. 31. Concurrency and Persistence Context Object Identity only one manage entity in PC represents a row User 2 transaction User 1 transaction Persistence Context 1 Entity Manager Persistence Context 2 Entity Manager Data source same entity
    32. 32. Optimistic versus Pessimistic Concurrency <ul><li>Optimistic Concurrency </li></ul><ul><ul><li>Pros—No database locks held </li></ul></ul><ul><ul><li>Cons—Requires a version attribute in schema </li></ul></ul><ul><ul><ul><li>user or app must refresh and retry failed updates </li></ul></ul></ul><ul><ul><li>Suitable when application has few parallel updates </li></ul></ul><ul><li>Pessimistic Concurrency </li></ul><ul><ul><li>Lock the row when data is read in </li></ul></ul><ul><ul><ul><li>database locks the row upon a select </li></ul></ul></ul><ul><ul><ul><li>(SELECT . . . FOR UPDATE [NOWAIT]) </li></ul></ul></ul><ul><ul><li>Pros—Simpler application code </li></ul></ul><ul><ul><li>Cons—Database locks </li></ul></ul><ul><ul><ul><li>limits concurrent access to the data = scalability </li></ul></ul></ul><ul><ul><ul><li>May cause deadlocks </li></ul></ul></ul><ul><ul><ul><li>Not in JPA 1.0 (vendor specific), supported in JPA 2.0 </li></ul></ul></ul><ul><ul><li>Suitable when application has many parallel updates </li></ul></ul>
    33. 33. Preventing Parallel Updates <ul><li>use @Version for optimistic locking </li></ul><ul><li>Used by persistence manager , Results in following SQL “ UPDATE Employee SET ..., version = version + 1 WHERE id = ? AND version = readVersion ” </li></ul><ul><li>Version Updated when transaction commits, merged or acquiring a write lock </li></ul><ul><li>OptimisticLockException if mismatch </li></ul><ul><li>Not used by the application! </li></ul>public class Employee { @ID int id; @Version int version; ... <ul><ul><ul><li>Can be int , Integer , short , Short , long , Long , Timestamp </li></ul></ul></ul>
    34. 34. Preventing Parallel Updates – 1 <ul><li>tx1.begin(); //Joe's employee id is 5 //e1.version == 1 e1 = findPartTimeEmp(5); //Joe's current rate is $9 e1.raise(2); tx1.commit(); //e1.version == 2 in db </li></ul><ul><li>//Joe's rate is $11 </li></ul><ul><li>tx2.begin(); //Joe's employee id is 5 //e1.version == 1 e1 = findPartTimeEmp(5); </li></ul><ul><li>/ /Joe's current rate is $9 if(e1.getRate() < 10) e1.raise(5); </li></ul><ul><li> //e1.version == 1 in db? tx2.commit(); //Joe's rate is $14 //OptimisticLockException </li></ul>Time
    35. 35. Preventing Stale Data JPA 1.0 <ul><li>Perform read or write locks on entities </li></ul><ul><li>Prevents non-repeatable reads in JPA </li></ul><ul><li>entityManager.lock( entity, READ); </li></ul><ul><ul><ul><li>perform a version check on entity before commit </li></ul></ul></ul><ul><ul><li>OptimisticLockException if mismatch </li></ul></ul><ul><li>entityManager.lock( entity, WRITE); </li></ul><ul><ul><ul><li>perform a version check on entity </li></ul></ul></ul><ul><ul><li>OptimisticLockException if mismatch </li></ul></ul><ul><ul><ul><li>and increment version before commit </li></ul></ul></ul>
    36. 36. Preventing Stale Data <ul><li>tx1.begin(); d1 = findDepartment(dId); //d1's original name is //”Engrg” d1 .setName(“MarketEngrg”); tx1.commit(); </li></ul><ul><li>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 </li></ul>Time
    37. 37. <ul><ul><li>Write lock prevents parallel updates </li></ul></ul><ul><li>tx1.begin(); d1 = findDepartment(dId); </li></ul><ul><li>//d1's original name is //”Engrg” d1 .setName(“MarketEngrg”); tx1.commit(); //tx rolls back </li></ul><ul><li>tx2.begin(); e1 = findEmp(eId); d1 = e1 .getDepartment(); em.lock(d1, WRITE); </li></ul><ul><li>//version++ for d1 em.flush(); if(d1's name is “Engrg”) e1 .raiseByTenPercent(); tx2.commit(); </li></ul>Preventing Parallel Updates – 2 Time
    38. 38. Bulk Updates <ul><li>Update directly against the database, can be Faster But </li></ul><ul><ul><li>By pass EntityManager </li></ul></ul><ul><ul><li>@Version will not be updated </li></ul></ul><ul><ul><li>Entities in PC not updated </li></ul></ul><ul><li>tx.begin(); int id = 5; //Joe's employee id is 5 e1 = findPartTimeEmp(id); //Joe's current rate is $9 //Double every employee's salary em.createQuery( “ Update Employee set rate = rate * 2 ”).executeUpdate(); //Joe's rate is still $9 in this persistence context if(e1.getRate() < 10) e1.raiseByFiveDollar(); tx.commit(); //Joe's salary will be $14 </li></ul>
    39. 39. JPA 2.0 Locks <ul><li>JPA1.0 only supported optimistic locking, JPA 2.0 also supports pessimistic locks </li></ul><ul><li>JPA 2.0 LockMode values : </li></ul><ul><ul><li>OPTIMISTIC (= READ) </li></ul></ul><ul><ul><li>OPTIMISTIC_FORCE_INCREMENT (= WRITE) </li></ul></ul><ul><ul><li>PESSIMISTIC </li></ul></ul><ul><ul><li>PESSIMISTIC_FORCE_INCREMENT </li></ul></ul><ul><li>Multiple places to specify lock </li></ul>database locks the row (SELECT . . . FOR UPDATE )
    40. 40. <ul><li>//Read then lock: </li></ul><ul><li>Account acct = em. find (Account.class, acctId); </li></ul><ul><li>// Decide to withdraw $100 so lock it for update </li></ul><ul><li>em.lock(acct, PESSIMISTIC); </li></ul><ul><li>int balance = acct.getBalance(); </li></ul><ul><li>acct.setBalance (balance - 100); </li></ul><ul><li>//Read and lock : </li></ul><ul><li>Account acct = em. find (Account.class, acctId, PESSIMISTIC ); </li></ul><ul><li>// Decide to withdraw $100 (already locked) </li></ul><ul><li>int balance = acct.getBalance(); </li></ul><ul><li>acct.setBalance (balance - 100); </li></ul>JPA 2.0 Locking Locks longer , could cause bottlenecks, deadlock Lock after read, risk stale , could cause OptimisticLock Exception
    41. 41. <ul><li>// read then lock and refresh </li></ul><ul><li>Account acct = em. find (Account.class, acctId); </li></ul><ul><li>// Decide to withdraw $100 - lock and refresh </li></ul><ul><li>em. refresh(acct, PESSIMISTIC); </li></ul><ul><li>int balance = acct.getBalance(); </li></ul><ul><li>acct. setBalance (balance - 100); </li></ul>JPA 2.0 Locking “ right” approach depends on requirements <ul><li>Trade-offs: </li></ul><ul><li>lock earlier : risk bad scalability, deadlock </li></ul><ul><li>Lock later : risk stale data for update, get optimistic lock exception </li></ul>
    42. 42. L2 cache shared across transactions and users Putting it all together User Session User Session User Session Persistence Context (EntityManager) Persistence Context (EntityManager) Persistence Context (EntityManager) L2 Cache (Shared Cache) Entity managers for a specific PersistenceUnit on a given Java Virtual Machine (JVM ™ ) (EntityManagerFactory)
    43. 43. Second-level Cache <ul><li>L2 Cache shares entity state across various persistence contexts </li></ul><ul><ul><li>If caching is enabled, entities not found in persistence context , will be loaded from L2 cache , if found </li></ul></ul><ul><li>Best for read-mostly classes </li></ul><ul><li>L2 Cache is Vendor specific </li></ul><ul><ul><li>Java Persistence API 1.0 does not specify L2 support </li></ul></ul><ul><ul><li>Java Persistence API 2.0 has basic cache operations </li></ul></ul><ul><ul><li>Most persistence providers-- Hibernate, EclipseLink, OpenJPA ... provide second-level cache(s) </li></ul></ul>
    44. 44. L2 Cache L2 Cache query that looks for a single object based on Id will go 1st to PC then to L2 cache, other queries go to database or query cache Shared entity User transaction 1 Persistence Context User transaction 2 Persistence Context Data source same entity not shared
    45. 45. L2 Caching <ul><li>Pros : </li></ul><ul><ul><li>avoids database access for already loaded entities </li></ul></ul><ul><ul><ul><li>faster for reading frequently accessed unmodified entities </li></ul></ul></ul><ul><li>Cons </li></ul><ul><ul><li>memory consumption for large amount of objects </li></ul></ul><ul><ul><li>Stale data for updated objects </li></ul></ul><ul><ul><li>Concurrency for write (optimistic lock exception, or pessimistic lock) </li></ul></ul><ul><ul><ul><li>Bad scalability for frequent or concurrently updated entities </li></ul></ul></ul>
    46. 46. L2 Caching <ul><li>Configure L2 caching for entities that are </li></ul><ul><ul><li>read often </li></ul></ul><ul><ul><li>modified infrequently </li></ul></ul><ul><ul><li>Not critical if stale </li></ul></ul><ul><li>protect any data that can be concurrently modified with a locking strategy </li></ul><ul><ul><li>Must handle optimistic lock failures on flush/commit </li></ul></ul><ul><ul><li>configure expiration, refresh policy to minimize lock failures </li></ul></ul><ul><li>Configure Query cache </li></ul><ul><ul><li>Useful for queries that are run frequently with the same parameters, for not modified tables </li></ul></ul>
    47. 47. JPA 2.0 Shared Cache API <ul><li>entity cache shared across persistence unit </li></ul><ul><ul><li>Accessible from EntityManagerFactory </li></ul></ul><ul><li>Supports only very basic cache operations </li></ul><ul><ul><li>Can be extended by vendors </li></ul></ul><ul><li>public class Cache { </li></ul><ul><ul><li>//checks if object is in IdentityMap </li></ul></ul><ul><ul><li>public boolean contains (Class class, Object pk); </li></ul></ul><ul><ul><li>// invalidates object in the IdentityMap </li></ul></ul><ul><ul><li>public void evict (Class class, Object pk); </li></ul></ul><ul><ul><li>public void evict (Class class ); // invalidates the class in the IdentityMap. </li></ul></ul><ul><ul><li>public void evictAll (); // Invalidates all classes in the IdentityMap </li></ul></ul><ul><li>} </li></ul>
    48. 48. EclipseLink Caching Architecture EclipseLink caches Entities in L2, Hibernate does not EntityManager EntityManager Factory Server L1 Cache PC Cache L2 Shared Cache Cache Coordination JMS (MDB) RMI CORBA IIOP
    49. 49. EclipseLink Extensions - L2 Caching <ul><li>Default : Entities read are L2 cached </li></ul><ul><li>Cache Configuration by Entity type or Persistence Unit </li></ul><ul><ul><li>You can disable L2 cache </li></ul></ul><ul><li>Configuration Parameters </li></ul><ul><ul><li>Cache isolation, type, size, expiration, coordination, invalidation,refreshing </li></ul></ul><ul><ul><li>Coordination (cluster-messaging) </li></ul></ul><ul><ul><ul><li>Messaging: JMS, RMI, RMI-IIOP, … </li></ul></ul></ul><ul><ul><ul><li>Mode: SYNC, SYNC+NEW, INVALIDATE, NONE </li></ul></ul></ul>
    50. 50. <ul><li>@Entity </li></ul><ul><li>@Table(name=&quot;EMPLOYEE&quot;) </li></ul><ul><li>@Cache ( </li></ul><ul><li>type=CacheType.WEAK, </li></ul><ul><li>isolated=false, </li></ul><ul><li>expiry=600000, </li></ul><ul><li>alwaysRefresh=true, </li></ul><ul><li>disableHits=true, </li></ul><ul><li>coordinationType=INVALIDATE_CHANGED_OBJECTS </li></ul><ul><li>) </li></ul><ul><li>public class Employee implements Serializable { </li></ul><ul><li>... </li></ul><ul><li>} </li></ul>EclipseLink Mapping Extensions Type= Full: objects never flushed unless deleted or evicted weak: object will be garbage collected if not referenced <ul><ul><li>@Cache </li></ul></ul><ul><ul><ul><li>type, size,isolated, expiry, refresh, cache usage, coordination </li></ul></ul></ul><ul><ul><ul><li>Cache usage and refresh query hints </li></ul></ul></ul>=true disables L2 cache
    51. 51. Hibernate L2 Cache <ul><li>Hibernate L2 cache is not configured by default </li></ul><ul><li>Hibernate L2 does not cache Entities. Hibernate caches Id and state </li></ul><ul><li>Hibernate L2 cache is pluggable </li></ul><ul><ul><li>EHCache, OSCache, SwarmCacheProvider (JVM) </li></ul></ul><ul><ul><li>JBoss TreeCache Cluster </li></ul></ul><ul><ul><li>Can plug in others like Terracotta </li></ul></ul>Cache Concurrency Strategy
    52. 52. Hibernate L2 Cache <ul><li><!-- optional configuration file parameter --> </li></ul><ul><li>net.sf.ehcache.configurationResourceName=/name_of_configuration_resource </li></ul><ul><li>@Entity </li></ul><ul><li>@Cache (usage = CacheConcurrencyStrategy . NONSTRICT_READ_WRITE ) </li></ul><ul><li>public Class Country { </li></ul><ul><li>private String name; </li></ul><ul><li>... </li></ul><ul><li>} </li></ul>not configured by default Cache Concurrency Strategy must be supported by cache provider
    53. 53. OpenJPA L2 Caching <ul><li>OpenJPA L2 caches object data and JPQL query results </li></ul><ul><li>Updated when data is loaded from database and after changes are successfully committed </li></ul><ul><li>For cluster caches are notified when changes are made </li></ul><ul><li>Can plug in implementations, such as Tangosol’s Coherence product </li></ul><ul><li>several cache eviction strategies: </li></ul><ul><ul><li>Time-to-live settings for cache instances </li></ul></ul><ul><ul><ul><li>@Entity @DataCache(timeout=5000) </li></ul></ul></ul><ul><ul><ul><li>public class Person { ... } </li></ul></ul></ul>
    54. 54. Agenda <ul><li>Entity Manager </li></ul><ul><li>Persistence Context </li></ul><ul><li>Entities </li></ul><ul><li>Schema and Queries </li></ul><ul><li>Transaction </li></ul>
    55. 55. Maintaining Relationship <ul><li>Application bears the responsibility of maintaining relationship between objects </li></ul>deptA.getEmployees().add(e3); Department A Employee1 Employee2 Employee3 Employee1 Employee2 Employee3 Before After Inconsistent! Department B Department A Department B
    56. 56. Example – Domain Model @Entity public class Employee { @Id private int id; private String firstName; private String lastName; @ManyToOne(fetch=LAZY) private Department dept; ... } @Entity public class Department { @Id private int id; private String name; @OneToMany(mappedBy = &quot;dept&quot;, fetch=LAZY) private Collection<Employee> emps = new ...; ... }
    57. 57. Example – Managing Relationship public int addNewEmployee(...) { Employee e = new Employee(...); Department d = new Department(1, ...); e.setDepartment(d); //Reverse relationship is not set em.persist(e); em.persist(d); return d.getEmployees().size(); } INCORRECT
    58. 58. Example – Managing Relationship public int addNewEmployee(...) { Employee e = new Employee(...); Department d = new Department(1, ...); e.setDepartment(d); d.getEmployees().add(e); em.persist(e); em.persist(d); return d.getEmployees().size(); } CORRECT
    59. 59. Navigating Relationships <ul><li>Data fetching strategy </li></ul><ul><li>EAGER – immediate </li></ul><ul><li>LAZY – loaded only when needed </li></ul><ul><li>LAZY is good for large objects and/or with relationships with deep hierarchies </li></ul>
    60. 60. Lazy loading and JPA <ul><li>Default FetchType is LAZY for 1:m and m:n relationships </li></ul><ul><ul><li>benefits large objects and relationships with deep hierarchies </li></ul></ul><ul><li>However for use cases where data is needed can cause n+1 selects </li></ul><ul><li>LAZY – N + 1 problem: </li></ul>@Entity public class Department { @Id private int id; @OneToMany(mappedBy = &quot;dept&quot;) private Collection<Employee> emps ; ... } SELECT d.id, ... FROM Department d // 1 time SELECT e.id, ... FROM Employee e WHERE e.deptId = ? // N times
    61. 61. Lazy loading and JPA <ul><li>Relationship can be Loaded Eagerly </li></ul><ul><ul><li>But if you have several related relationships , could load too much ! </li></ul></ul><ul><li>OR </li></ul><ul><li>Temporarily override the LAZY fetch type, use Join Fetch in a query : </li></ul>@Entity public class Department { @Id private int id; @OneToMany(mappedBy = &quot;dept&quot;, fetch=EAGER ) private Collection<Employee> employees ; ... } @NamedQueries ({ @NamedQuery(name=&quot;getItEarly&quot;, query=&quot;SELECT d FROM Department d JOIN FETCH d.employees &quot;)}) public class Department { ..... } Can cause Cartesian product
    62. 62. Lazy loading and JPA <ul><li>Capture generated SQL </li></ul><ul><ul><li>persistence.xml file: <property name=&quot; toplink.logging.level &quot; value=&quot; FINE &quot;> </li></ul></ul><ul><li>Test run use cases and examine the SQL statements </li></ul><ul><ul><li>optimise the number of SQL statements executed! </li></ul></ul><ul><ul><li>only retrieve the data your application needs! </li></ul></ul><ul><li>Lazy load large (eg BLOB) attributes and relationships that are not used often </li></ul><ul><li>Override to Eagerly load in use cases where needed </li></ul>
    63. 63. Navigating Relationships <ul><li>Accessing a LAZY relationship from a detached entity </li></ul><ul><ul><li>If not loaded , Causes an exception </li></ul></ul><ul><li>Solutions: </li></ul><ul><ul><li>Use JOIN FETCH </li></ul></ul><ul><ul><li>Or Set Fetch type to EAGER </li></ul></ul><ul><ul><li>Or Access the collection before entity is detached: </li></ul></ul>d.getEmployees().size(); Persistence Context
    64. 64. Navigating Relationships <ul><li>Data fetching strategy </li></ul><ul><li>Cascade specifies operations on relationships </li></ul><ul><ul><li>ALL, PERSIST, MERGE, REMOVE, REFRESH </li></ul></ul><ul><ul><li>The default is do nothing </li></ul></ul><ul><li>Avoid MERGE, ALL with deep hierarchies </li></ul><ul><ul><li>If want to do it, limit the scope </li></ul></ul>
    65. 65. Using Cascade @Entity public class Employee { @Id private int id; private String firstName; private String lastName; @ManyToOne( cascade=ALL , fetch=LAZY) private Department dept; ... } @Entity public class Department { @Id private int id; private String name; @OneToMany(mappedBy = &quot;dept&quot; cascade=ALL , fetch=LAZY) private Collection<Employee> emps = new ...; @OneToMany private Collection<DepartmentCode> codes; ... } Employee Department DepartmentCode cascade=ALL X
    66. 66. Agenda <ul><li>Entity Manager </li></ul><ul><li>Persistence Context </li></ul><ul><li>Entities </li></ul><ul><li>Schema and Queries </li></ul><ul><li>Transaction </li></ul>
    67. 67. Database design Basic foundation of performance <ul><li>Smaller tables use less disk, less memory, can give better performance </li></ul><ul><ul><li>Use as small data types as possible </li></ul></ul><ul><ul><li>use as small primary key as possible </li></ul></ul><ul><ul><li>Vertical Partition: </li></ul></ul><ul><ul><ul><li>split large, infrequently used columns into a separate one-to-one table </li></ul></ul></ul><ul><li>Use good indexing </li></ul><ul><ul><li>Indexes Speed up Querys </li></ul></ul><ul><ul><li>Indexes slow down Updates </li></ul></ul><ul><ul><li>Index columns frequently used in Query Where clause </li></ul></ul>
    68. 68. Normalization <ul><li>Normalization Eliminates redundant data </li></ul><ul><ul><li>updates are usually faster . </li></ul></ul><ul><ul><ul><li>there's less data to change . </li></ul></ul></ul><ul><li>However Normalized database causes joins for queries </li></ul><ul><ul><li>Queries maybe slower </li></ul></ul><ul><ul><li>Normalize then maybe De-normalize frequently read columns and cache them </li></ul></ul>
    69. 69. Mapping Inheritance Hierarchies Employee --------------------------- int id String firstName String lastName Department dept PartTimeEmployee ------------------------ int rate FullTimeEmployee ----------------------- double salary
    70. 70. Single Table Per Class <ul><li>Benefits </li></ul><ul><li>Simple </li></ul><ul><li>No joins required </li></ul><ul><ul><li>can be fast for Queries </li></ul></ul><ul><li>Drawbacks </li></ul><ul><li>Not normalized </li></ul><ul><ul><li>Wastes space </li></ul></ul><ul><li>Requires columns corresponding to subclasses' state to be null </li></ul><ul><li>Table can have too many columns </li></ul><ul><ul><li>Larger tables = more data, can have negative affects on performance </li></ul></ul>@Inheritance(strategy=SINGLE_TABLE) EMPLOYEE --------------------------- ID Int PK, FIRSTNAME varchar(255), LASTNAME varchar(255), DEPT_ID int FK, RATE int NULL, SALARY double NULL, DISCRIM varchar(30)
    71. 71. Joined Subclass <ul><li>Benefits </li></ul><ul><li>Normalized database </li></ul><ul><ul><li>Better for storage </li></ul></ul><ul><li>Database view same as domain model </li></ul><ul><li>Easy to evolve domain model </li></ul><ul><li>Drawbacks </li></ul><ul><li>Queries cause joins </li></ul><ul><ul><li>Slower queries </li></ul></ul><ul><ul><li>Poor performance for deep hierarchies, polymorphic queries and relationships </li></ul></ul>@Inheritance(strategy=JOINED) ID int PK, FIRSTNAME varchar(255), LASTNAME varchar(255), DEPT_ID int FK, ID int PK FK, RATE int NULL ID int PK FK, SALARY double NULL EMPLOYEE PARTTIMEEMPLOYEE FULLTIMEEMPLOYEE
    72. 72. Table Per Class <ul><li>Benefits </li></ul><ul><li>No need for joins to read entities of same type </li></ul><ul><ul><li>Faster reads </li></ul></ul><ul><li>Drawbacks </li></ul><ul><li>Not normalized </li></ul><ul><ul><li>Wastes space </li></ul></ul><ul><li>Polymorphic queries cause union (all employees) </li></ul><ul><ul><li>Poor performance </li></ul></ul><ul><li>This strategy is not mandatory </li></ul>@Inheritance(strategy=TABLE_PER_CLASS) ID int PK, FIRSTNAME varchar(255), LASTNAME varchar(255), DEPT_ID int FK, SALARY double NULL ID int PK, FIRSTNAME varchar(255), LASTNAME varchar(255), DEPT_ID int FK, RATE int NULL PARTTIMEEMPLOYEE FULLTIMEEMPLOYEE
    73. 73. vertical partitioning <ul><li>limit number of columns per table </li></ul><ul><li>split large, infrequently used columns into a separate table </li></ul>CREATE TABLE Customer ( user_id INT NOT NULL AUTO_INCREMENT , email VARCHAR(80) NOT NULL , display_name VARCHAR(50) NOT NULL , password CHAR(41) NOT NULL , first_name VARCHAR(25) NOT NULL , last_name VARCHAR(25) NOT NULL , address VARCHAR(80) NOT NULL , city VARCHAR(30) NOT NULL , province CHAR(2) NOT NULL , postcode CHAR(7) NOT NULL , interests TEXT NULL , bio TEXT NULL , signature TEXT NULL , skills TEXT NULL , PRIMARY KEY (user_id) , UNIQUE INDEX (email) ) ENGINE= InnoDB ; <ul><ul><li>Less Frequently </li></ul></ul><ul><ul><li>referenced, </li></ul></ul><ul><ul><li>TEXT data </li></ul></ul><ul><ul><li>Frequently </li></ul></ul><ul><ul><li>referenced </li></ul></ul>CREATE TABLE Customer( user_id INT NOT NULL AUTO_INCREMENT , email VARCHAR(80) NOT NULL , display_name VARCHAR(50) NOT NULL , password CHAR(41) NOT NULL , PRIMARY KEY (user_id) , UNIQUE INDEX (email) ) ENGINE = InnoDB ; CREATE TABLE CustomerInfo ( user_id INT NOT NULL , first_name VARCHAR(25) NOT NULL , last_name VARCHAR(25) NOT NULL , address VARCHAR(80) NOT NULL , city VARCHAR(30) NOT NULL , province CHAR(2) NOT NULL , postcode CHAR(7) NOT NULL , interests TEXT NULL , bio TEXT NULL , signature TEXT NULL , skills TEXT NULL , PRIMARY KEY (user_id) , FULLTEXT KEY (interests, skills) ) ENGINE = MyISAM ;
    74. 74. Vertical partitioning <ul><ul><li>split large, infrequently used columns into a separate table </li></ul></ul>@Entity public class Customer { int userid; String email; String password; @OneToOne(fetch=LAZY) CustomerInfo info; } @Entity public class CustomerInfo { int userid; String name; String interests; @OneToOne(mappedBy= &quot;CustomerInfo&quot;) Customer customer; }
    75. 75. Scalability: Sharding - Application Partitioning <ul><ul><li>Sharding =Horizontal partitioning </li></ul></ul><ul><ul><ul><li>Split table by rows into partitions </li></ul></ul></ul>Cust_id 1-999 Cust_id 1000-1999 Cust_id 2000-2999 Sharding Architecture Web/App Servers
    76. 76. Know what SQL is executed <ul><li>Capture generated SQL: </li></ul><ul><ul><li>persistence.xml file: </li></ul></ul><ul><ul><li><property name=&quot;toplink.logging.level&quot; value=&quot;FINE&quot;> </li></ul></ul><ul><li>Find and fix problem SQL: </li></ul><ul><ul><li>Watch for slow Queries </li></ul></ul><ul><ul><ul><li>use the MySQL slow query log and use Explain </li></ul></ul></ul><ul><ul><ul><ul><li>Can reveal problems such as a missing Indexes </li></ul></ul></ul></ul><ul><ul><li>Watch for Queries that execute too often to load needed data </li></ul></ul><ul><ul><li>Watch for loading more data than needed </li></ul></ul>
    77. 77. MySQL Query Analyser <ul><li>Find and fix problem SQL: </li></ul><ul><li>how long a query took </li></ul><ul><li>results of EXPLAIN statements </li></ul><ul><li>Historical and real-time analysis </li></ul><ul><ul><li>query execution counts , run time </li></ul></ul>Its not just slow running queries that are a problem, Sometimes its SQL that executes a lot that kills your system
    78. 78. Agenda <ul><li>Entities </li></ul><ul><li>Entity Manager </li></ul><ul><li>Persistence Context </li></ul><ul><li>Queries </li></ul><ul><li>Transaction </li></ul>
    79. 79. Query Types – 1 <ul><li>Named query </li></ul><ul><ul><li>Like findByXXXX() from EntityBeans </li></ul></ul><ul><ul><li>Compiled by persistence engine </li></ul></ul><ul><ul><li>Created either with @NamedQuery or externalized in orm.xml </li></ul></ul><ul><li>Dynamic query </li></ul><ul><ul><li>Created dynamically by passing a query string to EntityManager </li></ul></ul><ul><ul><ul><li>Query query = em.createQuery(“select ...”); </li></ul></ul></ul><ul><ul><li>Beware of SQL injection , better to use with named parameters </li></ul></ul>q = em.createQuery(“select e from Employee e WHERE ” + “e.empId LIKE '” + id + “'” ); q = em.createQuery(“select e from Employee e WHERE ” + “e.empId LIKE ' :id '”); q. setParameter (“ id ”, id ); NOT GOOD GOOD
    80. 80. Query Types – 2 <ul><li>Native query </li></ul><ul><ul><li>Leverage the native database querying facilities </li></ul></ul><ul><ul><li>Not portable – ties queries to database </li></ul></ul>
    81. 81. Flush Mode <ul><li>Controls whether the state of managed entities are synchronized before a query </li></ul><ul><li>Types of flush mode </li></ul><ul><ul><li>AUTO – immediate, default </li></ul></ul><ul><ul><li>COMMIT – flush only when a transaction commits </li></ul></ul><ul><ul><li>NEVER – need to invoke EntityManger.flush() to flush </li></ul></ul>//Assume JTA transaction Order order = em.find(Order.class, orderNumber); em.persist(order); Query q = em.createNamedQuery(“findAllOrders”); q.setParameter(“id”, orderNumber); q.setFlushMode(FlushModeType.COMMIT) ; //Newly added order will NOT visible List list = q.getResultList();
    82. 82. Agenda <ul><li>Entities </li></ul><ul><li>Entity Manager </li></ul><ul><li>Persistence Context </li></ul><ul><li>Queries </li></ul><ul><li>Transaction </li></ul>
    83. 83. Transactions <ul><li>Do not perform expensive and unnecessary operations that are not part of a transaction </li></ul><ul><ul><li>Hurt performance </li></ul></ul><ul><ul><li>Eg. logging – disk write are expensive, resource contention on log </li></ul></ul><ul><li>Do not use transaction when browsing data </li></ul><ul><ul><li>@TransactionAttribute(NOT_SUPPORTED) </li></ul></ul>
    84. 84. Carol McDonald Java Architect

    ×