Java & SQL Stronger Together · Database JDBC JPA Spring Data JPA Your Code Provides unique API...

Preview:

Citation preview

Java & SQL Stronger Together

@MarkusWinand @ModernSQL

Picture: Africa Studio@Shutterstock

“We can solve any problem by introducing an extra

level of abstraction” (Based on the “fundamental theorem of software engineering”)

Database

DatabaseJDBC

Provides unique API for different SQL-

Databases

DatabaseJDBCJPA

Provides unique API for different SQL-

Databases

Maps objects from/to tables

DatabaseJDBCJPA

Spring Data JPA

Provides unique API for different SQL-

Databases

Maps objects from/to tables

Makes common tasks very simple

DatabaseJDBCJPA

Spring Data JPAYour Code

Provides unique API for different SQL-

Databases

Maps objects from/to tables

Makes common tasks very simple

DatabaseJDBCJPA

Spring Data JPAYour Code

Provides unique API for different SQL-

Databases

Maps Objects from/to tables

Makes common tasks very simple

90%?

Doesn’t provide 100% of underlying

functionality

DatabaseJDBCJPA

Spring Data JPAYour Code

Provides unique API for different SQL-

Databases

Maps Objects from/to tables

Makes common tasks very simple

90%?Proprietary data types? —> (VendorCls)jdbcCls

DatabaseJDBCJPA

Spring Data JPAYour Code

Provides unique API for different SQL-

Databases

Maps Objects from/to tables

Makes common tasks very simple

90%?Proprietary data types? —> (VendorCls)jdbcCls

The processing is not about objects? —> QueryBuilder, JPQL

or native queries

DatabaseJDBCJPA

Spring Data JPAYour Code

Provides unique API for different SQL-

Databases

Maps Objects from/to tables

Makes common tasks very simple

90%?Proprietary data types? —> (VendorCls)jdbcCls

The processing is not about objects? —> QueryBuilder, JPQL

or native queries

“Hibernate’s design goal is to relieve the developer

from 95% of common data persistence-related

programming tasks[…] Hibernate does not hide

the power of SQLfrom you[…]”

— Hibernate ORM User Guide (second paragraph)

DatabaseJDBCJPA

Spring Data JPAYour Code

Provides unique API for different SQL-

Databases

Maps Objects from/to tables

Makes common tasks very simple

90%?Proprietary data types? —> (VendorCls)jdbcCls

The processing is not about objects? —> QueryBuilder, JPQL

or native queries

DatabaseJDBCJPA

Spring Data JPAYour Code

Provides unique API for different SQL-

Databases

Maps Objects from/to tables

Makes common tasks very simple

90%?Proprietary data types? —> (VendorCls)jdbcCls

The processing is not about objects? —> QueryBuilder, JPQL

or native queries

findBy… not powerful enough? —> QueryBuilder, JPQL

or native queries

What is theright level of abstraction

for any given problem?

Pattern #1: Lists

1.2.3.

Go for a walk in the woods

Picnic

Improve SQL-foo

BUCKET LISTSpring

DatabaseJDBCJPA

Spring Data JPAYour Code

List: All Attributes

DatabaseJDBCJPA

Spring Data JPAYour Code

SELECT*FROMtbl

List: All Attributes

DatabaseJDBCJPA

Spring Data JPAYour Code

ResultSetrs=c.prepareStatement("SELECT*"+"FROMtbl").executeQuery();

SELECT*FROMtbl

List: All Attributes

DatabaseJDBCJPA

Spring Data JPAYour Code

Collection<Entity>c=em.createQuery("FROMEntity").getResultList();

ResultSetrs=c.prepareStatement("SELECT*"+"FROMtbl").executeQuery();

SELECT*FROMtbl

List: All Attributes

DatabaseJDBCJPA

Spring Data JPAYour Code

Collection<Entity>c=em.createQuery("FROMEntity").getResultList();

Collection<Entity>c=r.findAll();

ResultSetrs=c.prepareStatement("SELECT*"+"FROMtbl").executeQuery();

SELECT*FROMtbl

List: All Attributes

DatabaseJDBCJPA

Spring Data JPAYour Code

List: Some Attributes

DatabaseJDBCJPA

Spring Data JPAYour Code

SELECTa1,…FROMtbl

List: Some Attributes

DatabaseJDBCJPA

Spring Data JPAYour Code

SELECTa1,…FROMtbl

List: Some Attributes

Runtime improvement: ~0% - 10 000%

DatabaseJDBCJPA

