JPA 2.0

4,395 views

Published on

What's new in JPA 2.0

Published in: Technology, News & Politics
0 Comments
4 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
4,395
On SlideShare
0
From Embeds
0
Number of Embeds
106
Actions
Shares
0
Downloads
0
Comments
0
Likes
4
Embeds 0
No embeds

No notes for slide
  • These defined properties must be implemented by each vendor (aside from vendor specific properties)
  • Let op! Mark @Transient anderswordtdezewegens default FIELD access ookgepersisteerd.
  • JPA 2.0

    1. 1. JPA 2.0<br />What’s new?<br />Emiel Paasschens<br />Ref. implemenatie van EclipseLink is bijlange (met name Criteria API) nanognietaf, dus…<br />GEEN Hands-On of tochwel…<br />
    2. 2. Programma<br /><ul><li> Standard properties in persistence.xml
    3. 3. Mixed @AccessType
    4. 4. Derived Identifiers
    5. 5. @ElementCollection
    6. 6. Undirectional @OneToMany / @OneToOne
    7. 7. @OrderColumn
    8. 8. Shared Cache API
    9. 9. Locking
    10. 10. JP QL
    11. 11. Expression and criteria API
    12. 12. HandsOn?
    13. 13. Drankjeaan de bar</li></li></ul><li>Standard properties for persistence.xml<br />SE only:<br /><ul><li>javax.persistence.jdbc.driver fully qualified name of the driver class
    14. 14. javax.persistence.jdbc.url driver-specific URL
    15. 15. javax.persistence.jdbc.user username used by database connection
    16. 16. javax.persistence.jdbc.password password for database connection validation</li></ul> <br />EE and SE:<br /><ul><li>javax.persistence.lock.timeoutvalue in milliseconds for pessimistic lock timeout
    17. 17. javax.persistence.query.timeoutvalue in milliseconds for query timeout
    18. 18. javax.persistence.validation.group.pre-persist groups that are targeted for validation upon the pre-persist event
    19. 19. javax.persistence.validation.group.pre-update groups that are targeted for validation upon the pre-update event
    20. 20. javax.persistence.validation.group.pre-remove groups that are targeted for validation upon the pre-remove event</li></li></ul><li>Mixed @AccessType<br /><ul><li>Property based or field based:@Access(FIELD)@Access(PROPERTY)
    21. 21. Can be mixed now! (instead of one or the other)At Entity/Class level the default Access type is defined
    22. 22. Can be set per attribute to differ from default: - on field (declaration) @Access(FIELD) access directly on instance variable by pers.prov.- on property (getter accessor) @Access(PROPERTY) access via accessor methods by pers. prov.
    23. 23. Be aware: @Access(PROPERTY):- validation/conversion logic in accessor methods is executed!- exceptions are catched and wrapped in PersistenceException, which is thrown. Transactions are marked for rollback.
    24. 24. The access type of an embeddable class is determined by the access type class in which it is embedded, independent of the containing class.</li></li></ul><li>Mixed @AccessType(code)<br />@Entity<br />@Access(FIELD)<br />public class Vehicle {<br /> @Id <br /> private Long id;<br /> @Transient<br /> double fuelEfficieny;<br /> <br /> @Access(PROPERTY)<br /> @Column(name=”FUEL_EFF”)<br /> public double getDbFuelEfficiency(){<br /> return convertToMetric(fuelEfficieny);<br /> }<br /> <br /> public void setDbFuelEfficiency(double d){<br />fuelEfficieny= convertToImperial(d);<br /> }<br />}<br />
    25. 25. Derived Identifiers (1)<br />Old JPA 1.0 way:<br /><ul><li> Identifiers that include a relationship
    26. 26. Require an additional foreign key field
    27. 27. Indicate one of the mappings as read only
    28. 28. Duplicate mapping info</li></ul>@Entity<br />public class Part {<br /> @Id Integer partNo;<br />@Column(name=“SUPP_ID”) @Id Integer suppId;<br /> ...<br /> @ManyToOne(insertable=false, updatable=false)<br />@JoinColumn(name=“SUPP_ID”)<br />Supplier supplier;<br /> ...<br />}<br />
    29. 29. Derived Identifiers (2) <br />The new JPA 2.0 way:<br /><ul><li> Identifiers can be derived from relationships</li></ul>@Entity public class Supplier {<br />@Id long supId;<br />String name;<br />...<br />}<br /> <br />public class PartId{<br />String desc; //matches name of @Id attribute<br />long sup; //matches name of @Id attribute and type of Supplier PK<br />}<br /> <br />@Entity<br />@IdClass(PartId.class)<br />public class Part {<br />@Id String desc;<br />@Id @ManyToOneSupplier sup;<br />...<br />}<br />
    30. 30. ElementCollection<br />@ElementCollection of basic types or embeddable classes with elements: - targetClass=&lt;full classname&gt; (required when generics are not used!) - fetch=FetchType.EAGER/LAZY (default=LAZY) (both optional)<br /><ul><li> Used to store a collection of an Entity in a (separate) table
    31. 31. Default tablename is <Entity tablename>_<attributename> or @CollectionTable(name=’tname’) with addition optional elements: - catalog (default=the ‘default’ catalog) - schema (default=the ‘default’ schema) - joinColumns (default=<Entityname>_<Entity PK>) - uniqueConstraints (only used at table generation/DDL)
    32. 32. Can be combined with existing @Column (only with basic type) and @OrderBy annotations
    33. 33. @OrderBy with basic types collection: value is not used! (only @OrderBy)</li></li></ul><li>@ElementCollection(code)<br />@Entity public class Person {<br />@Id private Long socialSecurityNo;<br />...<br />@ElementCollection<br />@OrderBy(&quot;zipcode.zip ASC, zipcode.plusFour DESC&quot;)<br />public Set&lt;Address&gt; getResidences() {...};<br />...<br />}<br />@Embeddable public class Address {<br />protected String street;<br />protected String city;<br />protected String state;<br />@Embedded protected Zipcodezipcode;<br />}<br />@Embeddable public class ZipCode {<br />protected String zip;<br />protected String plusFour;<br />}<br />
    34. 34. Undirectional @OneToMany / @OneToOne<br />@OneToMany Mapping with @JoinColumn on parent side:<br /> <br />@Entity public class Vehicle {<br /> ...<br /> @OneToMany<br /> @JoinColumn(name=”VEHIC”)<br /> List&lt;Parts&gt; parts;<br /> ...<br />}<br /> <br />Also applies to @OneToOne<br />With JPA 1.0 you had to define relation on both sides (necessary to specify columnname)<br />
    35. 35. @OrderColumn<br /><ul><li> @OrderColumn (invalidates @OrderBy), 0 based.
    36. 36. Stores the order in separate DB column, so preferable do not use!  insert object at begin of list causes lots of updates!
    37. 37. Elements, all optional:- name (default: <collection/set fieldname>_ORDER)- nullable (default: true)- insertable (default: true)- updatable (default: true)- columnDefinition (DDL for creating)- table (default: the jointable or table used for the collection)</li></li></ul><li>@OrderColumn(code)<br />@Entity<br />public class CreditCard {<br />@Id Long ccNumber;<br />@OneToMany // unidirectional<br />@OrderColumn<br />List&lt;CardTransaction&gt; transactionHistory;<br />...<br />}<br />Results in an ‘extra’ column in table of entity CardTransaction with name TRANSACTIONHISTORY_ORDER<br />
    38. 38. Shared Cache API<br /> <br />public class Cache {<br /> public boolean contains(Class cls, Object pk); <br /> public void evict(Class cls, Object pk); <br /> public void evict(Class cls);<br /> public void evictAll();<br />}<br /> <br /><ul><li> Exact implementation vendor dependent!
    39. 39. evict?  how about objects pointing to these evicting instances…
    40. 40. eventAllis save,
    41. 41. also contains, but what does it say…?</li></li></ul><li>Locking<br /><ul><li> new LockMode values: - OPTIMISTIC (READ) - OPTIMISTIC_FORCE_INCREMENT (WRITE) - PESSIMISTIC (*) - PESSIMISTIC_FORCE_INCREMENT (*)
    42. 42. API EntityManager: - LockModeparam added to find and refresh - Properties param added to find, refresh and lock (props are vendor dependent) - <T> T unwrap (Class<T> cls)  flexible vendor specific, e.g. to get DB connection - getEntityManagerFactory() - void clear(Object entity)  No sync to DB of unflushed changes!</li></li></ul><li>Locking (code)<br />//Read, then lock (little concurrency risk)<br />Account acct = em.find(Account.class, acctId);<br />//Withdraw, so lock for update (little risk of stale data)<br />em.lock(acct, PESSIMISTIC);<br />long balance = acct.getBalance();<br />acct.setBalance(balance – 100);<br /> <br />//Read and lock at same time (no concurrency risk)<br />Account acct = em.find(Account.class, acctId, PESSIMISTIC);<br />//Withdraw, already locked (so no risk of stale data)<br />long balance = acct.getBalance();<br />acct.setBalance(balance – 100);<br /> <br /> <br />//Read and then lock and refresh (no concurrency risk)<br />Account acct = em.find(Account.class, acctId);<br />//Withdraw, so lock and refresh (no risk of stale data)<br />em.refresh(acct, PESSIMISTIC);<br />long balance = acct.getBalance();<br />acct.setBalance(balance – 100);<br />Best approach depends upon specs & requirements!<br />
    43. 43. JP QL (1)<br /><ul><li> Timestamp literals (‘2009-07-06 17:30:00.’)
    44. 44. CLASS() in WHERE clause (kind of JP QL ‘instanceof’):SELECT e FROM Employee e WHERE CLASS(e) = FullTimeEmployee
    45. 45. Collection param from IN:SELECT e FROM Employee eWHERE e.id IN [:selectedIds]
    46. 46. INDEX in WHERE clause (e.g. to retrieve first 10 or paged getting data):SELECT e FROM Employee eWHERE INDEX(e) BETWEEN 0 AND 9</li></li></ul><li>JP QL (2)<br /><ul><li> CASE statement in WHERE clause :UPDATE Employee eSET e.salary =CASE e.rating WHEN 1 THEN e.salary * 1.1WHEN 2 THEN e.salary * 1.05ELSE e.salary * 1.01END
    47. 47. Also allowed is this variant:UPDATE Employee eSET e.salary =CASE WHEN e.rating = 1 THEN e.salary * 1.1WHEN e.rating = 2 THEN e.salary * 1.05ELSE e.salary * 1.01END</li></li></ul><li>Expression & criteria API (1)<br /><ul><li>QueryBuilderobject is the object the create queries with
    48. 48. Object Model totally been refactored (no more DomainObject or QueryDefinition objects)
    49. 49. CriteriaQueryrepresents JP QL in an object way
    50. 50. The query Root object defined by the from method and is analog to the “Employee e” in JP QL: SELECT e FROM Employee e
    51. 51. new Query object is created by passing CriteriaQuery to em.createQuery.
    52. 52. If CriteriaQuery is changed afterwards, the created Query object does not change!</li></li></ul><li>Expression & criteria API (2)<br /><ul><li> For all the JP QL where clause methods there is a equivalent method in the QueryBuilderAPI: e.gisEmpty(), between(), like(), equal(), notEqual(), selectCase,() all(), gt(), lt(), ge(), le(), etc.
    53. 53. Also applies for and(), or() and not(), methods of the QueryBuilder API
    54. 54. The same accounts for methods in the select: max(), min(), sum(), prod(), etc
    55. 55. But the orderBy(), groupBy() and having() are methods of the CriteriaQueryobject!
    56. 56. And function desc() and asc() are methods of the QueryBuilderobject !!</li></ul>Pro is type safe and no need any more to execute logic code twice when dynamically constructing a query comparing with JP QL (where one time parse is needed to construct the query query and one more to bind the bind params).<br />Con : quite complex and hard to read, so from maintenance perspective… <br />
    57. 57. Expression & criteria API (code) <br />Query q = em.createQuery(“SELECT a FROM Account a”);<br />QueryBuilderqb = em.getQueryBuilder();CriteriaQuerycq = qb.create();<br />Root&lt;Account&gt; account = cq.from(Account.class);<br />cq.select(account);<br />Query q = em.createQuery(cq);<br />List&lt;Account&gt; list = q. getResultList();<br /> <br />
    58. 58. Expression & criteria API (code) <br />SELECT c.name<br /> FROM Customer c<br /> JOIN c.orders o<br /> JOIN o.lineitemsi<br /> WHERE i.product.productType = ‘printer’<br />CriteriaQuery q = qb.create();<br />Root&lt;Customer&gt; cust = q.from(Customer.class);<br />Join&lt;Customer, Order&gt; order = cust.join(Customer_.orders);<br />Join&lt;Order, Item&gt; item = order.join(Order_.lineitems);<br />q.select(cust.get(Customer_.name))<br />.where(qb.equal(item.get(Item_.product).get(Product_.productType),<br /> &quot;printer&quot;));<br />
    59. 59. Expression & criteria API (code) <br />Joins can be chained, resulting into:<br /> CriteriaQueryq = qb.create();<br />Root&lt;Customer&gt; cust = q.from(Customer.class);<br />Join&lt;Order,Item&gt; item = cust.join(Customer_.orders).join(Order_.lineitems);<br />q.select(cust.get(Customer_.name))<br />.where(qb.equal(item.get(Item_.product).get(Product_.productType),<br /> &quot;printer&quot;));<br />  <br />Outer join with param on the join:<br /> SELECT c <br /> FROM Customer c <br />LEFT JOIN c.orders o <br /> WHERE c.status = 1<br /> <br />CriteriaQuery q = qb.create();<br />Root&lt;Customer&gt; cust = q.from(Customer.class);<br />Join&lt;Customer, Order&gt; order = cust.join(Customer_.orders, JoinType.LEFT);<br />q.where(qb.equal(cust.get(Customer_.status), 1)).select(cust);<br />
    60. 60. Expression & criteria API (code) <br />Example with ContactInfo as Embeddable class containing address and set of Phones.<br /> <br />SELECT p.vendor<br /> FROM Employee e <br /> JOIN e.contactInfo.phones p<br /> WHERE e.contactInfo.address.zipcode = &apos;95054&apos;<br /> <br />CriteriaQuery q = qb.create();<br />Root&lt;Employee&gt; emp = q.from(Employee.class);<br />Join&lt;ContactInfo, Phone&gt; phone =<br />emp.join(Employee_.contactInfo).join(ContactInfo_.phones);<br />q.where(qb.equal(emp.get(Employee_.contactInfo).get(<br />ContactInfo_.address).get(Address_.zipcode),<br /> &quot;95054&quot;)).select(phone.get(Phone_.vendor));<br />
    61. 61. Expression & criteria API (code) <br />Example with subquery using all:SELECT emp<br /> FROM Employee emp<br /> WHERE emp.salary &gt; ALL (SELECT m.salary<br /> FROM Manager m<br /> WHERE m.department = emp.department)<br />  <br />// create CriteriaQuery instance, with root Employee<br />CriteriaQuery q = qb.create();<br />Root&lt;Employee&gt; emp = q.from(Employee.class);<br /> <br />// create Subquery instance, with root Manager<br />Subquery&lt;BigDecimal&gt; sq = q.subquery(BigDecimal.class);<br />Root&lt;Manager&gt; manager = sq.from(Manager.class);<br />sq.select(manager.get(Manager_.salary));<br />sq.where(qb.equal(manager.get(Manager_.dept), emp.get(Employee_.dept)));<br /> <br />// an all expression is applied to the subquery result<br />q.select(emp).where(qb.gt(emp.get(Employee_.salary), qb.all(sq)));<br />
    62. 62. Expression & criteria API (code) <br />Example with order by: SELECT o.quantity,<br />a.zipcode<br /> FROM Customer c <br /> JOIN c.orders o <br /> JOIN c.address a<br /> WHERE a.state = &apos;CA’<br />ORDER BY o.quantity, <br />a.zipcode<br />CriteriaQuery q = qb.create();<br />Root&lt;Customer&gt; c = q.from(Customer.class);<br />Join&lt;Customer, Order&gt; o = c.join(Customer_.orders);<br />Join&lt;Customer, Address&gt; a = c.join(Customer_.address);<br />q.where(qb.equal(a.get(Address_.state), &quot;CA&quot;));<br />q.orderBy(qb.asc(o.get(Order_.quantity)),<br /> qb.asc(a.get(Address_.zipcode)));<br />q.select(o.get(Order_.quantity), a.get(Address_.zipcode));<br />
    63. 63. Expression & criteria API (code) <br />Example with group by and having: <br /> SELECT c.status, <br /> AVG(c.filledOrderCount),<br /> COUNT(c)<br /> FROM Customer c<br />GROUP BY c.status<br /> HAVING c.status IN (1, 2)<br />CriteriaQuery q = qb.create();<br />Root&lt;Customer&gt; cust = q.from(Customer.class);<br />q.groupBy(cust.get(Customer_.status));<br />q.having(qb.in(cust.get(Customer_.status)).value(1).value(2));<br />q.select(cust.get(Customer_.status),<br />qb.avg(cust.get(Customer_.filledOrderCount)),<br />qb.count(cust));<br />
    64. 64. AMIS Technology SchoolTrainingen & Masterclasses<br />- Trainingen op vakinhoudelijke Oracle onderwerpen<br /><ul><li>Voor consultants, door consultants
    65. 65. Training door Oracle ACE’s en ACE Director
    66. 66. Praktijkgebaseerd
    67. 67. Professionelenazorg</li></ul>Kijk op www.amis.nlvooronsactueletrainingsaanbod<br />

    ×