Post on 11-May-2015
description
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 1
© Copyright 2011, Software Alchemy
Overview of JPA v2.0(Java Persistence API)
Bryan BashamSoftware Alchemy
basham47@gmail.com
http://www.linkedin.com/in/SoftwareAlchemist
Containers &Deployment
QueryLanguage
EntityOperations
Entities
In Practice
Overviewof JPA v2.0
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 2
© Copyright 2011, Software Alchemy
History
● Java v1.1 (1997) included JDBC● J2EE v1.2 (1999) introduced EJB Entity beans● Entity beans sucked, so others did it better
– iBATIS (2001)– Hibernate (2001)– JDO (JSR 12, final in 2002)
● JPA v1.0 (JSR 220) was released in 2006● JPA v2.0 (JSR 317) was released in 2009
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 3
© Copyright 2011, Software Alchemy
Who Needs a Standard?
● JPA provides a flexible standard● Multiple, competing implementations
– DataNucleus – EclipseLink – Hibernate – ObjectDB – OpenJPA
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 4
© Copyright 2011, Software Alchemy
Typical Architecture #1
The Java Virtual Machine
Java Lang / JRE JDK
JPA
EclipseLink OpenJPA
Your Standalone Application
Spring(optional)
Hibernate(plus optional libs)
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 5
© Copyright 2011, Software Alchemy
Typical Architecture #2
The Java Virtual Machine
Java Lang / JRE JDK
JPA
Your Enterprise Application
Spring(optional)
Hibernate(plus optional libs)
Java EE(servlets, JSP, JSF, EJB, JNDI, etc.)
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 6
© Copyright 2011, Software Alchemy
Entities
Containers &Deployment
QueryLanguage
EntityOperationsIn Practice
Overviewof JPA v2.0
RelationshipsKeys
Beans &Properties
Inheritance
DB MappingsEntities
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 7
© Copyright 2011, Software Alchemy
Entity Classes
● Any POJO, but should be a Java Bean● Class must not be final; nor methods or
persistence instance variables● May be Serializable and be passed across
remote calls, such as RMI● Entities may exist in a class hierarchy● Queries may be polymorphic
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 8
© Copyright 2011, Software Alchemy
Entity Classes: Example
import javax.persistence.Basic;import javax.persistence.Entity;
@Entity /** Not fully baked */public class Employee {
@Basic(optional=false) private String firstName; @Basic(optional=false) private String lastName; @Basic(optional=false) private Integer age;
public String getFirstName() { return firstName; } public void setFirstName(String name) { this.firstName = name; }
public String getLastName() { return lastName; } public void setLastName(String name) { this.lastName = name; }
public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; }
}
«entity»Employee
firstName : StringlastName : Stringage : Integer
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 9
© Copyright 2011, Software Alchemy
Access Types
● Access to DB fields can be on instance variables or properties
● You can specific the access type with an annotation:
@Entity@Access(AccessType.PROPERTY)public class Employee { /* entity code */ }
● If no access type is defined, then the default type (by usage) applies to the whole entity class hierarchy
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 10
© Copyright 2011, Software Alchemy
Entity Classes: Example #2
// assume all necessary imports from now on
@Entity@Access(AccessType.PROPERTY)public class Employee {
private String _firstName; private String _lastName; private Integer _age;
@Basic(optional=false) public String getFirstName() { return _firstName; } public void setFirstName(String name) { this._firstName = name; }
@Basic(optional=false) public String getLastName() { return _lastName; } public void setLastName(String name) { this._lastName = name; }
@Basic(optional=false) public Integer getAge() { return _age; } public void setAge(Integer age) { this._age = age; }
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 11
© Copyright 2011, Software Alchemy
Data Types
● A property data type can be:– any Java primitive– any Java primitive wrapper– Strings– Dates– Big integer and decimals– Byte arrays (for BLOBs)– Character arrays (for CLOBs)– Enum values
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 12
© Copyright 2011, Software Alchemy
Enum Types
@Entitypublic class Employee {
public enum Gender { MALE, FEMALE }
@Basic(optional = false) private Gender gender;
@Basic(optional=false) private String firstName;
@Basic(optional=false) private String lastName;
@Basic(optional=false) private Integer age;
«entity»Employee
gender : GenderfirstName : StringlastName : Stringage : Integer
«enumeratedType»Gender
+MALE+FEMALE
Enum ordinal
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 13
© Copyright 2011, Software Alchemy
Derived Properties
@Entitypublic class Employee {
@Basic(optional=false) private String firstName;
@Basic(optional=false) private String lastName;
@Basic(optional=false) private Date dateOfBirth;
@Transient private Integer age;
public Integer getAge() { if ( this.age == null ) { this.age = DateUtils.dateDiffYears(new Date(), this.dateOfBirth); } return age; }
«entity»Employee
firstName : StringlastName : StringdateOfBirth : Date#age : Integer
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 14
© Copyright 2011, Software Alchemy
Embeddable Properties
● Useful for representing small, non-entity classes
● Thus supports DDD Value Object concepts (well, almost)
● Also supports Composition without the need for cascading deletes (fields are embedded within the owning entity table)
● One Embeddable can embed other Embeddables
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 15
© Copyright 2011, Software Alchemy
Embeddable Properties (2)
@Embeddablepublic class PhoneNumber {
@Basic(optional=false) private String areaCode; // unfortunately, can't make these final @Basic(optional=false) private String localNumber; @Basic(optional=true) private String extension;
public PhoneNumber() { /* no-arg ctor for JPA */ } public PhoneNumber(String areaCode, String localNumber, String extension) { this.areaCode = areaCode; this.localNumber = localNumber; this.extension = extension; }
public String getAreaCode() { return areaCode; } public String getLocalNumber() { return localNumber; } public String getExtension() { return extension; }}
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 16
© Copyright 2011, Software Alchemy
Embeddable Properties (3)
«entity»Employee
firstName : StringlastName : StringdateOfBirth : Date#age : IntegerofficePhone : PhoneNumber
«valueObject»PhoneNumber
areaCode : StringlocalNumber : Stringextension : String
officePhone
1
@Entitypublic class Employee {
@Embedded private PhoneNumber officePhone;
Fields of the Embeddableare embedded directly intothe table of the owning Entity.
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 17
© Copyright 2011, Software Alchemy
Embeddable Properties (4)
@Entitypublic class Employee {
@Embedded @ElementCollection(fetch = FetchType.LAZY) private Map<String,PhoneNumber> phones = new HashMap<String,PhoneNumber>();
Due to the one-to-manythe embeddables are storedin a separate table.
«entity»Employee
firstName : StringlastName : StringdateOfBirth : Date#age : Integerphones : Map<String, PhoneNumber>
«valueObject»PhoneNumber
areaCode : StringlocalNumber : Stringextension : String
1type
Entity FK Map key
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 18
© Copyright 2011, Software Alchemy
Entity Keys
● Every entity must have a primary key● Key is specified with the @Id annotation● Only one key defined for a given entity class
hierarchy● Keys can be simple or composite● Simple key (or properties of a composite key)
must have a simple data type:– Strings, Java primitives (or wrappers), dates, or
big numbers
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 19
© Copyright 2011, Software Alchemy
Entity Keys: Example
@Entitypublic class Employee {
@Id @Basic(optional=false) // SSN must be unique (not a good choice) private String SSN;
@Basic(optional=false) private String firstName;
@Basic(optional=false) private String lastName;
@Basic(optional=false) private Date dateOfBirth;
@Transient private Integer age;
«entity»Employee
SSN : StringfirstName : StringlastName : StringdateOfBirth : Date#age : Integer
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 20
© Copyright 2011, Software Alchemy
Entity Keys: Example #2
@Entitypublic class Employee {
@Id @GeneratedValue // let the DBMS assign the key on insert private Long id;
@Basic(optional=false) private String firstName;
@Basic(optional=false) private String lastName;
@Basic(optional=false) private Date dateOfBirth;
@Transient private Integer age;
«entity»Employee
id : LongfirstName : StringlastName : StringdateOfBirth : Date#age : Integer
MySQL uses autoincrementfor key generation.
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 21
© Copyright 2011, Software Alchemy
Associations
● Entities can be associated to other Entities and Embeddable objects
● Collections (bags), sets, sorted sets, lists, and even maps
● One-to-one, one-to-many, many-to-one, and many-to-many
● Uni- and bi-directional relationships● Lazy and Eager fetching techniques
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 22
© Copyright 2011, Software Alchemy
One-to-One
@Entitypublic class User {
@Id @GeneratedValue private Long id; @Basic(optional=false) private String userName; @Basic(optional=false) private String password;
@Basic(optional=false) @OneToOne(fetch=FetchType.EAGER) private Employee employee;
employee
1«entity»User
id : LonguserName : Stringpassword : Stringemployee : Employee
1 «entity»Employee
id : LongfirstName : StringlastName : StringdateOfBirth : Date#age : Integer
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 23
© Copyright 2011, Software Alchemy
One-to-One (2)
private void createExampleUser() { Calendar cal = Calendar.getInstance(); try { em.getTransaction().begin();
Employee emp = new Employee(); emp.setGender(Gender.MALE); emp.setFirstName("Bryan"); emp.setLastName("Basham"); cal.set(1964, 7, 22); emp.setDateOfBirth(cal.getTime()); em.persist(emp); // NOTE: need to persist all entities User u1 = new User(); u1.setUserName("bbasham"); u1.setPassword("guess"); u1.setEmployee(emp); em.persist(u1);
em.getTransaction().commit(); } catch (Exception e) { e.printStackTrace(); em.getTransaction().rollback(); }}
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 24
© Copyright 2011, Software Alchemy
One-to-Many
@Entitypublic class Department {
@Id @GeneratedValue private Long id;
@Basic(optional = false) private String name;
@OneToMany(fetch = FetchType.LAZY) private Set<Employee> staff;
staff
0..*«entity»Department
id : Longname : Stringstaff : Set<Employee>
1 «entity»Employee
id : LongfirstName : StringlastName : StringdateOfBirth : Date#age : Integer
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 25
© Copyright 2011, Software Alchemy
Many-to-Many
team
0..*«entity»Project
id : Longname : Stringteam : Set<Employee>
0..* «entity»Employee
id : LongfirstName : StringlastName : StringdateOfBirth : Date#age : Integerprojects : Set<Project>
projects
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 26
© Copyright 2011, Software Alchemy
Many-to-Many (2)
@Entitypublic class Employee {
@Id @GeneratedValue private Long id;
// Skipping basic properties
@ManyToMany(fetch = FetchType.LAZY, mappedTo=”team”) private Set<Project> projects;
@Entitypublic class Project {
@Id @GeneratedValue private Long id;
@Basic(optional = false) private String name;
@ManyToMany(fetch = FetchType.LAZY) private Set<Employee> team;
The mappedTo valuespecifies that the Project entityis the “owner” of the relationship.
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 27
© Copyright 2011, Software Alchemy
Many-to-Many (3)
Project FK Employee FK
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 28
© Copyright 2011, Software Alchemy
Inheritance
● JPA supports flexible Entity inheritance● A Entity may be an abstract class● An Entity class can extend a non-Entity class● A non-Entity class can extend an Entity class● Queries can be written to any Entity classes● Three DB mapping strategies:
– SINGLE_TABLE (the default)– JOINED – TABLE_PER_CLASS (not required per spec)
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 29
© Copyright 2011, Software Alchemy
Inheritance Example
team11
team21
«entity»Team
game1
1
game2
1
«entity»IntermediateGame
game1 : AbstractGamegame2 : AbstractGame
«entity»StartingTeam
team1 : Teamteam2 : Team
«entity»AbstractGame
id : Longteam1Score : intteam2Score : int
getTeam1() : TeamgetTeam2() : TeamgetWinner() : Team
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 30
© Copyright 2011, Software Alchemy
Single Table Example
@Entity@Inheritance(strategy=InheritanceType.SINGLE_TABLE)@DiscriminatorColumn( name="game_type" )public abstract class AbstractGame { @Id @GeneratedValue private Long id; @Basic(optional=false) private Integer team1Score; @Basic(optional=false) private Integer team2Score;
@Entity@DiscriminatorValue("SG")public class StartingGame extends AbstractGame { @Basic(optional=false) private Team team1; @Basic(optional=false) private Team team2;
@Entity@DiscriminatorValue("IG")public class IntermediateGame extends AbstractGame { @Basic(optional=false) private AbstractGame game1; @Basic(optional=false) private AbstractGame game2;
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 31
© Copyright 2011, Software Alchemy
Single Table Example (2)AbstractGame IntermediateGame
discriminatorfield
StartingGame
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 32
© Copyright 2011, Software Alchemy
Joined Example
@Entity@Inheritance(strategy=InheritanceType.JOINED)public abstract class AbstractGame { @Id @GeneratedValue private Long id; @Basic(optional=false) private Integer team1Score; @Basic(optional=false) private Integer team2Score;
@Entitypublic class StartingGame extends AbstractGame { @Basic(optional=false) private Team team1; @Basic(optional=false) private Team team2;
@Entitypublic class IntermediateGame extends AbstractGame { @Basic(optional=false) private AbstractGame game1; @Basic(optional=false) private AbstractGame game2;
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 33
© Copyright 2011, Software Alchemy
Joined Example (2)IntermediateGame
StartingGame
AbstractGame
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 34
© Copyright 2011, Software Alchemy
Database Mappings
● JPA implementations like Hibernate can dynamically create a DB schema for RAD
● But if you have an existing schema, then you can use annotations to map:
– Entity classes to tables– Entity properties to fields– Join columns of relationships– ...and more
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 35
© Copyright 2011, Software Alchemy
Domain Model Example
«entity»Employee
firstName : StringlastName : StringdateOfBirth : Date#age : Integerphones : Map<>projects : Set<Project>user : Userdepartment : Department
«valueObject»PhoneNumber
areaCode : StringlocalNumber : Stringextension : String
1type
team0..*
«entity»Project
id : Longname : Stringteam : Set<Employee>
0..* projects
staff0..*
«entity»Department
id : Longname : Stringstaff : Set<Employee>
employee
1«entity»User
id : LonguserName : Stringpassword : Stringemployee : Employee
1
department1
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 36
© Copyright 2011, Software Alchemy
ER Diagram«table»USR
SID : BIGINT(20)NAME : VARCHAR(32)PW : VARCHAR(16)EMP_SID : NUMBER(20)
«table»DEPT
SID : BIGINT(20)NAME : VARCHAR(64)
«table»EMP
SID : BIGINT(20)FNAME : VARCHAR(100)LNAME : VARCHAR(100)DOB : DATETIMEGEN_CODE : VARCHAR(6)
«table»PRJ
SID : BIGINT(20)NAME : VARCHAR(64)
«table»PRJ_EMP
PRJ_SID : BIGINT(20)EMP_SID : BIGINT(20)
«table»EMP_PHONE
EMP_SID : BIGINT(20)TYPE : VARCHAR(7)AREA_CODE : CHAR(3)NUMBER : CHAR(4)EXT : CHAR(3)
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 37
© Copyright 2011, Software Alchemy
Basic DB Mappings
@Entity@Table(name="EMP")public class Employee {
@Id @GeneratedValue @Column(name="SID") private Long id;
@Basic(optional = false) @Column(name="GEN_CODE", length=6) @Enumerated(value=EnumType.STRING) private Gender gender;
@Basic(optional=false) @Column(name="FNAME", length=100) private String firstName;
@Basic(optional=false) @Column(name="LNAME", length=100) private String lastName;
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 38
© Copyright 2011, Software Alchemy
Relationship Mappings
@Entity@Table(name="USR")public class User {
@Id @GeneratedValue @Column(name="SID") private Long id
@Basic(optional = false) @Column(name="NAME", length=32, unique=true) private String userName;
@Basic(optional = false) @Column(name="PW", length=16) private String password;
@Basic(optional = false) @OneToOne(fetch = FetchType.EAGER, cascade={CascadeType.ALL}) @JoinColumn(name="EMP_SID") private Employee employee;
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 39
© Copyright 2011, Software Alchemy
Relationship Mappings (2)
@Entity@Table(name = "PRJ")public class Project {
@Id @GeneratedValue @Column(name = "SID") private Long id;
@Basic(optional = false) @Column(name = "NAME", length=64) private String name;
@ManyToMany(fetch = FetchType.EAGER) @JoinTable(name = "PRJ_EMP", joinColumns = { @JoinColumn(name = "PRJ_SID", referencedColumnName = "SID") }, inverseJoinColumns = { @JoinColumn(name = "EMP_SID", referencedColumnName = "SID") }) private Set<Employee> team = new HashSet<Employee>();
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 40
© Copyright 2011, Software Alchemy
Embeddable Mappings
@Entity@Table(name="EMP")public class Employee { @Embedded @ElementCollection(fetch = FetchType.LAZY) @CollectionTable(name="EMP_PHONE", joinColumns={ @JoinColumn(name="EMP_SID", referencedColumnName="SID") }) @MapKeyColumn(name="PHONE_TYPE") private Map<String, PhoneNumber> phones = new HashMap<String, PhoneNumber>();
@Embeddablepublic class PhoneNumber { @Column(name="AREA_CODE", length=3) private String areaCode; @Column(name="NUMBER", length=7) private String localNumber; @Column(name="AREA_CODE", length=3, nullable=true) private String areaCode;
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 41
© Copyright 2011, Software Alchemy
Containers &Deployment
QueryLanguage
In Practice
CRUD OpsEntityManager
Other operations
EntityOperations
RelationshipsKeys
Beans &Properties
Inheritance
DB MappingsEntities
Overviewof JPA v2.0
Entity Operations
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 42
© Copyright 2011, Software Alchemy
Entity Manager
«class»Persistence
{from javax.persistence}
createEntityManager- Factory(String puName) : EMF
META-INF/persistence.xml
....
..
.....
....
«interface»EntityManagerFactory{from javax.persistence}
createEntityManager() : EM
«interface»EntityManager
{from javax.persistence}
persist(entity:Object) : voidfind(eCls:Class<T>, key:Object) : Tmerge(entity:T) : Tremove(entity:Object)
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 43
© Copyright 2011, Software Alchemy
CRUD Operations
● Create:– Just create an Entity POJO with no id– Call em.persist(entity); JPA populates id
● Retrieve:– Employee emp = em.find(Employee.class, 47L);
● Update:– Create POJO with id; call em.merge(entity)
● Delete:– Create POJO with id; call em.remove(entity)
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 44
© Copyright 2011, Software Alchemy
Persisting Relationships
● By default, you must persist all parts by hand– Remember our example:
// Make and persist an employeeEmployee emp = new Employee(); // setters skippedem.persist(emp);// Make and persist a userUser user = new User(); // setters skippeduser.setEmployee(emp);em.persist(user);
● You can tell JPA to persist parts with many relationship annotations
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 45
© Copyright 2011, Software Alchemy
Cascading Operations@Entitypublic class User {
@Id @GeneratedValue private Long id; @Basic(optional=false) private String userName; @Basic(optional=false) private String password;
@Basic(optional=false) @OneToOne(fetch=FetchType.EAGER , cascade={CascadeType.ALL}) private Employee employee;
private void createExampleUser() { em.getTransaction().begin(); // Make an employee Employee emp = new Employee(); // setters skipped // Make a user User user = new User(); // setters skipped user.setEmployee(emp); // Persist the User and the Employee is automatically saved em.persist(user);
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 46
© Copyright 2011, Software Alchemy
Other EM Operations
● flush()
– Saves EM context state to DB● detach(entity)
– Detaches an Entity from EM context● refresh(entity)
– Refreshes the Entity state from the DB● getReference(id):T
– Retrieves a lazy Entity from the DB
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 47
© Copyright 2011, Software Alchemy
Containers &Deployment
In Practice
UPDATE &DELETE
SELECT
Joins
SELECT Clause
Expressions
QueryParameters
QueryLanguage
RelationshipsKeys
Beans &Properties
CRUD OpsEntityManager
Other operations
EntityOperations
Inheritance
DB MappingsEntities
Overviewof JPA v2.0
Query Language
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 48
© Copyright 2011, Software Alchemy
SELECT Statements
● Like SQL SELECT statements; except it selects a whole Entity object
● Examples:– SELECT e FROM Employee AS e – SELECT e FROM Employee AS e
JOIN e.projects p WHERE p.name = 'Cobia'
● Code:String statement = "SELECT e FROM Employee AS e";TypedQuery<Employee> query = em.createQuery(statement, Employee.class);List<Employee> list = query.getResultList();
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 49
© Copyright 2011, Software Alchemy
Query Parameters
● Supports JDBC-like indexed parameters:private List<Employee> queryTeam(Project project) { String statement = "SELECT e FROM Employee AS e JOIN e.projects p WHERE p.name=?"; TypedQuery<Employee> query = em.createQuery(statement, Employee.class); query.setParameter(1, project.getName()); return query.getResultList();}
● Also supports named parameters:private List<Employee> queryTeam(Project project) { String statement = "SELECT e FROM Employee AS e JOIN e.projects p WHERE p.name=:PRJ"; TypedQuery<Employee> query = em.createQuery(statement, Employee.class); query.setParameter("PRJ", project.getName()); return query.getResultList();}
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 50
© Copyright 2011, Software Alchemy
Conditional Expressions
● Literals● Functions● Basic Operators● Collection Operators● Path expressions
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 51
© Copyright 2011, Software Alchemy
Literals
● Strings: 'string' and 'string''s'● Boolean: TRUE and FALSE● Numbers: both Java and SQL literals● Dates: {d '2011-10-11'}
– This syntax is handled by the JDBC provider– The JPA provider is not required to mediate
● Enums: org.basham.TestJPA.entities.Gender.MALE – Probably best to just pass in as a parameter
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 52
© Copyright 2011, Software Alchemy
Functions
● Strings: CONCAT, SUBSTRING, TRIM, UPPER, LOWER, LENGTH, LOCATE
● Numeric: ABS, SQRT, MOD, SIZE(collection), INDEX(item in a List)
● Temporal: CURRENT_DATE, CURRENT_TIME, and CURRENT_TIMESTAMP
● CASE statement● Entity Type: TYPE(game) = StartingGame
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 53
© Copyright 2011, Software Alchemy
Basic Operators
● Comparison: <, <=, =, <>, >, >=● Arithmetic: +, -, *, /● Logical: NOT, AND, and OR● Between: x [NOT] BETWEEN y AND z● String matching: x [NOT] LIKE 'B%' ● Null check: x IS [NOT] NULL
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 54
© Copyright 2011, Software Alchemy
Collection Operators
● Fixed membership:– a [NOT] IN (x, y, z, ...)
● Empty:– collection IS [NOT] EMPTY
● Flexible membership:– entity [NOT] MEMBER [OF] collection
private List<Employee> queryTeam(Project project) { String st = "SELECT e FROM Employee e WHERE :PRJ MEMBER OF e.projects"; TypedQuery<Employee> query = em.createQuery(st, Employee.class); query.setParameter("PRJ", project); return query.getResultList();}
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 55
© Copyright 2011, Software Alchemy
Path Expressions
● Allows simple object navigation– OneToOne and ManyToOne relationships– Single Embedded properties (no collections)
● Examples:– How many Employees with short passwords?
SELECT count(e) FROM Employee e WHERE LENGTH(e.user.password) <= 4
– How many Employees with office phones in Rochester?
SELECT count(e) FROM Employee e WHERE e.officePhone.areaCode = '585'
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 56
© Copyright 2011, Software Alchemy
Joins
● Like SQL joins; natural for relationship traversal● Support for outer join● Support for so-called “FETCH JOIN” which
allows the query to specify a Lazy relationship to be pre-fetched.
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 57
© Copyright 2011, Software Alchemy
Join Examples
● Get Employees for a specific project and gender:
SELECT e FROM Employee AS e JOIN e.projects p WHERE p.name=:N AND e.gender=:SEX
● Get Projects with team members from a specific Department:
SELECT p FROM Project p JOIN p.team emp JOIN emp.department dept WHERE dept.name=:DEPT
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 58
© Copyright 2011, Software Alchemy
SELECT Clause
● Select Entity objects (most of what we've seen)– The result is an Entity object
● Select specific attributes (like SQL)– The result is an Object[] result
● Select aggregations (like SQL)– May use a GROUP BY clause
● May construct new Entities from a query● May use DISTINCT; like in SQL
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 59
© Copyright 2011, Software Alchemy
Aggregation Example
● Department stats: # of Emps and youngest age private void queryEmployeeStatsByDept(Department dept) { String statement = "SELECT COUNT(e), MAX(e.dateOfBirth) FROM Employee e JOIN e.department dept WHERE dept.name=:DEPT"; Query query = em.createQuery(statement); query.setParameter("DEPT", dept.getName()); Object[] tuple = (Object[]) query.getSingleResult(); Long numOfEmps = (Long) tuple[0]; Date minDOB = (Date) tuple[1]; System.out.println(String.format("There %d employees in the %s department with the youngest age of %d years.", numOfEmps, dept.getName(), DateUtils.dateDiffYears(new Date(), minDOB))); }
There 5 employees in the IT department with the youngest age of 20 years.
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 60
© Copyright 2011, Software Alchemy
GROUP BY Example
● List # of Emps by Department and Genderprivate void queryDepartmentStats() { String statement = "SELECT dept.name, emp.gender, COUNT(emp) FROM Employee emp JOIN emp.department dept GROUP BY dept.name, emp.gender"; Query query = em.createQuery(statement); List<Object[]> list = (List<Object[]>) query.getResultList(); System.out.println("Department stats:"); for ( Object[] tuple : list ) { String deptName = (String) tuple[0]; Gender gender = (Gender) tuple[1]; Long numOfEmps = (Long) tuple[2]; System.out.println("\t" + deptName + " & " + gender.name() + " : " + numOfEmps + " employees"); }}
Department stats: Exec & FEMALE : 1 employees Exec & MALE : 5 employees HR & FEMALE : 1 employees HR & MALE : 6 employees ... and so on ...
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 61
© Copyright 2011, Software Alchemy
UPDATE and DELETE
● JPA also allows bulk updates and deletes● Syntax:
– UPDATE Entity AS e SET e.prop1=val1, e.prop2=val2, ... WHERE e.property = ?
– DELETE FROM Entity AS e WHERE e.property = ?
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 62
© Copyright 2011, Software Alchemy
UPDATE Example
private void resetPasswordsByDept(Department dept, String newPW) { try { em.getTransaction().begin();
String statement = "UPDATE User u SET u.password=? WHERE u.employee.id IN (SELECT e.id FROM Employee e WHERE e.department=?)"; Query query = em.createQuery(statement); query.setParameter(1, newPW); query.setParameter(2, dept); int howMany = query.executeUpdate(); System.out.println(String.format("%d user's passwords reset for %s", howMany, dept));
em.getTransaction().commit(); } catch (Exception e) { e.printStackTrace(); em.getTransaction().rollback(); } }
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 63
© Copyright 2011, Software Alchemy
In Practice
Packaging PersistenceUnit
Containers &Deployment
RelationshipsKeys
Beans &Properties
CRUD OpsEntityManager
Other operations
EntityOperations
Inheritance
DB MappingsEntities
UPDATE &DELETE
SELECT
Joins
SELECT Clause
Expressions
QueryParameters
QueryLanguage
Overviewof JPA v2.0
Containers & Deployment
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 64
© Copyright 2011, Software Alchemy
Persistence Unit
● JPA's configuration– Configuration of the persistence provider, such
as Hibernate– Set of entity classes; and what to exclude– Mapping configuration; if not provided by Entity
class annotations● Lives in the persistence.xml file
– Typically in the META-INF directory of a JAR– Or in the WEB-INF/classes directory of a WAR
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 65
© Copyright 2011, Software Alchemy
Persistence Unit (2)
<?xml version="1.0" encoding="UTF-8"?><persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" version="2.0">
<persistence-unit name="unit1" transaction-type="RESOURCE_LOCAL"> <!-- details --> </persistence-unit>
<persistence-unit name="unit2" transaction-type="RESOURCE_LOCAL"> <!-- details --> </persistence-unit> </persistence>
// code...EntityManagerFactory emf = Persistence.createEntityManagerFactory("unit1");EntityManager em = emf.createEntityManager();em.persist(entity);
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 66
© Copyright 2011, Software Alchemy
Persistence Unit (3)
<persistence ...>
<persistence-unit name="unit1" transaction-type="RESOURCE_LOCAL"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <class>org.basham.TestJPA.mappings.Employee</class> <class>org.basham.TestJPA.mappings.User</class> <class>org.basham.TestJPA.mappings.Department</class> <class>org.basham.TestJPA.mappings.Project</class> <exclude-unlisted-classes /> <properties> <property name="hibernate.hbm2ddl.auto" value="create-drop" /> <property name="hibernate.show_sql" value="true" /> <property name="hibernate.cache.provider_class" value="org.hibernate.cache.HashtableCacheProvider" /> <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" /> <property name="hibernate.connection.url" value="jdbc:mysql://localhost:8889/TestJPA_mappings" /> <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver" /> <property name="hibernate.connection.password" value="root" /> <property name="hibernate.connection.username" value="root" /> </properties> </persistence-unit> </persistence>
PersistenceProvider
configuration
EntityClasses
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 67
© Copyright 2011, Software Alchemy
Packaging a Standalone App
TestJPA.jar
mysql-connector-java-5.1.5.jar
hibernate-entitymanager-3.6.7-Final.jar
hibernate-jpa-2.0-api.jar
jta-1.1.jar
JSR-305.jar
Several other JARs
META-INF/persistence.xml
....
..
.....
....
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 68
© Copyright 2011, Software Alchemy
Building a Standalone w/ Maven
● If you just build a standalone JAR for your app– You must include all of the external JARs by
hand in the classpath during execution– Plus all of their dependencies (this gets complex)
● Or you can use Maven– To manage the transitive dependencies– And build a single executable JAR
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 69
© Copyright 2011, Software Alchemy
Standalone App POM
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.basham</groupId> <artifactId>TestJPA</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging>
<repositories> <repository> <id>repository.jboss.org</id> <name>Public JBoss Repository Group</name> <url>https://repository.jboss.org/nexus/content/groups/public-jboss/</url> <layout>default</layout> </repository> </repositories>
<!-- Build configuration and plugins -->
<!-- Build dependencies -->
</project>
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 70
© Copyright 2011, Software Alchemy
Standalone App POM (2)
<project ...>
<!-- Build configuration and plugins --> <build> <plugins> <plugin> <artifactId>maven-assembly-plugin</artifactId> <configuration> <archive> <manifest> <mainClass>org.basham.TestJPA.app.Main</mainClass> </manifest> </archive> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> </configuration> </plugin> <!-- a few other typical Maven plugins --> </plugins> </build>
</project>
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 71
© Copyright 2011, Software Alchemy
Standalone App POM (3)
<project ...>
<!-- Build dependencies --> <dependencies> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager</artifactId> <version>3.6.7.Final</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.12</version> <scope>runtime</scope> </dependency> <!-- a few other dependencies --> </dependencies>
</project>
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 72
© Copyright 2011, Software Alchemy
Packing a Web App
MyWebApp.war
mysql-connector-java-5.1.5.jar
hibernate-entitymanager-3.6.7-Final.jar
WEB-INF/lib
hibernate-jpa-2.0-api.jar
jta-1.1.jar
JSR-305.jar
Several other JARs
persistence.xml
....
..
.....
....
META-INF/
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 73
© Copyright 2011, Software Alchemy
Building a Web App
● Packing in a webapp is easier because all of the external JARs are placed in WEB-INF/lib
● Again, using Maven makes this really easy
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 74
© Copyright 2011, Software Alchemy
Partialloading
Paging &Ordering
Open ViewPattern
Locking
Caching
In Practice
RelationshipsKeys
Beans &Properties
CRUD OpsEntityManager
Other operations
EntityOperations
Paging &Ordering
Inheritance
DB MappingsEntities
UPDATE &DELETE
SELECT
Joins
SELECT Clause
Expressions
QueryParameters
QueryLanguage
Packaging PersistenceUnit
Containers &Deployment
Overviewof JPA v2.0
In Practice
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 75
© Copyright 2011, Software Alchemy
Paging and Ordering
● The following example demonstrates the use of paging, searching, and ordering in a real app
● This webapp, UserMgr, uses the following stack:
– GWT and GXT (ExtJS widgets in GWT)– Spring– JPA and Spring DAO utilities– MySQL
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 76
© Copyright 2011, Software Alchemy
UserMgr: Users Table
Table filtered byUserType and Last Name
Ordered bySelected Column
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 77
© Copyright 2011, Software Alchemy
UserMgr: Users Table (2)
Table supports Paging
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 78
© Copyright 2011, Software Alchemy
UserMgr: User Query Stack
MySQL«DAO»
UserDao
«helper»JpaDaoSupport
{from org.spgfrm.orm.jpa.support}
«GWT»UserGrid
«RPC»UserRpc
«service»UserSvc
«valueObject»QueryRequest
start : intpageSize : intsortField : “String”sortDir : {ASC, DESC}
«valueObject»PagedQueryResult
totalCount : intitems : List<T>
T=UserThe UserGrid component on thebrowser sends the request for anew page of Users via the GWTRPC async service which is notshown here.
Server-side code
«create»«create»
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 79
© Copyright 2011, Software Alchemy
UserMgr: UserDaoImpl
public PagedQueryResult<User> retrieveUsers(final UserType userType, final QueryRequest requestInfo) { // Count the number of Users in this user type int totalCount = getJdbcTemplate().queryForInt( "SELECT count(*) FROM user WHERE user_type_id = ?", new Object[] { userType.getId() });
// Create the dynamic query (set the ORDER BY field) String sortField = requestInfo.getSortField(); SortDir sortDir = requestInfo.getSortDirection(); final String queryString = String.format( "SELECT u FROM User u" + " WHERE u.userType = ? and u.deleted = false " + " ORDER BY u.%s %s", // eg) " ORDER BY u.lastName ASC" sortField, sortDir.name());
// Perform the query // SEE NEXT SLIDE
return new PagedQueryResult<User>(totalCount, users); }
Order-bycriteria
Pagingresults
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 80
© Copyright 2011, Software Alchemy
UserMgr: UserDaoImpl (2)
public PagedQueryResult<User> retrieveUsers(final UserType userType, final QueryRequest requestInfo) { final String queryString = // SEE PREVIOUS SLIDE
// Perform the query List<User> users = (List<User>) getJpaTemplate().executeFind( new JpaCallback() { public Object doInJpa(EntityManager em) throws PersistenceException { Query query = em.createQuery(queryString); query.setParameter(1, userType); query.setMaxResults(requestInfo.getPageSize()); query.setFirstResult(requestInfo.getStart()); return query.getResultList(); } });
return new PagedQueryResult<User>(totalCount, users); }
Pagingcriteria
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 81
© Copyright 2011, Software Alchemy
Partial Loading
● Associations can have a FetchType of either:– LAZY : Fetch when requested (aka “lazy loaded”)
● One-to-Many● Many-to-Many
– Or EAGER : Fetch when Entity is retrieved● One-to-One● Many-to-One
● Properties can also be lazy loaded– Default is eager
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 82
© Copyright 2011, Software Alchemy
Partial Loading Poor Example
@Entity@Table(name="USR_TYP")public class UserType {
@Id @GeneratedValue @Column(name="SID") private Long id;
@Column(name="NAME", length=32, unique=true) private String name;
@OneToMany(fetch = FetchType.EAGER) private Set<User> users;
«entity»UserType
users «entity»User
1..*
type
1
What's wrong withthis relationship?
It depends...
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 83
© Copyright 2011, Software Alchemy
Partial Loading Solution
● In the situation where there could be thousands of Users per UserType:
– Remove the bi-directional association– Provide a Service tier method to query the Users
by type, possibly with paging and filtering
«entity»UserType
«entity»User
type
1
«service»UserTypeService
getUsers(Long typeId) : Set<User>// better yet use// paging & filtering
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 84
© Copyright 2011, Software Alchemy
Partial Loading Example
@Entity@Table(name="USR")public class User {
@Id @GeneratedValue @Column(name="SID") private Long id;
@Basic(optional = false) @Column(name="NAME", length=32, unique=true) private String userName;
@Basic(optional = false , fetch = FetchType.LAZY) @Column(name="PW", length=16) private String password;
@Basic(optional = false) @OneToOne(fetch = FetchType.LAZY) @JoinColumn(name="EMP_SID") private Employee employee;
Don't want to exposethe user's passwordto the GUI.
Also, the GUI rarelyneeds access to theEmployee record.
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 85
© Copyright 2011, Software Alchemy
«DAO»UserDao
«GWT»UserGrid
«RPC»UserRpc
«service»UserSvc
Typical transaction boundary
«entity»User
«create»
The User object is “managed”within a transactional boundary.Outside that boundary the entitybecomes “detached”.
«entity»User
u.getEmployee().getAge()
But outside of the txn boundaryaccess to the associatedEmployee object fails:LazyInitializationException
Partial Loading Example (2)
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 86
© Copyright 2011, Software Alchemy
Open Session in View Pattern
«DAO»UserDao
«GWT»UserGrid
«RPC»UserRpc
«service»UserSvc
Transaction boundary
«entity»User
u.getEmployee().getAge()
«filter»Open
EntityManagerInViewFilter
● One solution is to move the transaction boundary up the stack (say in Servlet filter):
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 87
© Copyright 2011, Software Alchemy
Optimistic Locking
● Assumed, but code support must be injected● The @Version annotation is used to flag an
Entity attribute as the “version attribute”– @Version long version – @Version Date versionStamp
● An OptimisticLockException is thrown when one session attempts to update the entity after another session has already done so
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 88
© Copyright 2011, Software Alchemy
Pessimistic Locking
● Can lock an individual entity:User user = em.find(User.class, 47L);em.lock(user, LockModeType.PESSIMISTIC_WRITE);// OR simply:User user = em.find(User.class, 47L, LockModeType.PESSIMISTIC_WRITE);
● Can lock all entities returned by a query:String statement = // some limited queryTypedQuery<User> query = em.createQuery(statement, User.class);query.setLockMode(LockModeType.PESSIMISTIC_READ);List<User> users = query.getResultList();
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 89
© Copyright 2011, Software Alchemy
Caching
● The JPA spec supports the use of second-level caching by the persistence provider.
● The developer can mark Entity classes to be cached by the @Cacheable annotation.
● Similarly the developer can mark an Entity class to never be cached using: @Cacheable(false)
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 90
© Copyright 2011, Software Alchemy
Caching Example
@Entity@Cacheable(true)public class Category {
@Id @GeneratedValue private Long id;
private String title;
@ManyToOne private Category parent;
@Transient private Set<Category> children = new HashSet<Category>();
children0..*
parent
0..1«entity»Category
The Category entity representsa reflexive hierarchy that rarelychanges; thus is a good candidatefor caching.
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 91
© Copyright 2011, Software Alchemy
Overviewof JPA v2.0
RelationshipsKeys
Beans &Properties
CRUD OpsEntityManager
Other operations
EntityOperations
Partialloading
Paging &Ordering
Open ViewPattern
Locking
Caching
In Practice
Inheritance
DB MappingsEntities
UPDATE &DELETE
SELECT
Joins
SELECT Clause
Expressions
QueryParameters
QueryLanguage
Packaging PersistenceUnit
Containers &Deployment
Q & A
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 92
© Copyright 2011, Software Alchemy
Ten Great Topics Not Covered1) Composite keys; great for mapping to an existing DB schema
2) Primary key generation; eg) hashes or UUID
3) Native SQL queries
4) GROUP BY and HAVING clauses
5) More nuances of Entity relationships
6) More nuances to DB mappings
7) Entity lifecycle events and listeners (could be used for data manipulation or auditing)
8) Bean validation
9) Programmatic query APIs
10) Metamodel APIs
Rochester JUG: 11-Oct-2011
Bryan Basham – Overview of JPA v2.0 Slide 93
© Copyright 2011, Software Alchemy
Resources
● JPA v2.0– JSR 317 (click here)– Javadocs (click here)– Tutorials (click here)
● JPA Documentation– Wikipedia (click here)– Wikibooks (click here)