Spring Data JPAYour Code

SELECTa1,…FROMtbl

List: Some Attributes

Runtime improvement: ~0% - 10 000%

Affects:

DatabaseJDBCJPA

Spring Data JPAYour Code

SELECTa1,…FROMtbl

List: Some Attributes

Runtime improvement: ~0% - 10 000%

Affects:- Java: GC

DatabaseJDBCJPA

Spring Data JPAYour Code

SELECTa1,…FROMtbl

List: Some Attributes

Runtime improvement: ~0% - 10 000%

Affects:- Java: GC- Network

DatabaseJDBCJPA

Spring Data JPAYour Code

SELECTa1,…FROMtbl

List: Some Attributes

Runtime improvement: ~0% - 10 000%

Affects:- Java: GC- Network- Database:

DatabaseJDBCJPA

Spring Data JPAYour Code

SELECTa1,…FROMtbl

List: Some Attributes

Runtime improvement: ~0% - 10 000%

Affects:- Java: GC- Network- Database:

- Index Only Scan

DatabaseJDBCJPA

Spring Data JPAYour Code

SELECTa1,…FROMtbl

List: Some Attributes

Runtime improvement: ~0% - 10 000%

Affects: - Java: GC - Network - Database:

- Index Only Scan - Mem + CPU (e.g. sorting)

DatabaseJDBCJPA

Spring Data JPAYour Code

ResultSetrs=c.prepareStatement("SELECTa1,…"+"FROMtbl").executeQuery();

SELECTa1,…FROMtbl

List: Some Attributes

DatabaseJDBCJPA

Spring Data JPAYour Code

Collection<DTO>c=em.createQuery("SELECTnewDTO(a1,…)"+"FROMEnt").getResultList();

ResultSetrs=c.prepareStatement("SELECTa1,…"+"FROMtbl").executeQuery();

SELECTa1,…FROMtbl

List: Some Attributes

DatabaseJDBCJPA

Spring Data JPAYour Code

Collection<DTO>c=em.createQuery("SELECTnewDTO(a1,…)"+"FROMEnt").getResultList();

ResultSetrs=c.prepareStatement("SELECTa1,…"+"FROMtbl").executeQuery();

SELECTa1,…FROMtbl

List: Some Attributes

Or: LAZY attributes

DatabaseJDBCJPA

Spring Data JPAYour Code

Collection<DTO>c=em.createQuery("SELECTnewDTO(a1,…)"+"FROMEnt").getResultList();

ResultSetrs=c.prepareStatement("SELECTa1,…"+"FROMtbl").executeQuery();

SELECTa1,…FROMtbl

List: Some Attributes

Or: LAZY attributes

<P>Collection<P>findAllProjectedBy(Class<P>p);

DatabaseJDBCJPA

Spring Data JPAYour Code

Collection<DTO>c=em.createQuery("SELECTnewDTO(a1,…)"+"FROMEnt").getResultList();

ResultSetrs=c.prepareStatement("SELECTa1,…"+"FROMtbl").executeQuery();

SELECTa1,…FROMtbl

List: Some Attributes

Or: LAZY attributes

<P>Collection<P>findAllProjectedBy(Class<P>p);

publicinterfaceProj{…getA1();…}

DatabaseJDBCJPA

Spring Data JPAYour Code

Collection<DTO>c=em.createQuery("SELECTnewDTO(a1,…)"+"FROMEnt").getResultList();

ResultSetrs=c.prepareStatement("SELECTa1,…"+"FROMtbl").executeQuery();

SELECTa1,…FROMtbl

List: Some Attributes

Or: LAZY attributes

<P>Collection<P>findAllProjectedBy(Class<P>p);Collection<Proj>c=r.findAllProjectedBy(Proj.class);

publicinterfaceProj{…getA1();…}

DatabaseJDBCJPA

Spring Data JPAYour Code

List: Attributes of Multiple Objects

DatabaseJDBCJPA

Spring Data JPAYour Code

SELECTa.a1,b.a1,…FROMtblaJOINtbl2bON…

List: Attributes of Multiple Objects

DatabaseJDBCJPA

Spring Data JPAYour Code

Collection<DTO>c=em.createQuery("SELECT"+"newDTO(a.a1,b.a1,…)"+"FROMEntityaJOINa.childb").getResultList();

SELECTa.a1,b.a1,…FROMtblaJOINtbl2bON…

List: Attributes of Multiple Objects

DatabaseJDBCJPA

Spring Data JPAYour Code

