SlideShare a Scribd company logo
Second-­‐Level	
  Cache	
  	
  
in	
  JPA	
  Explained
Patrycja	
  Wegrzynowicz	
  
CTO,	
  Yonita,	
  Inc.	
  
JavaOne	
  2016
About	
  Me
• 15+	
  professional	
  experience	
  	
  
• SoPware	
  engineer,	
  architect,	
  head	
  of	
  
soPware	
  R&D	
  	
  
• Author	
  and	
  speaker	
  	
  
• JavaOne,	
  Devoxx,	
  JavaZone,	
  
TheServerSide	
  Java	
  Symposium,	
  Jazoon,	
  
OOPSLA,	
  ASE,	
  others	
  	
  
• Top	
  10	
  Women	
  in	
  Tech	
  2016	
  in	
  Poland	
  
• Founder	
  and	
  CTO	
  of	
  Yonita	
  
• Automated	
  detecXon	
  and	
  refactoring	
  of	
  
soPware	
  defects	
  
• Trainings	
  and	
  code	
  reviews	
  
• Security,	
  performance,	
  concurrency,	
  
databases	
  	
  
• TwiYer	
  @yonlabs	
  
About	
  Me
• 15+	
  professional	
  experience	
  	
  
• SoPware	
  engineer,	
  architect,	
  head	
  of	
  
soPware	
  R&D	
  	
  
• Author	
  and	
  speaker	
  	
  
• JavaOne,	
  Devoxx,	
  JavaZone,	
  
TheServerSide	
  Java	
  Symposium,	
  Jazoon,	
  
OOPSLA,	
  ASE,	
  others	
  	
  
• Top	
  10	
  Women	
  in	
  Tech	
  2016	
  in	
  Poland	
  
• Founder	
  and	
  CTO	
  of	
  Yonita	
  
• Automated	
  detecXon	
  and	
  refactoring	
  of	
  
soPware	
  defects	
  
• Trainings	
  and	
  code	
  reviews	
  
• Security,	
  performance,	
  concurrency,	
  
databases	
  	
  
• TwiYer	
  @yonlabs	
  
Agenda
• Why	
  cacheing	
  is	
  important?	
  
• 1st	
  Level	
  Cache	
  and	
  2nd	
  Level	
  Cache	
  
• JPA	
  configuraXon	
  parameters	
  for	
  cache	
  
• JPA	
  API	
  for	
  cache	
  
• Hibernate	
  2nd	
  Level	
  Cache	
  
• EclipseLink	
  2nd	
  Level	
  Cache	
  (a	
  bit)
Databases
Databases
Performance
Request	
  Handling
Performance:	
  Throughput
Performance:	
  ExecuXon	
  Time
Performance:	
  Latency
Performance:	
  Response	
  Time
Example
Employee	
  Entity
@Entity public class Employee {

@Id @GeneratedValue
private Long id;

private String firstName; 

private String lastName;

private BigDecimal salary;

@OneToOne @JoinColumn(name = "address_id")

private Address address;

@Temporal(TemporalType.DATE)

private Date startDate;

@Temporal(TemporalType.DATE)

private Date endDate; 

@ManyToOne @JoinColumn(name = "manager_id")

private Employee manager;
// …

}
14
Sum	
  of	
  Salaries	
  By	
  Country

Select	
  All	
  (1)
TypedQuery<Employee> query = em.createQuery(
"SELECT e FROM Employee e", Employee.class);
List<Employee> list = query.getResultList();

// calculate sum of salaries by country
// map: country->sum
Map<String, BigDecimal> results = new HashMap<>();

for (Employee e : list) {

String country = e.getAddress().getCountry();

BigDecimal total = results.get(country);

if (total == null) total = BigDecimal.ZERO;

total = total.add(e.getSalary());

results.put(country, total);

}

15
Sum	
  of	
  Salaries	
  by	
  Country

Select	
  Join	
  Fetch	
  (2)