Collection<DTO>c=em.createQuery("SELECT"+"newDTO(a.a1,b.a1,…)"+"FROMEntityaJOINa.childb").getResultList();

SELECTa.a1,b.a1,…FROMtblaJOINtbl2bON…

List: Attributes of Multiple Objects

<P>Collection<P>findAllProjectedBy(Class<P>p);Collection<Proj>c=r.findAllProjectedBy(Proj.class);

DatabaseJDBCJPA

Spring Data JPAYour Code

Collection<DTO>c=em.createQuery("SELECT"+"newDTO(a.a1,b.a1,…)"+"FROMEntityaJOINa.childb").getResultList();

SELECTa.a1,b.a1,…FROMtblaJOINtbl2bON…

List: Attributes of Multiple Objects

<P>Collection<P>findAllProjectedBy(Class<P>p);Collection<Proj>c=r.findAllProjectedBy(Proj.class);

publicinterfaceProj{…getA1();Proj2getB();}

DatabaseJDBCJPA

Spring Data JPAYour Code

Collection<DTO>c=em.createQuery("SELECT"+"newDTO(a.a1,b.a1,…)"+"FROMEntityaJOINa.childb").getResultList();

SELECTa.a1,b.a1,…FROMtblaJOINtbl2bON…

List: Attributes of Multiple Objects

<P>Collection<P>findAllProjectedBy(Class<P>p);Collection<Proj>c=r.findAllProjectedBy(Proj.class);

publicinterfaceProj{…getA1();Proj2getB();}

Still selects all columns

DATAJPA-1218

DatabaseJDBCJPA

Spring Data JPAYour Code

Collection<DTO>c=em.createQuery("SELECT"+"newDTO(a.a1,b.a1,…)"+"FROMEntityaJOINa.childb").getResultList();

SELECTa.a1,b.a1,…FROMtblaJOINtbl2bON…

List: Attributes of Multiple Objects

@Query("SELECT"+"newDTO(a.a1,b.a1,…)"+"FROMEntityaJOINa.childb")Collection<DTO>findAllDtoProj();Collection<DTO>c=r.findAllDtoProj();

publicinterfaceProj{…getA1();Proj2getB();}

Still selects all columns

DATAJPA-1218

DatabaseJDBCJPA

Spring Data JPAYour Code

Collection<DTO>c=em.createQuery("SELECT"+"newDTO(a.a1,b.a1,…)"+"FROMEntityaJOINa.childb").getResultList();

SELECTa.a1,b.a1,…FROMtblaJOINtbl2bON…

List: Attributes of Multiple Objects

@Query("SELECT"+"newDTO(a.a1,b.a1,…)"+"FROMEntityaJOINa.childb")Collection<DTO>findAllDtoProj();Collection<DTO>c=r.findAllDtoProj();

publicinterfaceProj{…getA1();Proj2getB();}

Still selects all columns

DATAJPA-1218

Consider Blaze Persistence

Entity Views

DatabaseJDBCJPA

Spring Data JPAYour Code

List: Derived Data

DatabaseJDBCJPA

Spring Data JPAYour Code

SELECTa.a1,SUM(b.a1)FROMtblaJOINtbl2bGROUPBYa.a1

List: Derived Data

DatabaseJDBCJPA

Spring Data JPAYour Code Collection<DTO>c=

em.createQuery("SELECT"+"newDTO(a.a1,SUM(b.a1))"+"FROMEntityaJOINa.childb"+"GROUPBYa").getResultList();

SELECTa.a1,SUM(b.a1)FROMtblaJOINtbl2bGROUPBYa.a1

List: Derived Data

DatabaseJDBCJPA

Spring Data JPAYour Code Collection<DTO>c=

em.createQuery("SELECT"+"newDTO(a.a1,SUM(b.a1))"+"FROMEntityaJOINa.childb"+"GROUPBYa").getResultList();

SELECTa.a1,SUM(b.a1)FROMtblaJOINtbl2bGROUPBYa.a1

List: Derived Data@Query("SELECT"+"newDTO(a.a1,SUM(b.a1))"+"FROMEntityaJOINa.childb"+"GROUPBYa")Collection<DTO>findAllDtoProj();Collection<DTO>c=r.findAllDtoProj();

DatabaseJDBCJPA

Spring Data JPAYour Code

SELECTa.a1,SUM(b.a1),SUM(CASEWHENb.a2=1THENb.a1ELSE0END)FROMtblaJOINtbl2bGROUPBYa.a1

List: Derived Data

DatabaseJDBCJPA

Spring Data JPAYour Code

SELECTa.a1,SUM(b.a1),SUM(CASEWHENb.a2=1THENb.a1ELSE0END)FROMtblaJOINtbl2bGROUPBYa.a1

List: Derived Data

More beautifully, but rarely supported: SELECTa.a1,SUM(b.a1),SUM(b.a1)FILTER(WHEREb.a2=1)FROMtblaJOINtbl2bGROUPBYa.a1

DatabaseJDBCJPA

Spring Data JPAYour Code

SELECTa.a1,SUM(b.a1),SUM(CASEWHENb.a2=1THENb.a1ELSE0END)FROMtblaJOINtbl2bGROUPBYa.a1

List: Derived Data

More beautifully, but rarely supported: SELECTa.a1,SUM(b.a1),SUM(b.a1)FILTER(WHEREb.a2=1)FROMtblaJOINtbl2bGROUPBYa.a1

1999

2001

2003

2005

2007

2009

2011

2013

2015

2017

2019

5.1 MariaDBMySQL

9.4 PostgreSQL1.0 3.30 SQLite

DB2 LUWOracleSQL Server

DatabaseJDBCJPA

Spring Data JPAYour Code

SELECTa.a1,SUM(b.a1),SUM(CASEWHENb.a2=1THENb.a1ELSE0END)FROMtblaJOINtbl2bGROUPBYa.a1

List: Derived Data

JPQL doesn't allow CASE in aggregates

More beautifully, but rarely supported: SELECTa.a1,SUM(b.a1),SUM(b.a1)FILTER(WHEREb.a2=1)FROMtblaJOINtbl2bGROUPBYa.a1

1999

2001

2003

2005

2007

2009

2011

2013

2015

2017

2019

5.1 MariaDBMySQL

9.4 PostgreSQL1.0 3.30 SQLite

DB2 LUWOracleSQL Server

DatabaseJDBCJPA

Spring Data JPAYour Code

SELECTa.a1,SUM(b.a1),SUM(CASEWHENb.a2=1THENb.a1ELSE0END)FROMtblaJOINtbl2bGROUPBYa.a1

List: Derived Data

JPQL doesn't allow CASE in aggregates

DatabaseJDBCJPA

Spring Data JPAYour Code

SELECTa.a1,SUM(b.a1),SUM(CASEWHENb.a2=1THENb.a1ELSE0END)FROMtblaJOINtbl2bGROUPBYa.a1

List: Derived Data@NamedNativeQuery(name="Entity.findAllXy",query="<<SQL>>",resultSetMapping="…")@SqlResultSetMapping(…)publicclassEntity{…}

JPQL doesn't allow CASE in aggregates

DatabaseJDBCJPA

Spring Data JPAYour Code

SELECTa.a1,SUM(b.a1),SUM(CASEWHENb.a2=1THENb.a1ELSE0END)FROMtblaJOINtbl2bGROUPBYa.a1

List: Derived Data@NamedNativeQuery(name="Entity.findAllXy",query="<<SQL>>",resultSetMapping="…")@SqlResultSetMapping(…)publicclassEntity{…}

Collection<DTO>c=em.createNamedQuery("Entity.findAllXy").getResultList();

JPQL doesn't allow CASE in aggregates

DatabaseJDBCJPA

Spring Data JPAYour Code

SELECTa.a1,SUM(b.a1),SUM(CASEWHENb.a2=1THENb.a1ELSE0END)FROMtblaJOINtbl2bGROUPBYa.a1

List: Derived Data@NamedNativeQuery(name="Entity.findAllXy",query="<<SQL>>",resultSetMapping="…")@SqlResultSetMapping(…)publicclassEntity{…}

Collection<DTO>c=em.createNamedQuery("Entity.findAllXy").getResultList();

@Query(native=true)Collection<DTO>findAllXy();

JPQL doesn't allow CASE in aggregates

DatabaseJDBCJPA

Spring Data JPAYour Code

SELECTa.a1,SUM(b.a1),SUM(CASEWHENb.a2=1THENb.a1ELSE0END)FROMtblaJOINtbl2bGROUPBYa.a1

List: Derived Data

JPQL doesn't allow CASE in aggregates

DatabaseJDBCJPA

Spring Data JPAYour Code

SELECTa.a1,SUM(b.a1),SUM(CASEWHENb.a2=1THENb.a1ELSE0END)FROMtblaJOINtbl2bGROUPBYa.a1