TypedQuery<Employee> query = em.createQuery(
"SELECT e FROM Employee e
JOIN FETCH e.address", Employee.class);

List<Employee> list = query.getResultList();

// calculate sum of salaries by country
// map: country->sum
Map<String, BigDecimal> results = new HashMap<>();

for (Employee e : list) {

String country = e.getAddress().getCountry();

BigDecimal total = results.get(country);

if (total == null) total = BigDecimal.ZERO;

total = total.add(e.getSalary());

results.put(country, total);

}

16
Sum	
  of	
  Salaries	
  by	
  Country

Projection	
  (3)
Query query = em.createQuery(
"SELECT e.salary, e.address.country
FROM Employee e");

List<Object[]> list = (List<Object[]>) query.getResultList();

// calculate sum of salaries by country
// map: country->sum
Map<String, BigDecimal> results = new HashMap<>();

for (Object[] e : list) {

String country = (String) e[1];

BigDecimal total = results.get(country);

if (total == null) total = BigDecimal.ZERO;

total = total.add((BigDecimal) e[0]);

results.put(country, total);

}

17
Sum	
  of	
  Salaries	
  by	
  Country

Aggregation	
  JPQL	
  (4)
Query query = em.createQuery(
"SELECT SUM(e.salary), e.address.country
FROM Employee e
GROUP BY e.address.country");
List<Object[]> list = (List<Object[]>) query.getResultList();

// already calculated!

18
Comparison	
  1-­‐4	
  (Hibernate)	
  
100000	
  Employees,	
  Different	
  DB	
  LocaXons
Local DB
(ping: ~0.05ms)
North California
(ping: ~38ms)
EU Frankfurt
(ping: ~420ms)
(1) Select All
(N+1)
26756ms 2-3 hours ~1 day
(2) Select Join
Fetch
(3) Projection
(4) Aggregation
JPQL
Comparison	
  1-­‐4	
  
100000	
  Employees,	
  Different	
  DB	
  LocaXons
Local DB
(ping: ~0.05ms)
North California
(ping: ~38ms)
EU Frankfurt
(ping: ~420ms)
(1) Select All
(N+1)
26756ms 2-3 hours ~1 day
(2) Select Join
Fetch
4854ms 18027ms 25096ms
(3) Projection
(4) Aggregation
JPQL
Comparison	
  1-­‐4	
  
100000	
  Employees,	
  Different	
  DB	
  LocaXons
Local DB
(ping: ~0.05ms)
North California
(ping: ~38ms)
EU Frankfurt
(ping: ~420ms)
(1) Select All
(N+1)
26756ms 2-3 hours ~1 day
(2) Select Join
Fetch
4854ms 18027ms 25096ms
(3) Projection 653ms 2902ms 5006ms
(4) Aggregation
JPQL
Comparison	
  1-­‐4	
  
100000	
  Employees,	
  Different	
  DB	
  LocaXons
Local DB
(ping: ~0.05ms)
North California
(ping: ~38ms)
EU Frankfurt
(ping: ~420ms)
(1) Select All
(N+1)
26756ms 2-3 hours ~1 day
(2) Select Join
Fetch
4854ms 18027ms 25096ms
(3) Projection 653ms 2902ms 5006ms
(4) Aggregation
JPQL
182ms 353ms 1198ms
Performance	
  Tuning:	
  Data
• Get	
  your	
  data	
  in	
  bigger	
  chunks	
  	
  
• Many	
  small	
  queries	
  =>	
  many	
  round-­‐trips	
  =>	
  huge	
  extra	
  Xme	
  on	
  
transport	
  =>	
  high	
  latency	
  
• Move	
  your	
  data	
  closer	
  to	
  the	
  processing	
  place	
  
• Large	
  distance	
  to	
  data	
  =>	
  long	
  round-­‐trip	
  =>	
  high	
  latency	
  
• Don’t	
  ask	
  about	
  the	
  same	
  data	
  many	
  Xmes	
  
• Extra	
  processing	
  Xme	
  +	
  extra	
  transport	
  Xme
Cache
Cache	
  is	
  Everywhere
Web Cache
Application Cache
RDBMS Cache
DNS Cache
OS Files Cache
Second	
  Level	
  Cache	
  in	
  
JPA
JPA	
  Spec
• “Persistence	
  providers	
  are	
  not	
  required	
  to	
  support	
  a	
  
second-­‐level	
  cache.”	
  
• “Portable	
  applicaXons	
  should	
  not	
  rely	
  on	
  support	
  by	
  
persistence	
  providers	
  for	
  a	
  second-­‐level	
  cache.”
JPA	
  Providers	
  Poll
A. Hibernate	
  
B. EclipseLink	
  
C. OpenJPA	
  
D. DataNuclues	
  
E. Other
• Second	
  Level	
  Cache	
  
• Persistence	
  Unit	
  
• EnXtyManagerFactory	
  
• Thread-­‐safe,	
  shared	
  
• Available	
  for	
  many	
  en1ty	
  
managers	
  from	
  one	
  en1ty	
  
manager	
  factory	
  
• Provider	
  specific	
  support
JPA	
  Caches
• First	
  Level	
  Cache	
  
• Persistence	
  Context	
  
• EnXtyManager	
  
• Not	
  thread-­‐safe	
  
• Available	
  for	
  many	
  
transac1ons	
  on	
  one	
  en1ty	
  
manager	
  
• Always
EnXtyManagerFactory
EntityManagerFactory
creates
creates
creates2LC
EntityManager
1LC
EntityManager
1LC
EntityManager
1LC
Puzzle	
  #1
em.getTransaction().begin();

Employee employee = em.find(Employee.class, 2L);

employee.getAddress().size();
Employee another = em.find(Employee.class, 2L);

em.getTransaction().commit();

(A) No cache used
(B) First Level Cache Used
(C) Second Level Cache Used
(D) None of the above
30
Loading
EntityManager
Factory
2LC
EntityManager
1LC
load from 1LC load from 2LC
select from
database
NOT FOUND NOT FOUND
FOUND FOUND RESULT
FIND
Puzzle	
  #1
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();

Employee employee = em.find(Employee.class, 2L);

employee.getAddress().size();
Employee another = em.find(Employee.class, 2L);

em.getTransaction().commit();

(A) No cache used
(B) First Level Cache Used
(C) Second Level Cache Used
(D) None of the above
32
Puzzle	
  #1
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();

Employee employee = em.find(Employee.class, 2L);

employee.getAddress().size();
Employee another = em.find(Employee.class, 2L);

em.getTransaction().commit();

(A) No cache used
(B) First Level Cache Used
(C) Second Level Cache Used
(D) None of the above
33
Puzzle	
  #2
EntityManager em1 = emf.createEntityManager();
em1.getTransaction().begin();

Employee employee = em1.find(Employee.class, 2L);

employee.getAddress().size();
em1.getTransaction().commit();

EntityManager em2 = emf.createEntityManager();
em2.getTransaction().begin();

Employee employee = em2.find(Employee.class, 2L);

employee.getAddress().size();
em2.getTransaction().commit();

(A) No cache used
(B) First Level Cache used
(C) Second Level Cache used
(D) None of the above
34
Puzzle	
  #2
EntityManager em1 = emf.createEntityManager();
em1.getTransaction().begin();

Employee employee = em1.find(Employee.class, 2L);

employee.getAddress().size();
em1.getTransaction().commit();

EntityManager em2 = emf.createEntityManager();
em2.getTransaction().begin();

Employee employee = em2.find(Employee.class, 2L);

employee.getAddress().size();
em2.getTransaction().commit();

(A) No cache used
(B) First Level Cache used
(C) Second Level Cache used
(D) None of the above
35
Puzzle	
  #3	
  (2LC	
  Configured,	
  
Hibernate)
EntityManager em1 = emf.createEntityManager();
em1.getTransaction().begin();

Employee employee = em1.find(Employee.class, 2L);

employee.getAddress().size();
em1.getTransaction().commit();

EntityManager em2 = emf.createEntityManager();
em2.getTransaction().begin();

Employee employee = em2.find(Employee.class, 2L);

employee.getAddress().size();
em2.getTransaction().commit();

(A) No cache used
(B) First Level Cache used
(C) Second Level Cache used
(D) None of the above
36
Puzzle	
  #3	
  (2LC	
  Configured,	
  
Hibernate)
EntityManager em1 = emf.createEntityManager();
em1.getTransaction().begin();

Employee employee = em1.find(Employee.class, 2L);

employee.getAddress().size();
em1.getTransaction().commit();

EntityManager em2 = emf.createEntityManager();
em2.getTransaction().begin();

Employee employee = em2.find(Employee.class, 2L);

employee.getAddress().size();
em2.getTransaction().commit();

(A) No cache used
(B) First Level Cache used
(C) Second Level Cache used
(D) None of the above
37
Puzzle	
  #4	
  (2LC	
  Configured!)
em1.getTransaction().begin();

Employee employee = em1.find(Employee.class, 2L);

employee.getAddress().size();
em1.getTransaction().commit();
a
em2.getTransaction().begin();

TypedQuery<Employee> q =
em.createQuery("SELECT e FROM Employee e WHERE e.id=:id", Employee.class);
q.setParameter("id", 2l);

Employee employee = q.getSingleResult();
employee.getAddress().size();
em2.getTransaction().commit();


(A) No cache used
(B) First Level Cache used
(C) Second Level Cache used
(D) None of the above 38
Puzzle	
  #4	
  (2LC	
  Configured!)
em1.getTransaction().begin();

Employee employee = em1.find(Employee.class, 2L);

employee.getAddress().size();
em1.getTransaction().commit();
a
em2.getTransaction().begin();

TypedQuery<Employee> q =
em.createQuery("SELECT e FROM Employee e WHERE e.id=:id", Employee.class);
q.setParameter("id", 2l);

Employee employee = q.getSingleResult();
employee.getAddress().size();
em2.getTransaction().commit();


(A) No cache used
(B) First Level Cache used
(C) Second Level Cache used
(D) None of the above 39
persistence.xml
<shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>

40
Programmatic	
  
Properties props = new Properties()
.add(“javax.persistence.sharedCache.mode”, “ENABLE_SELECTIVE”);
EntityManagerFactor emf = Persistence
.createEntityManagerFactory(“test-pu”, props);
41
JPA	
  Cache	
  Modes
• ALL	
  
• All	
  enXty	
  data	
  is	
  stored	
  in	
  the	
  second-­‐level	
  cache	
  for	
  this	
  persistence	
  unit.	
   	
  
• NONE	
   	
  
• No	
  data	
  is	
  cached	
  in	
  the	
  persistence	
  unit.	
  The	
  persistence	
  provider	
  must	
  not	
  cache	
  any	
  
data.	
  
• ENABLE_SELECTIVE	
   	
  
• Enable	
  caching	
  for	
  enXXes	
  that	
  have	
  been	
  explicitly	
  set	
  with	
  the	
  @Cacheable	
  annotaXon.	
  
• DISABLE_SELECTIVE	
  	
  
• Enable	
  caching	
  for	
  all	
  enXXes	
  except	
  those	
  that	
  have	
  been	
  explicitly	
  set	
  with	
  the	
  
@Cacheable(false)	
  annotaXon.	
   	
  
• UNSPECIFIED	
   	
  
• The	
  caching	
  behavior	
  for	
  the	
  persistence	
  unit	
  is	
  undefined.	
  The	
  persistence	
  provider’s	
  
default	
  caching	
  behavior	
  will	
  be	
  used.
JPA	
  Cache	
  Modes
• ALL	
  
• All	
  enXty	
  data	
  is	
  stored	
  in	
  the	
  second-­‐level	
  cache	
  for	
  this	
  persistence	
  unit.	
   	
  
• NONE	
   	
  
• No	
  data	
  is	
  cached	
  in	
  the	
  persistence	
  unit.	
  The	
  persistence	
  provider	
  must	
  not	
  cache	
  any	
  
data.	
  
• ENABLE_SELECTIVE	
   	
  
• Enable	
  caching	
  for	
  enXXes	
  that	
  have	
  been	
  explicitly	
  set	
  with	
  the	
  @Cacheable	
  annotaXon.	
  
• DISABLE_SELECTIVE	
  	
  
• Enable	
  caching	
  for	
  all	
  enXXes	
  except	
  those	
  that	
  have	
  been	
  explicitly	
  set	
  with	
  the	
  
@Cacheable(false)	
  annotaXon.	
   	
  
• UNSPECIFIED	
   	
  
• The	
  caching	
  behavior	
  for	
  the	
  persistence	
  unit	
  is	
  undefined.	
  The	
  persistence	
  provider’s	
  
default	
  caching	
  behavior	
  will	
  be	
  used.
@Cachable
@Entity

@Cacheable

public class Employee {

}
@Entity

@Cacheable(true)

public class Employee {

}
@Entity

@Cacheable(false)

public class Address {

}
44
@Cacheable
• @Cacheable	
  ignored	
  for	
  ALL	
  or	
  NONE
Cache	
  Retrieval	
  and	
  Store	
  
Modes
• Cache	
  Retrieval	
  Modes	
  
• javax.persistence.CacheRetrieveMode	
  
• USE	
  (default)	
  
• BYPASS	
  
• Cache	
  Store	
  Modes	
  
• javax.persistence.storeMode	
  
• USE	
  (default)	
  
• the	
  cache	
  data	
  is	
  created	
  or	
  updated	
  when	
  data	
  is	
  read	
  from	
  or	
  commiYed	
  to	
  
• when	
  data	
  is	
  already	
  in	
  the	
  cache,	
  no	
  refresh	
  on	
  read	
  
• REFRESH	
  
• forced	
  refresh	
  on	
  read	
  
• BYPASS
Cache	
  Retrieval	
  and	
  Store	
  
EntityManager em = ...;
em.setProperty("javax.persistence.cache.storeMode", “BYPASS");
Map<String, Object> props = new HashMap<String, Object>();
props.put("javax.persistence.cache.retrieveMode", "BYPASS");
Employee employee = = em.find(Employee.class, 1L, props);
TypedQuery<Employee> q = em.createQuery(cq);
q.setHint("javax.persistence.cache.storeMode", "REFRESH");
47
Programmatic	
  Access	
  to	
  Cache
EntityManager em = ...;
Cache cache = em.getEntityManagerFactory().getCache();
if (cache.contains(Employee.class, 1L)) {
// the data is cached
} else {
// the data is NOT cached
}
Cache interface methods:
boolean contains(Class cls, Object primaryKey)
void evict(Class cls)
void evict(Class cls, Object primaryKey)
void evictAll()
<T> T unwrap(Class<T> cls)
48
Forget	
  that!
• Don’t	
  use	
  cache	
  retrieval	
  and	
  store	
  modes	
  
• Don’t	
  use	
  programmaXc	
  access	
  to	
  2LC	
  
• Use	
  provider-­‐specific	
  configuraXon!
Hibernate	
  Caches
Hibernate	
  Caches
• First	
  Level	
  Cache	
  
• Second	
  Level	
  Cache	
  
• hydrated	
  or	
  disassembled	
  enXXes:	
  EnXtyEntry	
  
• collecXons	
  
• Query	
  Cache
Hibernate	
  Cache	
  ConfiguraXon
• hibernate.cache.use_second_level_cache	
  
• Enable	
  or	
  disable	
  second	
  level	
  caching	
  overall.	
  	
  
• Default	
  is	
  true	
  
• hibernate.cache.region.factory_class	
  
• Default	
  region	
  factory	
  is	
  NoCachingRegionFactory	
  
• hibernate.cache.use_query_cache	
  
• Enable	
  or	
  disable	
  second	
  level	
  caching	
  of	
  query	
  results.	
  	
  
• Default	
  is	
  false.	
  
• hibernate.cache.query_cache_factory
Hibernate	
  Cache	
  ConfiguraXon
• hibernate.cache.use_minimal_puts	
  
• OpXmizes	
  second-­‐level	
  cache	
  operaXons	
  to	
  minimize	
  writes,	
  at	
  the	
  
cost	
  of	
  more	
  frequent	
  reads.	
  Providers	
  typically	
  set	
  this	
  appropriately.	
  
• hibernate.cache.default_cache_concurrency_strategy	
  
• In	
  Hibernate	
  second-­‐level	
  caching,	
  all	
  regions	
  can	
  be	
  configured	
  
differently	
  including	
  the	
  concurrency	
  strategy	
  to	
  use	
  when	
  accessing	
  
that	
  parXcular	
  region.	
  This	
  sevng	
  allows	
  to	
  define	
  a	
  default	
  strategy	
  
to	
  be	
  used.	
  
• Providers	
  specify	
  this	
  sevng!
Hibernate	
  Cache	
  ConfiguraXon
• hibernate.cache.use_structured_entries	
  
• If	
  true,	
  forces	
  Hibernate	
  to	
  store	
  data	
  in	
  the	
  second-­‐level	
  cache	
  in	
  a	
  more	
  
human-­‐friendly	
  format.	
  	
  
• Default:	
  false	
  
• hibernate.cache.auto_evict_collecXon_cache	
  
• Enables	
  or	
  disables	
  the	
  automaXc	
  evicXon	
  of	
  a	
  bidirecXonal	
  associaXon’s	
  
collecXon	
  cache	
  entry	
  when	
  the	
  associaXon	
  is	
  changed	
  just	
  from	
  the	
  owning	
  
side.	
  
• Default:	
  false	
  
• hibernate.cache.use_reference_entries	
  
• Enable	
  direct	
  storage	
  of	
  enXty	
  references	
  into	
  the	
  second	
  level	
  cache	
  for	
  
read-­‐only	
  or	
  immutable	
  enXXes.
Cache	
  Concurrency	
  Strategy
• Global	
  cache	
  concurrency	
  strategy	
  
• hibernate.cache.default_cache_concurrency_strategy	
  
• Hibernate	
  @Cache	
  annotaXon	
  on	
  an	
  enXty	
  level	
  
• usage:	
  defines	
  the	
  CacheConcurrencyStrategy	
  
• region:	
  defines	
  a	
  cache	
  region	
  where	
  entries	
  will	
  be	
  stored	
  
• include:	
  if	
  lazy	
  properXes	
  should	
  be	
  included	
  in	
  the	
  second	
  level	
  
cache.	
  Default	
  value	
  is	
  "all",	
  so	
  lazy	
  properXes	
  are	
  cacheable.	
  The	
  
other	
  possible	
  value	
  is	
  "non-­‐lazy",	
  so	
  lazy	
  properXes	
  are	
  not	
  
cacheable.
Cache	
  Concurrency	
  Strategies
• read-­‐only	
  
• ApplicaXon	
  read-­‐only	
  data	
  
• Allows	
  deletes	
  
• read-­‐write	
  
• ApplicaXon	
  updates	
  data	
  
• Consistent	
  access	
  to	
  a	
  single	
  enXty,	
  but	
  not	
  a	
  serializable	
  transacXon	
  isolaXon	
  
level	
  
• nonstrict-­‐read-­‐write	
  
• Occasional	
  stale	
  reads	
  
• transacXonal	
  
• Provides	
  serializable	
  transacXon	
  isolaXon	
  level
Example	
  –	
  Entity	
  and	
  Collection	
  
Cache@Entity
@Cacheable
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Employee {
@OneToMany(mappedBy = "employee", cascade = CascadeType.ALL)
@org.hibernate.annotations.Cache(usage =
CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
private Set<Phone> phones = new HashSet<>();
}
// cache used!
Person person = entityManager.find(Employee.class, 1L);
// cache used!
Person person = entityManager.find(Employee.class, 1L);
person.getPhones().size();
57
Example	
  -­‐	
  Query	
  Cache
List<Employee> employees = entityManager.createQuery(
"select e " +
"from Employee e " +
"where e.firstName = :firstName", Employee.class)
.setParameter( "firstName", "John")
.setHint("org.hibernate.cacheable", "true")
.getResultList();
58
Puzzle	
  #2
EntityManager em1 = emf.createEntityManager();
em1.getTransaction().begin();

Employee employee = em1.find(Employee.class, 2L);

employee.getAddress().size();
em1.getTransaction().commit();

EntityManager em2 = emf.createEntityManager();
em2.getTransaction().begin();

Employee employee = em2.find(Employee.class, 2L);

employee.getAddress().size();
em2.getTransaction().commit();

59
find,	
  no	
  collecXon	
  caching
Local DB
(ping: ~0.05ms)
North California
(ping: ~38ms)
EU Frankfurt
(ping: ~420ms)
No cache 87ms 186ms 1164ms
Cached 62ms 127ms 995ms
find,	
  collecXon	
  caching
Local DB
(ping: ~0.05ms)
North California
(ping: ~38ms)
EU Frankfurt
(ping: ~420ms)
No cache 82ms 162ms 1178ms
Cached 3ms 98ms 941ms
Puzzle	
  #2/P6Spy
EntityManager em1 = emf.createEntityManager();
em1.getTransaction().begin();

Employee employee = em1.find(Employee.class, 2L);

employee.getAddress().size();
em1.getTransaction().commit();

EntityManager em2 = emf.createEntityManager();
em2.getTransaction().begin();

Employee employee = em2.find(Employee.class, 2L);

employee.getAddress().size();
em2.getTransaction().commit();

62
Available	
  Hibernate	
  2nd	
  Level	
  
Cache	
  ImplementaXons
• EHCache	
  
• Infinispan	
  
• Hazelcast
Infinispan	
  Configuration	
  (Local)
<!-- This configuration is suitable for non-clustered environments, where only single instance accesses the DB -->

<cache-container name="SampleCacheManager" statistics="false" default-cache="the-default-cache" shutdown-hook="DEFAULT">

<jmx duplicate-domains="true"/>



<local-cache-configuration name="the-default-cache" statistics="false" />



<!-- Default configuration is appropriate for entity/collection caching. -->

<local-cache-configuration name="entity" simple-cache="true" statistics="false" statistics-available="false">

<transaction mode="NONE" />

<eviction max-entries="10000" strategy="LRU"/>

<expiration max-idle="100000" interval="5000"/>

</local-cache-configuration>



<!-- A config appropriate for query caching. Does not replicate queries. -->

<local-cache-configuration name="local-query" simple-cache="true" statistics="false" statistics-available="false">

<transaction mode="NONE" />

<eviction max-entries="10000" strategy="LRU"/>

<expiration max-idle="100000" interval="5000"/>

</local-cache-configuration>



<local-cache-configuration name="timestamps" simple-cache="true" statistics="false" statistics-available="false">

<locking concurrency-level="1000" acquire-timeout="15000"/>

<!-- Explicitly non transactional -->

<transaction mode="NONE"/>

<!-- Don't ever evict modification timestamps -->

<eviction strategy="NONE"/>

<expiration interval="0"/>

</local-cache-configuration>



<!-- When providing custom configuration, always make this cache local and non-transactional.

64
Infinispan	
  Configuration	
  
(Clustered)<jgroups>

<stack-file name="hibernate-jgroups" path="${hibernate.cache.infinispan.jgroups_cfg:default-configs/default-jgroups-tcp.xml}"/>

</jgroups>

<cache-container name="SampleCacheManager" statistics="false" default-cache="the-default-cache" shutdown-hook="DEFAULT">

<transport stack="hibernate-jgroups" cluster="infinispan-hibernate-cluster"/>

<jmx duplicate-domains="true"/>



<local-cache-configuration name="the-default-cache" statistics="false" />



<!-- Default configuration is appropriate for entity/collection caching. -->

<invalidation-cache-configuration name="entity" mode="SYNC" remote-timeout="20000" statistics="false" statistics-available="false">

<locking concurrency-level="1000" acquire-timeout="15000"/>

<transaction mode="NONE" />

<eviction max-entries="10000" strategy="LRU"/>

<expiration max-idle="100000" interval="5000"/>

</invalidation-cache-configuration>



<!-- A config appropriate for query caching. Does not replicate queries. -->

<local-cache-configuration name="local-query" statistics="false" statistics-available="false">

<locking concurrency-level="1000" acquire-timeout="15000"/>

<transaction mode="NONE" />

<eviction max-entries="10000" strategy="LRU"/>

<expiration max-idle="100000" interval="5000"/>

</local-cache-configuration>



<!-- A query cache that replicates queries. Replication is asynchronous. -->

<replicated-cache-configuration name="replicated-query" mode="ASYNC" statistics="false" statistics-available="false">

<locking concurrency-level="1000" acquire-timeout="15000"/>

<transaction mode="NONE" />

<eviction max-entries="10000" strategy="LRU"/>

<expiration max-idle="100000" interval="5000"/>

</replicated-cache-configuration>



<!-- Optimized for timestamp caching. A clustered timestamp cache

is required if query caching is used, even if the query cache

itself is configured with CacheMode=LOCAL. -->

65
Guidelines
• Cache	
  as	
  much	
  as	
  you	
  can	
  
• As	
  much	
  RAM	
  you	
  have	
  
• Do	
  it	
  wisely	
  
• Read-­‐only	
  data	
  
• Almost	
  read-­‐only	
  data	
  
• More	
  reads	
  than	
  writes	
  
• Hit	
  raXo
EclipseLink
• 2LC	
  enabled	
  by	
  default	
  
• CollecXon	
  caching	
  
• Query	
  caching	
  
• @org.eclipse.persistence.annotaXons.Cache	
  
• type:	
  type	
  of	
  the	
  cache	
  (FULL,	
  WEAK,	
  SOFT,	
  SOFT_WEAK,	
  HARD_WEAK)	
  
• size:	
  number	
  of	
  objects	
  
• isolaXon:	
  shared,	
  isolated,	
  protected	
  
• expiry	
  
• expiryTimeOfDay	
  
• alwaysRefresh	
  
• refreshOnlyIfNewer	
  
• disableHits	
  
• coordinaXonType	
  
• databaseChangeNoXficaXonType
Conclusion
A	
  fool	
  with	
  a	
  tool	
  is	
  only	
  a	
  fool!
ConXnuous	
  Learning	
  
Please,	
  vote!	
  :)
Q&A
• patrycja@yonita.com	
  
• @yonlabs

More Related Content

PPTX
Introduction à spring boot
PPTX
Spring boot
PPTX
Spring boot - an introduction
PPTX
Spring Boot and REST API
PPTX
Spring boot Introduction
PDF
Appalications JEE avec Servlet/JSP
PDF
Spring Boot
Introduction à spring boot
Spring boot
Spring boot - an introduction
Spring Boot and REST API
Spring boot Introduction
Appalications JEE avec Servlet/JSP
Spring Boot

What's hot (20)

PDF
Spring Framework - Core
PDF
Support cours angular
PPTX
Spring Framework
PPTX
Spring boot
PDF
From Java 11 to 17 and beyond.pdf
PDF
PUC SE Day 2019 - SpringBoot
PDF
Spring Boot
PDF
Spring Boot and Microservices
PDF
Interface fonctionnelle, Lambda expression, méthode par défaut, référence de...
PPT
Spring Batch 2.0
PPTX
Introduction to Spring Boot
PDF
Spring Boot
PDF
Maven et industrialisation du logiciel
PDF
Support distributed computing and caching avec hazelcast
PDF
Sql Injection Myths and Fallacies
PPTX
Angular kickstart slideshare
PDF
Spring Meetup Paris - Back to the basics of Spring (Boot)
PPTX
Java Spring framework, Dependency Injection, DI, IoC, Inversion of Control
PDF
A Basic Django Introduction
Spring Framework - Core
Support cours angular
Spring Framework
Spring boot
From Java 11 to 17 and beyond.pdf
PUC SE Day 2019 - SpringBoot
Spring Boot
Spring Boot and Microservices
Interface fonctionnelle, Lambda expression, méthode par défaut, référence de...
Spring Batch 2.0
Introduction to Spring Boot
Spring Boot
Maven et industrialisation du logiciel
Support distributed computing and caching avec hazelcast
Sql Injection Myths and Fallacies
Angular kickstart slideshare
Spring Meetup Paris - Back to the basics of Spring (Boot)
Java Spring framework, Dependency Injection, DI, IoC, Inversion of Control
A Basic Django Introduction
Ad

Viewers also liked (20)

PDF
Lazy vs. Eager Loading Strategies in JPA 2.1
PPTX
Thinking Beyond ORM in JPA
PDF
Java EE 6 & GlassFish 3
PDF
Performance Anti-Patterns in Hibernatee, by Patrycja Wegrzynowicz
PDF
Hibernate using jpa
DOCX
Colloquium Report
PDF
Secure Authentication and Session Management in Java EE
PPT
Spring Boot. Boot up your development
PDF
Java persistence api 2.1
PPTX
JPA For Beginner's
PDF
How To Get The Most Out Of Your Hibernate, JBoss EAP 7 Application (Ståle Ped...
PDF
JPA - Beyond copy-paste
PPTX
JDBC - JPA - Spring Data
PPTX
Spring.Boot up your development
PPTX
Spring data jpa
PDF
Spring Data Jpa
PPTX
Amazon Webservices for Java Developers - UCI Webinar
PPTX
Junior,middle,senior?
PPTX
Introduction to JPA Framework
Lazy vs. Eager Loading Strategies in JPA 2.1
Thinking Beyond ORM in JPA
Java EE 6 & GlassFish 3
Performance Anti-Patterns in Hibernatee, by Patrycja Wegrzynowicz
Hibernate using jpa
Colloquium Report
Secure Authentication and Session Management in Java EE
Spring Boot. Boot up your development
Java persistence api 2.1
JPA For Beginner's
How To Get The Most Out Of Your Hibernate, JBoss EAP 7 Application (Ståle Ped...
JPA - Beyond copy-paste
JDBC - JPA - Spring Data
Spring.Boot up your development
Spring data jpa
Spring Data Jpa
Amazon Webservices for Java Developers - UCI Webinar
Junior,middle,senior?
Introduction to JPA Framework
Ad

Similar to Second Level Cache in JPA Explained (20)

PDF
Presto anatomy
PDF
A Deep Dive into Query Execution Engine of Spark SQL
PDF
My Top 5 APEX JavaScript API's
PDF
[245] presto 내부구조 파헤치기
PPTX
Flink internals web
PDF
Testing and validating spark programs - Strata SJ 2016
PDF
Beyond Parallelize and Collect by Holden Karau
PDF
Everyday I'm Shuffling - Tips for Writing Better Spark Programs, Strata San J...
PDF
Building Hermetic Systems (without Docker)
PDF
Apache Flink Deep Dive
PDF
Apache Flink internals
PDF
Test strategies for data processing pipelines, v2.0
PDF
ES6: The Awesome Parts
PDF
Ufuc Celebi – Stream & Batch Processing in one System
PPTX
The SAM Pattern: State Machines and Computation
PDF
Java OOP Programming language (Part 8) - Java Database JDBC
PDF
GDG Jakarta Meetup - Streaming Analytics With Apache Beam
PDF
Complex Made Simple: Sleep Better with TorqueBox
PPTX
Beyond parallelize and collect - Spark Summit East 2016
PDF
Standardizing JavaScript Decorators in TC39 (Full Stack Fest 2019)
Presto anatomy
A Deep Dive into Query Execution Engine of Spark SQL
My Top 5 APEX JavaScript API's
[245] presto 내부구조 파헤치기
Flink internals web
Testing and validating spark programs - Strata SJ 2016
Beyond Parallelize and Collect by Holden Karau
Everyday I'm Shuffling - Tips for Writing Better Spark Programs, Strata San J...
Building Hermetic Systems (without Docker)
Apache Flink Deep Dive
Apache Flink internals
Test strategies for data processing pipelines, v2.0
ES6: The Awesome Parts
Ufuc Celebi – Stream & Batch Processing in one System
The SAM Pattern: State Machines and Computation
Java OOP Programming language (Part 8) - Java Database JDBC
GDG Jakarta Meetup - Streaming Analytics With Apache Beam
Complex Made Simple: Sleep Better with TorqueBox
Beyond parallelize and collect - Spark Summit East 2016
Standardizing JavaScript Decorators in TC39 (Full Stack Fest 2019)

More from Patrycja Wegrzynowicz (9)

PDF
The Hacker's Guide to Kubernetes: Reloaded
PDF
The Hacker's Guide to Kubernetes
PDF
The Hacker's Guide to JWT Security
PDF
The Hacker's Guide to JWT Security
PDF
The Hacker's Guide to XSS
PDF
The Hacker's Guide to NoSQL Injection
PDF
The Hacker's Guide to Session Hijacking
PDF
The Hacker's Guide To Session Hijacking
PPTX
Thinking Beyond ORM in JPA
The Hacker's Guide to Kubernetes: Reloaded
The Hacker's Guide to Kubernetes
The Hacker's Guide to JWT Security
The Hacker's Guide to JWT Security
The Hacker's Guide to XSS
The Hacker's Guide to NoSQL Injection
The Hacker's Guide to Session Hijacking
The Hacker's Guide To Session Hijacking
Thinking Beyond ORM in JPA

Recently uploaded (20)

PDF
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
PDF
Diabetes mellitus diagnosis method based random forest with bat algorithm
PDF
Empathic Computing: Creating Shared Understanding
PDF
Reach Out and Touch Someone: Haptics and Empathic Computing
PDF
CIFDAQ's Market Insight: SEC Turns Pro Crypto
PDF
cuic standard and advanced reporting.pdf
PPTX
20250228 LYD VKU AI Blended-Learning.pptx
PPTX
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
PDF
Approach and Philosophy of On baking technology
PPTX
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
PPT
“AI and Expert System Decision Support & Business Intelligence Systems”
PPT
Teaching material agriculture food technology
PDF
NewMind AI Monthly Chronicles - July 2025
PDF
Shreyas Phanse Resume: Experienced Backend Engineer | Java • Spring Boot • Ka...
PDF
Electronic commerce courselecture one. Pdf
PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
PDF
Advanced methodologies resolving dimensionality complications for autism neur...
PDF
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
PDF
The Rise and Fall of 3GPP – Time for a Sabbatical?
PDF
Building Integrated photovoltaic BIPV_UPV.pdf
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
Diabetes mellitus diagnosis method based random forest with bat algorithm
Empathic Computing: Creating Shared Understanding
Reach Out and Touch Someone: Haptics and Empathic Computing
CIFDAQ's Market Insight: SEC Turns Pro Crypto
cuic standard and advanced reporting.pdf
20250228 LYD VKU AI Blended-Learning.pptx
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
Approach and Philosophy of On baking technology
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
“AI and Expert System Decision Support & Business Intelligence Systems”
Teaching material agriculture food technology
NewMind AI Monthly Chronicles - July 2025
Shreyas Phanse Resume: Experienced Backend Engineer | Java • Spring Boot • Ka...
Electronic commerce courselecture one. Pdf
Digital-Transformation-Roadmap-for-Companies.pptx
Advanced methodologies resolving dimensionality complications for autism neur...
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
The Rise and Fall of 3GPP – Time for a Sabbatical?
Building Integrated photovoltaic BIPV_UPV.pdf

Second Level Cache in JPA Explained

  • 1. Second-­‐Level  Cache     in  JPA  Explained Patrycja  Wegrzynowicz   CTO,  Yonita,  Inc.   JavaOne  2016
  • 2. About  Me • 15+  professional  experience     • SoPware  engineer,  architect,  head  of   soPware  R&D     • Author  and  speaker     • JavaOne,  Devoxx,  JavaZone,   TheServerSide  Java  Symposium,  Jazoon,   OOPSLA,  ASE,  others     • Top  10  Women  in  Tech  2016  in  Poland   • Founder  and  CTO  of  Yonita   • Automated  detecXon  and  refactoring  of   soPware  defects   • Trainings  and  code  reviews   • Security,  performance,  concurrency,   databases     • TwiYer  @yonlabs  
  • 3. About  Me • 15+  professional  experience     • SoPware  engineer,  architect,  head  of   soPware  R&D     • Author  and  speaker     • JavaOne,  Devoxx,  JavaZone,   TheServerSide  Java  Symposium,  Jazoon,   OOPSLA,  ASE,  others     • Top  10  Women  in  Tech  2016  in  Poland   • Founder  and  CTO  of  Yonita   • Automated  detecXon  and  refactoring  of   soPware  defects   • Trainings  and  code  reviews   • Security,  performance,  concurrency,   databases     • TwiYer  @yonlabs  
  • 4. Agenda • Why  cacheing  is  important?   • 1st  Level  Cache  and  2nd  Level  Cache   • JPA  configuraXon  parameters  for  cache   • JPA  API  for  cache   • Hibernate  2nd  Level  Cache   • EclipseLink  2nd  Level  Cache  (a  bit)
  • 14. Employee  Entity @Entity public class Employee {
 @Id @GeneratedValue private Long id;
 private String firstName; 
 private String lastName;
 private BigDecimal salary;
 @OneToOne @JoinColumn(name = "address_id")
 private Address address;
 @Temporal(TemporalType.DATE)
 private Date startDate;
 @Temporal(TemporalType.DATE)
 private Date endDate; 
 @ManyToOne @JoinColumn(name = "manager_id")
 private Employee manager; // …
 } 14
  • 15. Sum  of  Salaries  By  Country
 Select  All  (1) TypedQuery<Employee> query = em.createQuery( "SELECT e FROM Employee e", Employee.class); List<Employee> list = query.getResultList();
 // calculate sum of salaries by country // map: country->sum Map<String, BigDecimal> results = new HashMap<>();
 for (Employee e : list) {
 String country = e.getAddress().getCountry();
 BigDecimal total = results.get(country);
 if (total == null) total = BigDecimal.ZERO;
 total = total.add(e.getSalary());
 results.put(country, total);
 }
 15
  • 16. Sum  of  Salaries  by  Country
 Select  Join  Fetch  (2) TypedQuery<Employee> query = em.createQuery( "SELECT e FROM Employee e JOIN FETCH e.address", Employee.class);
 List<Employee> list = query.getResultList();
 // calculate sum of salaries by country // map: country->sum Map<String, BigDecimal> results = new HashMap<>();
 for (Employee e : list) {
 String country = e.getAddress().getCountry();
 BigDecimal total = results.get(country);
 if (total == null) total = BigDecimal.ZERO;
 total = total.add(e.getSalary());
 results.put(country, total);
 }
 16
  • 17. Sum  of  Salaries  by  Country
 Projection  (3) Query query = em.createQuery( "SELECT e.salary, e.address.country FROM Employee e");
 List<Object[]> list = (List<Object[]>) query.getResultList();
 // calculate sum of salaries by country // map: country->sum Map<String, BigDecimal> results = new HashMap<>();
 for (Object[] e : list) {
 String country = (String) e[1];
 BigDecimal total = results.get(country);
 if (total == null) total = BigDecimal.ZERO;
 total = total.add((BigDecimal) e[0]);
 results.put(country, total);
 }
 17
  • 18. Sum  of  Salaries  by  Country
 Aggregation  JPQL  (4) Query query = em.createQuery( "SELECT SUM(e.salary), e.address.country FROM Employee e GROUP BY e.address.country"); List<Object[]> list = (List<Object[]>) query.getResultList();
 // already calculated!
 18
  • 19. Comparison  1-­‐4  (Hibernate)   100000  Employees,  Different  DB  LocaXons Local DB (ping: ~0.05ms) North California (ping: ~38ms) EU Frankfurt (ping: ~420ms) (1) Select All (N+1) 26756ms 2-3 hours ~1 day (2) Select Join Fetch (3) Projection (4) Aggregation JPQL
  • 20. Comparison  1-­‐4   100000  Employees,  Different  DB  LocaXons Local DB (ping: ~0.05ms) North California (ping: ~38ms) EU Frankfurt (ping: ~420ms) (1) Select All (N+1) 26756ms 2-3 hours ~1 day (2) Select Join Fetch 4854ms 18027ms 25096ms (3) Projection (4) Aggregation JPQL
  • 21. Comparison  1-­‐4   100000  Employees,  Different  DB  LocaXons Local DB (ping: ~0.05ms) North California (ping: ~38ms) EU Frankfurt (ping: ~420ms) (1) Select All (N+1) 26756ms 2-3 hours ~1 day (2) Select Join Fetch 4854ms 18027ms 25096ms (3) Projection 653ms 2902ms 5006ms (4) Aggregation JPQL
  • 22. Comparison  1-­‐4   100000  Employees,  Different  DB  LocaXons Local DB (ping: ~0.05ms) North California (ping: ~38ms) EU Frankfurt (ping: ~420ms) (1) Select All (N+1) 26756ms 2-3 hours ~1 day (2) Select Join Fetch 4854ms 18027ms 25096ms (3) Projection 653ms 2902ms 5006ms (4) Aggregation JPQL 182ms 353ms 1198ms
  • 23. Performance  Tuning:  Data • Get  your  data  in  bigger  chunks     • Many  small  queries  =>  many  round-­‐trips  =>  huge  extra  Xme  on   transport  =>  high  latency   • Move  your  data  closer  to  the  processing  place   • Large  distance  to  data  =>  long  round-­‐trip  =>  high  latency   • Don’t  ask  about  the  same  data  many  Xmes   • Extra  processing  Xme  +  extra  transport  Xme Cache
  • 24. Cache  is  Everywhere Web Cache Application Cache RDBMS Cache DNS Cache OS Files Cache
  • 25. Second  Level  Cache  in   JPA
  • 26. JPA  Spec • “Persistence  providers  are  not  required  to  support  a   second-­‐level  cache.”   • “Portable  applicaXons  should  not  rely  on  support  by   persistence  providers  for  a  second-­‐level  cache.”
  • 27. JPA  Providers  Poll A. Hibernate   B. EclipseLink   C. OpenJPA   D. DataNuclues   E. Other
  • 28. • Second  Level  Cache   • Persistence  Unit   • EnXtyManagerFactory   • Thread-­‐safe,  shared   • Available  for  many  en1ty   managers  from  one  en1ty   manager  factory   • Provider  specific  support JPA  Caches • First  Level  Cache   • Persistence  Context   • EnXtyManager   • Not  thread-­‐safe   • Available  for  many   transac1ons  on  one  en1ty   manager   • Always
  • 30. Puzzle  #1 em.getTransaction().begin();
 Employee employee = em.find(Employee.class, 2L);
 employee.getAddress().size(); Employee another = em.find(Employee.class, 2L);
 em.getTransaction().commit();
 (A) No cache used (B) First Level Cache Used (C) Second Level Cache Used (D) None of the above 30
  • 31. Loading EntityManager Factory 2LC EntityManager 1LC load from 1LC load from 2LC select from database NOT FOUND NOT FOUND FOUND FOUND RESULT FIND
  • 32. Puzzle  #1 EntityManager em = emf.createEntityManager(); em.getTransaction().begin();
 Employee employee = em.find(Employee.class, 2L);
 employee.getAddress().size(); Employee another = em.find(Employee.class, 2L);
 em.getTransaction().commit();
 (A) No cache used (B) First Level Cache Used (C) Second Level Cache Used (D) None of the above 32
  • 33. Puzzle  #1 EntityManager em = emf.createEntityManager(); em.getTransaction().begin();
 Employee employee = em.find(Employee.class, 2L);
 employee.getAddress().size(); Employee another = em.find(Employee.class, 2L);
 em.getTransaction().commit();
 (A) No cache used (B) First Level Cache Used (C) Second Level Cache Used (D) None of the above 33
  • 34. Puzzle  #2 EntityManager em1 = emf.createEntityManager(); em1.getTransaction().begin();
 Employee employee = em1.find(Employee.class, 2L);
 employee.getAddress().size(); em1.getTransaction().commit();
 EntityManager em2 = emf.createEntityManager(); em2.getTransaction().begin();
 Employee employee = em2.find(Employee.class, 2L);
 employee.getAddress().size(); em2.getTransaction().commit();
 (A) No cache used (B) First Level Cache used (C) Second Level Cache used (D) None of the above 34
  • 35. Puzzle  #2 EntityManager em1 = emf.createEntityManager(); em1.getTransaction().begin();
 Employee employee = em1.find(Employee.class, 2L);
 employee.getAddress().size(); em1.getTransaction().commit();
 EntityManager em2 = emf.createEntityManager(); em2.getTransaction().begin();
 Employee employee = em2.find(Employee.class, 2L);
 employee.getAddress().size(); em2.getTransaction().commit();
 (A) No cache used (B) First Level Cache used (C) Second Level Cache used (D) None of the above 35
  • 36. Puzzle  #3  (2LC  Configured,   Hibernate) EntityManager em1 = emf.createEntityManager(); em1.getTransaction().begin();
 Employee employee = em1.find(Employee.class, 2L);
 employee.getAddress().size(); em1.getTransaction().commit();
 EntityManager em2 = emf.createEntityManager(); em2.getTransaction().begin();
 Employee employee = em2.find(Employee.class, 2L);
 employee.getAddress().size(); em2.getTransaction().commit();
 (A) No cache used (B) First Level Cache used (C) Second Level Cache used (D) None of the above 36
  • 37. Puzzle  #3  (2LC  Configured,   Hibernate) EntityManager em1 = emf.createEntityManager(); em1.getTransaction().begin();
 Employee employee = em1.find(Employee.class, 2L);
 employee.getAddress().size(); em1.getTransaction().commit();
 EntityManager em2 = emf.createEntityManager(); em2.getTransaction().begin();
 Employee employee = em2.find(Employee.class, 2L);
 employee.getAddress().size(); em2.getTransaction().commit();
 (A) No cache used (B) First Level Cache used (C) Second Level Cache used (D) None of the above 37
  • 38. Puzzle  #4  (2LC  Configured!) em1.getTransaction().begin();
 Employee employee = em1.find(Employee.class, 2L);
 employee.getAddress().size(); em1.getTransaction().commit();
a em2.getTransaction().begin();
 TypedQuery<Employee> q = em.createQuery("SELECT e FROM Employee e WHERE e.id=:id", Employee.class); q.setParameter("id", 2l);
 Employee employee = q.getSingleResult(); employee.getAddress().size(); em2.getTransaction().commit(); 
 (A) No cache used (B) First Level Cache used (C) Second Level Cache used (D) None of the above 38
  • 39. Puzzle  #4  (2LC  Configured!) em1.getTransaction().begin();
 Employee employee = em1.find(Employee.class, 2L);
 employee.getAddress().size(); em1.getTransaction().commit();
a em2.getTransaction().begin();
 TypedQuery<Employee> q = em.createQuery("SELECT e FROM Employee e WHERE e.id=:id", Employee.class); q.setParameter("id", 2l);
 Employee employee = q.getSingleResult(); employee.getAddress().size(); em2.getTransaction().commit(); 
 (A) No cache used (B) First Level Cache used (C) Second Level Cache used (D) None of the above 39
  • 41. Programmatic   Properties props = new Properties() .add(“javax.persistence.sharedCache.mode”, “ENABLE_SELECTIVE”); EntityManagerFactor emf = Persistence .createEntityManagerFactory(“test-pu”, props); 41
  • 42. JPA  Cache  Modes • ALL   • All  enXty  data  is  stored  in  the  second-­‐level  cache  for  this  persistence  unit.     • NONE     • No  data  is  cached  in  the  persistence  unit.  The  persistence  provider  must  not  cache  any   data.   • ENABLE_SELECTIVE     • Enable  caching  for  enXXes  that  have  been  explicitly  set  with  the  @Cacheable  annotaXon.   • DISABLE_SELECTIVE     • Enable  caching  for  all  enXXes  except  those  that  have  been  explicitly  set  with  the   @Cacheable(false)  annotaXon.     • UNSPECIFIED     • The  caching  behavior  for  the  persistence  unit  is  undefined.  The  persistence  provider’s   default  caching  behavior  will  be  used.
  • 43. JPA  Cache  Modes • ALL   • All  enXty  data  is  stored  in  the  second-­‐level  cache  for  this  persistence  unit.     • NONE     • No  data  is  cached  in  the  persistence  unit.  The  persistence  provider  must  not  cache  any   data.   • ENABLE_SELECTIVE     • Enable  caching  for  enXXes  that  have  been  explicitly  set  with  the  @Cacheable  annotaXon.   • DISABLE_SELECTIVE     • Enable  caching  for  all  enXXes  except  those  that  have  been  explicitly  set  with  the   @Cacheable(false)  annotaXon.     • UNSPECIFIED     • The  caching  behavior  for  the  persistence  unit  is  undefined.  The  persistence  provider’s   default  caching  behavior  will  be  used.
  • 44. @Cachable @Entity
 @Cacheable
 public class Employee {
 } @Entity
 @Cacheable(true)
 public class Employee {
 } @Entity
 @Cacheable(false)
 public class Address {
 } 44
  • 45. @Cacheable • @Cacheable  ignored  for  ALL  or  NONE
  • 46. Cache  Retrieval  and  Store   Modes • Cache  Retrieval  Modes   • javax.persistence.CacheRetrieveMode   • USE  (default)   • BYPASS   • Cache  Store  Modes   • javax.persistence.storeMode   • USE  (default)   • the  cache  data  is  created  or  updated  when  data  is  read  from  or  commiYed  to   • when  data  is  already  in  the  cache,  no  refresh  on  read   • REFRESH   • forced  refresh  on  read   • BYPASS
  • 47. Cache  Retrieval  and  Store   EntityManager em = ...; em.setProperty("javax.persistence.cache.storeMode", “BYPASS"); Map<String, Object> props = new HashMap<String, Object>(); props.put("javax.persistence.cache.retrieveMode", "BYPASS"); Employee employee = = em.find(Employee.class, 1L, props); TypedQuery<Employee> q = em.createQuery(cq); q.setHint("javax.persistence.cache.storeMode", "REFRESH"); 47
  • 48. Programmatic  Access  to  Cache EntityManager em = ...; Cache cache = em.getEntityManagerFactory().getCache(); if (cache.contains(Employee.class, 1L)) { // the data is cached } else { // the data is NOT cached } Cache interface methods: boolean contains(Class cls, Object primaryKey) void evict(Class cls) void evict(Class cls, Object primaryKey) void evictAll() <T> T unwrap(Class<T> cls) 48
  • 49. Forget  that! • Don’t  use  cache  retrieval  and  store  modes   • Don’t  use  programmaXc  access  to  2LC   • Use  provider-­‐specific  configuraXon!
  • 51. Hibernate  Caches • First  Level  Cache   • Second  Level  Cache   • hydrated  or  disassembled  enXXes:  EnXtyEntry   • collecXons   • Query  Cache
  • 52. Hibernate  Cache  ConfiguraXon • hibernate.cache.use_second_level_cache   • Enable  or  disable  second  level  caching  overall.     • Default  is  true   • hibernate.cache.region.factory_class   • Default  region  factory  is  NoCachingRegionFactory   • hibernate.cache.use_query_cache   • Enable  or  disable  second  level  caching  of  query  results.     • Default  is  false.   • hibernate.cache.query_cache_factory
  • 53. Hibernate  Cache  ConfiguraXon • hibernate.cache.use_minimal_puts   • OpXmizes  second-­‐level  cache  operaXons  to  minimize  writes,  at  the   cost  of  more  frequent  reads.  Providers  typically  set  this  appropriately.   • hibernate.cache.default_cache_concurrency_strategy   • In  Hibernate  second-­‐level  caching,  all  regions  can  be  configured   differently  including  the  concurrency  strategy  to  use  when  accessing   that  parXcular  region.  This  sevng  allows  to  define  a  default  strategy   to  be  used.   • Providers  specify  this  sevng!
  • 54. Hibernate  Cache  ConfiguraXon • hibernate.cache.use_structured_entries   • If  true,  forces  Hibernate  to  store  data  in  the  second-­‐level  cache  in  a  more   human-­‐friendly  format.     • Default:  false   • hibernate.cache.auto_evict_collecXon_cache   • Enables  or  disables  the  automaXc  evicXon  of  a  bidirecXonal  associaXon’s   collecXon  cache  entry  when  the  associaXon  is  changed  just  from  the  owning   side.   • Default:  false   • hibernate.cache.use_reference_entries   • Enable  direct  storage  of  enXty  references  into  the  second  level  cache  for   read-­‐only  or  immutable  enXXes.
  • 55. Cache  Concurrency  Strategy • Global  cache  concurrency  strategy   • hibernate.cache.default_cache_concurrency_strategy   • Hibernate  @Cache  annotaXon  on  an  enXty  level   • usage:  defines  the  CacheConcurrencyStrategy   • region:  defines  a  cache  region  where  entries  will  be  stored   • include:  if  lazy  properXes  should  be  included  in  the  second  level   cache.  Default  value  is  "all",  so  lazy  properXes  are  cacheable.  The   other  possible  value  is  "non-­‐lazy",  so  lazy  properXes  are  not   cacheable.
  • 56. Cache  Concurrency  Strategies • read-­‐only   • ApplicaXon  read-­‐only  data   • Allows  deletes   • read-­‐write   • ApplicaXon  updates  data   • Consistent  access  to  a  single  enXty,  but  not  a  serializable  transacXon  isolaXon   level   • nonstrict-­‐read-­‐write   • Occasional  stale  reads   • transacXonal   • Provides  serializable  transacXon  isolaXon  level
  • 57. Example  –  Entity  and  Collection   Cache@Entity @Cacheable @org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE) public class Employee { @OneToMany(mappedBy = "employee", cascade = CascadeType.ALL) @org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) private Set<Phone> phones = new HashSet<>(); } // cache used! Person person = entityManager.find(Employee.class, 1L); // cache used! Person person = entityManager.find(Employee.class, 1L); person.getPhones().size(); 57
  • 58. Example  -­‐  Query  Cache List<Employee> employees = entityManager.createQuery( "select e " + "from Employee e " + "where e.firstName = :firstName", Employee.class) .setParameter( "firstName", "John") .setHint("org.hibernate.cacheable", "true") .getResultList(); 58
  • 59. Puzzle  #2 EntityManager em1 = emf.createEntityManager(); em1.getTransaction().begin();
 Employee employee = em1.find(Employee.class, 2L);
 employee.getAddress().size(); em1.getTransaction().commit();
 EntityManager em2 = emf.createEntityManager(); em2.getTransaction().begin();
 Employee employee = em2.find(Employee.class, 2L);
 employee.getAddress().size(); em2.getTransaction().commit();
 59
  • 60. find,  no  collecXon  caching Local DB (ping: ~0.05ms) North California (ping: ~38ms) EU Frankfurt (ping: ~420ms) No cache 87ms 186ms 1164ms Cached 62ms 127ms 995ms
  • 61. find,  collecXon  caching Local DB (ping: ~0.05ms) North California (ping: ~38ms) EU Frankfurt (ping: ~420ms) No cache 82ms 162ms 1178ms Cached 3ms 98ms 941ms
  • 62. Puzzle  #2/P6Spy EntityManager em1 = emf.createEntityManager(); em1.getTransaction().begin();
 Employee employee = em1.find(Employee.class, 2L);
 employee.getAddress().size(); em1.getTransaction().commit();
 EntityManager em2 = emf.createEntityManager(); em2.getTransaction().begin();
 Employee employee = em2.find(Employee.class, 2L);
 employee.getAddress().size(); em2.getTransaction().commit();
 62
  • 63. Available  Hibernate  2nd  Level   Cache  ImplementaXons • EHCache   • Infinispan   • Hazelcast
  • 64. Infinispan  Configuration  (Local) <!-- This configuration is suitable for non-clustered environments, where only single instance accesses the DB -->
 <cache-container name="SampleCacheManager" statistics="false" default-cache="the-default-cache" shutdown-hook="DEFAULT">
 <jmx duplicate-domains="true"/>
 
 <local-cache-configuration name="the-default-cache" statistics="false" />
 
 <!-- Default configuration is appropriate for entity/collection caching. -->
 <local-cache-configuration name="entity" simple-cache="true" statistics="false" statistics-available="false">
 <transaction mode="NONE" />
 <eviction max-entries="10000" strategy="LRU"/>
 <expiration max-idle="100000" interval="5000"/>
 </local-cache-configuration>
 
 <!-- A config appropriate for query caching. Does not replicate queries. -->
 <local-cache-configuration name="local-query" simple-cache="true" statistics="false" statistics-available="false">
 <transaction mode="NONE" />
 <eviction max-entries="10000" strategy="LRU"/>
 <expiration max-idle="100000" interval="5000"/>
 </local-cache-configuration>
 
 <local-cache-configuration name="timestamps" simple-cache="true" statistics="false" statistics-available="false">
 <locking concurrency-level="1000" acquire-timeout="15000"/>
 <!-- Explicitly non transactional -->
 <transaction mode="NONE"/>
 <!-- Don't ever evict modification timestamps -->
 <eviction strategy="NONE"/>
 <expiration interval="0"/>
 </local-cache-configuration>
 
 <!-- When providing custom configuration, always make this cache local and non-transactional.
 64
  • 65. Infinispan  Configuration   (Clustered)<jgroups>
 <stack-file name="hibernate-jgroups" path="${hibernate.cache.infinispan.jgroups_cfg:default-configs/default-jgroups-tcp.xml}"/>
 </jgroups>
 <cache-container name="SampleCacheManager" statistics="false" default-cache="the-default-cache" shutdown-hook="DEFAULT">
 <transport stack="hibernate-jgroups" cluster="infinispan-hibernate-cluster"/>
 <jmx duplicate-domains="true"/>
 
 <local-cache-configuration name="the-default-cache" statistics="false" />
 
 <!-- Default configuration is appropriate for entity/collection caching. -->
 <invalidation-cache-configuration name="entity" mode="SYNC" remote-timeout="20000" statistics="false" statistics-available="false">
 <locking concurrency-level="1000" acquire-timeout="15000"/>
 <transaction mode="NONE" />
 <eviction max-entries="10000" strategy="LRU"/>
 <expiration max-idle="100000" interval="5000"/>
 </invalidation-cache-configuration>
 
 <!-- A config appropriate for query caching. Does not replicate queries. -->
 <local-cache-configuration name="local-query" statistics="false" statistics-available="false">
 <locking concurrency-level="1000" acquire-timeout="15000"/>
 <transaction mode="NONE" />
 <eviction max-entries="10000" strategy="LRU"/>
 <expiration max-idle="100000" interval="5000"/>
 </local-cache-configuration>
 
 <!-- A query cache that replicates queries. Replication is asynchronous. -->
 <replicated-cache-configuration name="replicated-query" mode="ASYNC" statistics="false" statistics-available="false">
 <locking concurrency-level="1000" acquire-timeout="15000"/>
 <transaction mode="NONE" />
 <eviction max-entries="10000" strategy="LRU"/>
 <expiration max-idle="100000" interval="5000"/>
 </replicated-cache-configuration>
 
 <!-- Optimized for timestamp caching. A clustered timestamp cache
 is required if query caching is used, even if the query cache
 itself is configured with CacheMode=LOCAL. -->
 65
  • 66. Guidelines • Cache  as  much  as  you  can   • As  much  RAM  you  have   • Do  it  wisely   • Read-­‐only  data   • Almost  read-­‐only  data   • More  reads  than  writes   • Hit  raXo
  • 67. EclipseLink • 2LC  enabled  by  default   • CollecXon  caching   • Query  caching   • @org.eclipse.persistence.annotaXons.Cache   • type:  type  of  the  cache  (FULL,  WEAK,  SOFT,  SOFT_WEAK,  HARD_WEAK)   • size:  number  of  objects   • isolaXon:  shared,  isolated,  protected   • expiry   • expiryTimeOfDay   • alwaysRefresh   • refreshOnlyIfNewer   • disableHits   • coordinaXonType   • databaseChangeNoXficaXonType
  • 69. A  fool  with  a  tool  is  only  a  fool!