List: Derived Data

JPQL doesn't allow CASE in aggregates

Blaze Persistence Entity Views &

JPQL.next

@EntityView(Entity.class)interfaceProj{IntegergetA1();

@Mapping("SUM(b.a1)")IntegergetSum1();

@Mapping("SUM(b.a1)FILTER(WHEREa2=1)")IntegergetSum2();}

Application

Application

Application

Application ORMs are super useful for the Load-Change-Store

cycle on complexentity graphs.

Application ORMs are super useful for the Load-Change-Store

cycle on complexentity graphs.

If the cycle is broken,entities might not be the right level of abstraction.

Pattern #2: Search

Pattern #2: Search

DatabaseJDBCJPA

Spring Data JPAYour Code

SELECT*FROMtbla<<supercomplexquery>>

Search: Load Entity from Native Query

DatabaseJDBCJPA

Spring Data JPAYour Code

SELECT*FROMtbla<<supercomplexquery>>

Search: Load Entity from Native Query

@NamedNativeQuery(name="Entity.findSpecialOnes",query="<<SQL>>",resultSetMapping="…")@SqlResultSetMapping(@entities=@EntityResult(entityClass=Entity.class))publicclassEntity{…}

DatabaseJDBCJPA

Spring Data JPAYour Code

SELECT*FROMtbla<<supercomplexquery>>

Search: Load Entity from Native Query

@NamedNativeQuery(name="Entity.findSpecialOnes",query="<<SQL>>",resultSetMapping="…")@SqlResultSetMapping(@entities=@EntityResult(entityClass=Entity.class))publicclassEntity{…}

@Query(native=true)Collection<Entity>findSpecialOnes();

CREATETABLEt(idINTEGER,parentINTEGER,)

CREATETABLEt(idINTEGER,parentINTEGER,)

CREATETABLEt(idINTEGER,parentINTEGER,)

CREATETABLEt(idINTEGER,parentINTEGER,)

publicvoiddescendTree(Entitystart){for(Entitye:start.getChildren()){descendTree(e);}}

publicvoiddescendTree(Entitystart){for(Entitye:start.getChildren()){descendTree(e);}}

publicvoiddescendTree(Entitystart){for(Entitye:start.getChildren()){descendTree(e);}}

SELECT...FROMEntityWHEREparent=?

publicvoiddescendTree(Entitystart){for(Entitye:start.getChildren()){descendTree(e);}}

SELECT...FROMEntityWHEREparent=?

publicvoiddescendTree(Entitystart){for(Entitye:start.getChildren()){descendTree(e);}}

SELECT...FROMEntityWHEREparent=?

publicvoiddescendTree(Entitystart){for(Entitye:start.getChildren()){descendTree(e);}}

SELECT...FROMEntityWHEREparent=?

publicvoidascendTree(Entitye){while(e!=null){e=e.getParent();}}

publicvoiddescendTree(Entitystart){for(Entitye:start.getChildren()){descendTree(e);}}

SELECT...FROMEntityWHEREparent=?

publicvoidascendTree(Entitye){while(e!=null){e=e.getParent();}}

SELECT...FROMEntityWHEREid=?

SELECTt.id,t.parentFROMtWHEREt.id=?

SELECTt.id,t.parentFROMtWHEREt.id=?UNIONALLSELECTt.id,t.parentFROMtWHEREt.parent=?

SELECTt.id,t.parentFROMtWHEREt.id=?UNIONALLSELECTt.id,t.parentFROMtWHEREt.parent=?

SELECTt.id,t.parentFROMtWHEREt.id=?UNIONALLSELECTt.id,t.parentFROMtWHEREt.parent=?

WITHRECURSIVEprev(id,parent)AS(

)

SELECTt.id,t.parentFROMtWHEREt.id=?UNIONALLSELECTt.id,t.parentFROMtJOINprevONt.parent=prev.id

SELECT*FROMprev

WITHRECURSIVEprev(id,parent)AS(

)

SELECTt.id,t.parentFROMtWHEREt.id=?UNIONALLSELECTt.id,t.parentFROMtJOINprevONt.parent=prev.id

SELECT*FROMprev

WITHRECURSIVEprev(id,parent)AS(

)

SELECTt.id,t.parentFROMtWHEREt.id=?UNIONALLSELECTt.id,t.parentFROMtJOINprevONprev.parent=t.id

SELECT*FROMprev

Vendor Dialect

Vendor DialectStandard SQL (ISO 9075)

Vendor DialectStandard SQL (ISO 9075)

HQL

Vendor DialectStandard SQL (ISO 9075)

HQLJPQL

Vendor DialectStandard SQL (ISO 9075)

HQLJPQL

Spring .findBy…

Vendor DialectStandard SQL (ISO 9075)

HQLJPQL

Spring .findBy…

1999

2001

2003

2005

2007

2009

2011

2013

2015

2017

2019

5.1 10.2 MariaDB8.0 MySQL

8.4 PostgreSQL1.0 3.8.3 SQLite

7.0 DB2 LUW11gR2 Oracle

2005 SQL Server

* without keyword recursive

withrecursive

**

*

JVM

JVM

JVM

publicvoidascendTree(Entitye){while(e!=null){e=e.getParent();}}

JVM

publicvoidascendTree(Entitye){while(e!=null){e=e.getParent();}}

JVM

publicvoidascendTree(Entitye){while(e!=null){e=e.getParent();}}

JVM

publicvoidascendTree(Entitye){while(e!=null){e=e.getParent();}}

PersistenceContext

JVM

publicvoidascendTree(Entitye){while(e!=null){e=e.getParent();}}

PersistenceContext

JVM

publicvoidascendTree(Entitye){while(e!=null){e=e.getParent();}}

PersistenceContext

JVM

publicvoidascendTree(Entitye){while(e!=null){e=e.getParent();}}

PersistenceContext

What if I run the recursive query

What if I run the recursive query

What if I run the recursive query

before my JPA logic?

JVM

PersistenceContext

JVM

PersistenceContext

@NamedNativeQuery(name="Entity.findSpecialOnes",query="<<SQL>>",resultSetMapping="…")@SqlResultSetMapping(@entities=@EntityResult(entityClass=Entity.class))publicclassEntity{…}

JVM

PersistenceContext

findSpecialOnes();//WarmUp

JVM

PersistenceContext

findSpecialOnes();//WarmUp

JVM

PersistenceContext

findSpecialOnes();//WarmUp

JVM

publicvoidascendTree(Entitye){while(e!=null){e=e.getParent();}}

PersistenceContext

findSpecialOnes();//WarmUp

JVM

PersistenceContext

JVM

PersistenceContext

@NamedNativeQuery(name="Entity.findSpecialOnes",query="<<SQL>>",resultSetMapping="…")@SqlResultSetMapping(@entities=@EntityResult(entityClass=Entity.class))publicclassEntity{…}

JVM

PersistenceContext

findSpecialOnes();//WarmUp

JVM

PersistenceContext

findSpecialOnes();//WarmUp

JVM

PersistenceContext

findSpecialOnes();//WarmUp

JVM

PersistenceContext

findSpecialOnes();//WarmUp

publicvoiddescendTree(Entitys){for(Entitye:s.getChildren()){descendTree(e);}}

JVM

PersistenceContext

findSpecialOnes();//WarmUp

publicvoiddescendTree(Entitys){for(Entitye:s.getChildren()){descendTree(e);}}

SELECT...FROMEntityWHEREparent=?

JVM

PersistenceContext

findSpecialOnes();//WarmUp

publicvoiddescendTree(Entitys){for(Entitye:s.getChildren()){descendTree(e);}}

SELECT...FROMEntityWHEREparent=?

PersistenceContext cannot be searched

by PARENT *

* Possible Solution: EclipseLink @CacheIndex

JVM

PersistenceContext

findSpecialOnes();//WarmUp

publicvoiddescendTree(Entitys){for(Entitye:s.getChildren()){descendTree(e);}}

SELECT...FROMEntityWHEREparent=?

PersistenceContext cannot be searched

by PARENT *

* Possible Solution: EclipseLink @CacheIndex

Pre-Load via Modern SQL

1.

2.

Ineffective if Java code doesn’t access via @Id. (EclipseLink @CacheIndex?)

@NativeQueries flush the PersistenceContext

Limitations

1.2.3.

BlazePersistence

jOOQ.org

(myBatis, QueryDSL)

Helpful Tools

A lot has happened

since SQL-92

SQL has evolved

beyond the relational idea

A lot has happened

since SQL-92

SQL has evolved

beyond the relational idea

If you use SQL for CRUD operations only, you are doing it wrong

A lot has happened

since SQL-92

SQL has evolved

beyond the relational idea

If you use SQL for CRUD operations only, you are doing it wrong

A lot has happened

since SQL-92

https://modern-sql.com @ModernSQL by @MarkusWinand

Recommended