55
Ertuğrul ASLAN 1 : @ertugrulasla n : ertugrulaslan.blogspo t.com : /ertugrulaslan Mail: [email protected]

AnkaraJUG Nisan 2013 - Java Persistance API

Embed Size (px)

Citation preview

Page 1: AnkaraJUG Nisan 2013 - Java Persistance API

1

Ertuğrul ASLAN

: @ertugrulaslan: ertugrulaslan.blogspot.com: /ertugrulaslan

Mail: [email protected]

Page 2: AnkaraJUG Nisan 2013 - Java Persistance API

2

Agenda ORM (Object Relational Mapping) teknolojisi

JPA (Java Persistence API) JPA’mı Hibernate’mi kullanmalıyız.? Persistence.xml Entity ve annotasyonlar EntityManager  Relatationships JPQL (JPA sorgulama dili) JPA concurrency Java EE 7 ve JPA 2.1 ile gelecek yeni özellikler Demo uygulama

Page 3: AnkaraJUG Nisan 2013 - Java Persistance API

3

OBJECT RELATION MAPPING (ORM)

public class Person {

private String adı; private String soyadı; private String yaşı; private String telefon; //getter and setter}

• Objelerin tablolarda kalıcı hale getirilmeleri için uygulamadaki classların veritabanındaki tablolara, classlarda tanımlanan obje özelliklerinin yani obje değişkenlerinin bu tablolardaki sütunlarla eşleştirilmesi ORM (Object-Relational Mapping) denir.

Page 4: AnkaraJUG Nisan 2013 - Java Persistance API

4

ORM teknolojilerine neden ihyiyaç duyuldu.? Object-oriented dil kullanan programcılar, objelerini

yine object-oriented bir veritabanı sisteminde tutmak istiyorlar.

Yazılımda çalışma zamanında üretilen nesnelerin taşıdıkları bilgilerin daha sonra kullanılmak üzere kalıcı hale getirilmesinin en tabii yöntemi, olsa olsa bir object-oriented veri tabanı yönetim sistemi kullanmaktır.

Fakat şuan veriyi kalıcı kılmanın en tabii yolu olarak ilişkisel veri tabanı yönetim sistemleri (Relational Database Management Systems, RDBMS)

Page 5: AnkaraJUG Nisan 2013 - Java Persistance API

5

ORM teknolojilerine neden ihyiyaç duyuldu.?

Ve bunu basarabilmek icin, aşağıdaki yöntem kullanılmaktaydı. ResultSet’den dönen sonucuları objeye map etme vs.

Page 6: AnkaraJUG Nisan 2013 - Java Persistance API

6

ORM teknolojilerine neden ihyiyaç duyuldu.?

Bu şekilde uygulama geliştiren programcılar, zaman zaman tabloların yapısının değişmesiyle kodlarında tekrar tekrar düzeltme yapmak zorunda kaldı ve uygulamalar büyüdükçe bu katlanılamaz bir durum olmaya başladı.

Peki ne yapılmalı.?

Page 7: AnkaraJUG Nisan 2013 - Java Persistance API

7

ORM teknolojilerine neden ihyiyaç duyuldu.?

Bu uyumsuzluğun önüne geçmek için, RDBMS önüne konulacak bir katmanla, RDBMS in Object-oriented db’ye dönüştürülmesidir. Yani RDBMS ile uygulama arasına konulacak böyle bir katmanın iki arayüzü olacaktır: Birisi SQL(JDBC)’ı kullanarak RDBMS ile haberleşen interface, diğeri ise bir API üzerinden objelerle alakalı CRUD(Create, Read, Update,Delete) işlemlerini yapmaya izin veren interface. Dolayısıyla bu katman, programcıları, arkadaki RDBMS’in ilişikisel yapısından uzak tutacak ve onlara, objeleri sanki bir Object-oriented veritabanında kalıcı hale getiriyormuş gibi program yazma imkanı sağlayacaktır.

Page 8: AnkaraJUG Nisan 2013 - Java Persistance API

8

JPA’dan önce J2EE’nin ilk sürümü olan Aralık 1999 tarihli ilk versiyonunda EJB (Enterprise

JavaBean)’nin iki türünden birisi olan entity bean, bir ORM aracı idi ve Java ile geliştirilen uygulamaların veri katmanını halledecek şekilde geliştirilmişti. Büyük umutlarla beklenen EJB’ler ve özellikle de Entity beanler kısa sürede hayal kırıklığı yarattı.

Aynı zamanda birer uzak/dağıtık obje olan EJB’ler, gerek işin doğasının zaten çok zor olması gerek ise aşırı akademik yaklaşımdan dolayı kullanıcılarına öğrenme, uygulama ve özellikle de çalışma zamanındaki performans ve ölçeklenirlik açısından ciddi sıkıntılar yaşattı.

Sun EJB 2.0’ı yayınlayıp, özellikle performans ve ölçeklenirlik konusunda belli ilerlemeler sağladıysa da entity beanlere olan güvenin azalmış olması gerek Java programcılarını veri katmanınında kullanacakları ORM aracı konusunda alternatifler aramaya itti.

Page 9: AnkaraJUG Nisan 2013 - Java Persistance API

9

JPA(Java Persistence API)’nın doğuşu

Page 10: AnkaraJUG Nisan 2013 - Java Persistance API

10

JPA(Java Persistence API)’nın doğuşu

Hibernate, TopLink vs. çok başarılıydı fakat, farklı API’lere sahiplerdi.

Bu yüzden bu çözümler birbirlerinin yerine geçebilir durumda değillerdi.

Bu konuda bu kadar çok kütüphane çıktıktan sonra ortada bir karmaşa oluştu.

Ve Java dünyasında her konuda olduğu gibi bu konuda da üretilen bunca kütüphanenin ortak ve iyi yönleri toplanmış ve bir standart belirlenmiştir. İşte bu spesifikasyon Java Persistence API (JPA).

Page 11: AnkaraJUG Nisan 2013 - Java Persistance API

11

JPA(Java Persistence API)’nın doğuşu Ana teması daha kolay geliştirme ve programcılara çok büyük

kolaylık ve yenilikler getiren Java EE 5’in içindeki EJB 3.0’ın bir parçası olarak 2006 yılında ilk versiyon olan JPA 1.0 yayınlandı.

EJB 3.0 ile birlikte tanıtılan bu spesifikasyon java dünyasında büyük bir ilgi karşılandı.

Hibernate ve TopLink, JPA uyumlu ürünlerini piyasaya çıkardılar. Ve hem JPA hem de kendi özel (native) API’leri üzerinden programlama yapılabildiler.

Bu durum specifikasyon tabanlı ilerleyen java’nın yapısına çok daha uygundu ve Java programcıları artık standart bir API üzerinden pek çok farklı ORM ürününü kullanabilir hale gelmişlerdi. 2009’un sonrlarında yayınlanan Java EE 6. sürümünün bir parçası olarak yayınlanan JPA 2.0 sürümü, 1.0 sürümüne yaptığı eklerle JPA’yi çok daha güçlü hale getirdi.

Page 12: AnkaraJUG Nisan 2013 - Java Persistance API

12

JPA’mı Hibernate’mi kullanılmalı

JPA, Java EE ve ORM dünyasındaki karmaşalar sonucunda ortaya çıkmış bir persistence API’dir.

JPA, bir spesifikasyondur. Implementasyon değil.

JPA, kullanabilmek için bir implementasyona ihtiyaç vardır.

Bu implementasyonlarda, Hibernate, Toplink, EcpliseLink vs. Birer JPA implementasyonudur.

Hibernate

JPA

Page 13: AnkaraJUG Nisan 2013 - Java Persistance API

13

JPA(Java Persistence API) faydaları - I Öğrenimi ve kullanımı çok kolaydır.

Java SE hem de Java EE ortamlarında rahatlıkla kullanılabilmektedir.

Objeler arasında OneToMany, OneToOne ve ManyTo Many ilişkiler yanında inheritance ve polymorphism gibi özellikleri de destekler.

Konfigurasyon bilgileri ister XML’de istersek Java anotation’ları ile yapma imkanı verir.

Default değerle çalışabilir.

LazyFetching

Cascade Operations: Bir objeyi silince ona bağlı diğer objelerinde silinmesi veya güncellenmesi

Page 14: AnkaraJUG Nisan 2013 - Java Persistance API

14

JPA(Java Persistence API) faydaları - II Callbacks, veritabanlarındaki triggerlara benzetebiliriz.

@PrePersist, @PostRemove

NamedQueries, Sorgumuzu oluşturup bir isim veriyoruz ve sorgumuzu istenilen yerde bu isimle çağırıyoruz. PreparedStatementlera benzetebiliriz.

Native SQL, JPQL’in dışında kendi kendi SQL’lerimizi yazma imkanı verir. Büyük uygulamalarda yazmak zorunda kalabiliyoruz.

Page 15: AnkaraJUG Nisan 2013 - Java Persistance API

15

Persistence.xml JPA kullanmak için gerekli olan .xml dosyası

Örnek bir persistence.xml dosyası

Page 16: AnkaraJUG Nisan 2013 - Java Persistance API

16

Persistence.xml Unit name

Transaction type, JTA veya RESOURCE_LOCAL

Page 17: AnkaraJUG Nisan 2013 - Java Persistance API

17

Persistence.xml

Kullanılan JPA provider

Page 18: AnkaraJUG Nisan 2013 - Java Persistance API

18

Persistence.xml

Page 19: AnkaraJUG Nisan 2013 - Java Persistance API

19

Persistence.xml İmplementasyona bağlı propertyler olabililir.

Page 20: AnkaraJUG Nisan 2013 - Java Persistance API

20

Persistence.xml İmplementasyona bağlı propertyler olabililir.

Page 21: AnkaraJUG Nisan 2013 - Java Persistance API

21

Entity

Entity; JPA’yı kullanarak veritabanında kalıcı olacak objeye denir.

Bir objenin entity olması için o objenin kendisinden üretileceği classın @Entity annotasyonuyla ifade edilmesi yeterlidir.

Seralizable olması dikkat etmeliyiz, katmanlar arası geçişte kullanıyor olabiliriz.

Page 22: AnkaraJUG Nisan 2013 - Java Persistance API

22

Entity - II

Page 23: AnkaraJUG Nisan 2013 - Java Persistance API

23

@ Annotationlar

@Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id;

@Column(name = "MAIL", unique = true, length = 80, nullable = false) private Long id;

@Transient; veritabanında kalıcı olmasını istemediğimiz değişkenler (property) için kullanırız.

@Transient private String surname;

Not: javax.persistence paketinden import ediyoruz.

Page 24: AnkaraJUG Nisan 2013 - Java Persistance API

24

@ Annotationlar - II

@Embedded private Address address;

Page 25: AnkaraJUG Nisan 2013 - Java Persistance API

25

@ Annotationlar - III

@Enumurated

public enum PhoneType { MOBILE,HOME,WORK}

@Entity@Table(name="PERSONS")public class Person implements Serializable { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id;

@Enumerated(EnumType.STRING) private PhoneType phoneType;

Page 26: AnkaraJUG Nisan 2013 - Java Persistance API

26

EntityManager EntityManager; Entity class’larımız üzerinde CRUD

(CREATE,READ,UPDATE,DELETE) işlemlerini yapmak için kullanılan bir interface’dir.

Uygulama sunucusu kullanılıp kullanılmadığımıza bağlı olarak, EntityManager interface’ine ulaşmak için değişik yöntemler kullanılmalıdır.

EntityManagerFactory, tek objeli (singleton) bir interface olup, üzerinde entitylerle ilgili CRUD(create, read, update, delete) metodlarını çağıracağımız EntityManager nesnelerinin fabrikasıdır (factory).

Page 27: AnkaraJUG Nisan 2013 - Java Persistance API

27

EntityManager - II @PersistenceContext

EntityManager em;

* Bu kullanımda uygulama sunucusu tarafından EntityManager objesinin inject edilmesini sağlıyoruz.

@PersistenceUnit(unitName="ankaraJugPU") EntityManagerFactory emf; EntityManager em = emf.createEntityManager();

EntityManagerFactory emf =

Persistence.createEntityManagerFactory("ankaraJugPU"); EntityManager em = emf.createEntityManager();

* Bu kullanım ise uygulama sunucusu olmayan(uygulama sunucusu olan ortamlarda olabilir) desktop uygulamalarında kullanılan yöntemdir.

Page 28: AnkaraJUG Nisan 2013 - Java Persistance API

28

EntityManager - III

Persistence Context and EntityManager

PersistenceContext

EntityManager

persist()remove()refresh()merge()find()createQuery()createNativeQuery()createNamedQuery()contains()flush()

JavaBeanServlet

Page 29: AnkaraJUG Nisan 2013 - Java Persistance API

29

EntityManager - IV

Page 30: AnkaraJUG Nisan 2013 - Java Persistance API

30

EntityTransaction

JPA, veri üzerinde CUD yapan işlemler için mutlaka bir transaction beklemektedir.

Sizin DataSource bean'ı üzerinde veya hibernate.cfg.xml içerisinde autocommit davranışını true yapmanızın bir etkisi olmamaktadır.

Transaction kullanılmasa javax.persistence.TransactionRequiredException hatası anlınacaktır.

EJB kullanıyorsa, ejb metodları default olarak transactional olarak çalışmaktadır.

Page 31: AnkaraJUG Nisan 2013 - Java Persistance API

31

EntityTransaction

EJB metodu içerisinde aşağıdaki gibi kullanılabilinir.

Page 32: AnkaraJUG Nisan 2013 - Java Persistance API

32

Relationships

@OneToOne @OneToMany

@ManyToOne @ManyToMany

Bidirectional ve Undirectional

Page 33: AnkaraJUG Nisan 2013 - Java Persistance API

33

Relationships -II

public class Order {

int id; ...

Customer cust;}

public class Customer {

int id; ... Set<Order> orders;}

@Entity @Entity

@ManyToOne @OneToMany(mappedBy=“cust”)

@Id @Id

CUSTOMER

ID . . .

ORDER

CUST_IDID. . .

1 n

OneToMany Bidirectional

Page 34: AnkaraJUG Nisan 2013 - Java Persistance API

34

Relationships -III

ManyToOne

public class Customer {

int id;

Address addr;}

CUSTOMER

ADDR_IDID

ADDRESS

. . .ID

@Entity

@ManyToOne

@Id

ADDR_ID

Page 35: AnkaraJUG Nisan 2013 - Java Persistance API

35

Relationships -III

ManyToMany

public class Customer {

int id; ...

Collection<Phone> phones;}

PHONES_IDCUSTS_ID

@Entity @Entity(access=FIELD)

@Id @Id

@ManyToMany @ManyToMany(mappedBy=“phones”)

public class Phone {

int id; ...

Collection<Customer> custs;}

CUSTOMER

ID . . .

PHONE

ID. . .

CUSTOMER_PHONEID

@Entity

Page 36: AnkaraJUG Nisan 2013 - Java Persistance API

36

Relationships -IV

ManyToMany

PHONES_IDCUST_ID

CUSTOMER

ID . . .

PHONE

ID. . .CUST_PHONE

@Entitypublic class Customer { ... @ManyToMany @JoinTable(table=@Table(name=“CUST_PHONE”), joinColumns=@JoinColumn(name=“CUST_ID”), inverseJoinColumns=@JoinColumn(name=“PHONES_ID”)) Collection<Phone> phones;}

İlişkinin sahibi

Page 37: AnkaraJUG Nisan 2013 - Java Persistance API

37

Relationships -IV

ManyToMany

PHONES_IDCUST_ID

CUSTOMER

ID . . .

PHONE

ID. . .CUST_PHONE

@Entitypublic class Customer { ... @ManyToMany @JoinTable(table=@Table(name=“CUST_PHONE”), joinColumns=@JoinColumn(name=“CUST_ID”), inverseJoinColumns=@JoinColumn(name=“PHONES_ID”)) Collection<Phone> phones;}

İlişkinin sahibi

Page 38: AnkaraJUG Nisan 2013 - Java Persistance API

38

Relationships -VCascading

Persist

@Entitypublic class Student implements Serializable {  @Id @GeneratedValue private Long id; private String name; @OneToOne(cascade = CascadeType.PERSIST) private Address address

Page 39: AnkaraJUG Nisan 2013 - Java Persistance API

39

@Entitypublic class Student implements Serializable {  @Id @GeneratedValue private Long id; private String name; @OneToOne(cascade = {PERSIST, REMOVE}) private Address address;

Tip Tanım

PERSIST Nesne persist edilirse alt nesne de persist edilir

MERGE Nesne merge edilirse alt nesne de merge edilir

REMOVE Nesne silinirse bağlı alt nesne de silinir

REFRESH Nesne yenilenirse bağlı alt nesne de yenilenir

ALL Tüm işlemler birlikte yapılır

Page 40: AnkaraJUG Nisan 2013 - Java Persistance API

40

Queries(Sorgular) – JPQL

JPQL (Java Persistence Query Language)

Named, Dynamic, Native Queries

SELECT e FROM Employee e

SELECT e FROM Employee e WHERE e.name=‘ali’;

SELECT e FROM Employee e WHERE e.name=‘ali’ and e.email=‘[email protected]’;

em.createQuery("SELECT e FROM Employee e").getResultList();

em.createQuery("SELECT e FROM Employee e WHERE e.name=‘ali’").getResultList();

em.createQuery("SELECT e FROM Employee e WHERE e.name=:name") .setParameter("name", name).getResultList();

Page 41: AnkaraJUG Nisan 2013 - Java Persistance API

41

Queries(Sorgular) – JPQL

JPQL;List<Person> persons = em.createQuery("SELECT e FROM Person

e").getResultList();

Native SQL; List<Person> persons2 = em.createNativeQuery("SELECT * FROM Persons").getResultList();

JOINSSELECT e.name, d.name FROM Employee e JOIN e.department dWHERE e.status = ‘Tam zamanlı’

SELECT DISTINCT o FROM Order o JOIN o.lineItems l JOIN l.product p WHERE p.productType = ‘shoes’

Page 42: AnkaraJUG Nisan 2013 - Java Persistance API

42

Queries(Sorgular) – JPQL

Query query = em.createQuery("SELECT p FROM Person p " + "WHERE p.name LIKE :name"); query.setParameter(“name", adı); query.setFirstResult(5); query.setMaxResults(10);

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

Dikkat !

Person pr = (Person) em.createQuery("SELECT p FROM Person p WHERE p.email=:") .setParameter("email“,mail).getSingleResult();

- Birden fazla kayıt dönerse hata alınır.

Page 43: AnkaraJUG Nisan 2013 - Java Persistance API

43

Queries(Sorgular) – JPQL Named

Queries

List<Person> list = em.createNamedQuery("Person.findAll"). getResultList();

Query query = em.createNamedQuery("Person.findByEmail"); query.setParameter(“mail", mail);

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

Kullanımı

Page 45: AnkaraJUG Nisan 2013 - Java Persistance API

45

JPA 2.0 Concurrency and locking

tx1.begin(); //employee id 5 e1 = findEmp(5);

e1.setSalary(4000);

tx1.commit();//e1.version == 2 in db

tx2.begin(); //employee id 5 e1 = findEmp(5);

e1.setSalary(5000);

tx2.commit();//OptimisticLockException

Zaman

Peki bu durumda sonuç ne olacak.?

Transaction Locking; Locking mekanizması entity objeleri üzerinde yapılan okuma ve yazma işlemlerine farklı kilit türlerinin konmasını tanımlayan mekanizmadır.  

Page 46: AnkaraJUG Nisan 2013 - Java Persistance API

46

JPA 2.0 Concurrency and locking READ(JPA 1.0) || OPTIMISTIC (JPA 2.0)

Entity objeleri üzeride okuma kilidi. Kilitleme mekanizmalarında genel olarak o anda bir yazma işlemi yapılmıyorsa, aynı anda yapılan birden fazla eşzamanlı okuma işlemine izin verilir

WRITE (JPA 1.0) || OPTIMISTIC_FORCE_INCREMENT (JPA 2.0) Entity objeleri üzeride yazma kilidi. Eğer bir entity nesnesi üzerinde eşzamanlı olarak veri değişikliği yapılmak isteniyorsa bu işleme müdahale edilmez, ama geliştiriciye OptimisticLockingException istisnası fırlatılarak bilgilendirme yapılır.

Veritabanı seviyesinde kilit uygulanmaz

Page 47: AnkaraJUG Nisan 2013 - Java Persistance API

47

JPA 2.0 Concurrency and locking

PESSIMISTIC_WRITE Entity objesi üzerinde işlem yapılırken o anki yazma ya da okuma işlemi haricindeki tüm diğer okuma ve yazma işlemleri o işlem tamamlanana kadar askıya alınırlar.

PESSIMISTIC_READ Bu kilit mekanizması okuma işlemlerine kilit koyarken veritabanı seviyesinde kilit uygulanır. PESSIMISTIC_READ uygulanan bir entity nesnesi üzerinde eşzamanlı yapılan okuma işlemlerine müdahale edilmez. Okuma anında yapılmak istenen yazma işlemleri ise okuma işlemi tamamlanana kadar askıya alınır. Bu sayede karışıklıkta giderilmiş olur.

PESSIMISTIC_FORCE_INCREMENT Versiyonlama özelliğiyle entity nesnesi üzerinde yapılan her bir değişiklik, entity nesnesinin @Version annotasyonu ile (@Version Long vers) +1 değer arttırımına neden olur. Bu sayede her bir veri değişikliği versiyonlanmış olur. Çalışma anında bellek alanında bir entity nesnesinin birden fazla yönetimli karşılığı olabilir, versiyonlama sistemiyle en yüksek değerlikli versiyon değerine sahip entity nesnesi diğer eski versiyonlarına göre tercih edilmelidir, çünkü en günceli odur.

Page 48: AnkaraJUG Nisan 2013 - Java Persistance API

48

JPA 2.0 Concurrency and locking

Örnek kullanımlar

em.lock(person, LockModeType.PESSIMISTIC_FORCE_INCREMENT);

em.find(Person.class, 10L, LockModeType.READ);

em.refresh(person, LockModeType.PESSIMISTIC_READ);

Page 49: AnkaraJUG Nisan 2013 - Java Persistance API

49

JPA 2.1 New features

Stored procedures ve function desteği

Update ve Delete Critieria queries desteği

Schema generation desteği

CDI injection into listeners

Page 50: AnkaraJUG Nisan 2013 - Java Persistance API

50

JPA 2.1 New features

@Entity@NamedStoredProcedureQuery(

name="topGiftsStoredProcedure", procedureName="Top10Gifts")

StoredProcedreQuery query = EntityManager.createNamedStoredProcedureQuery("topGiftsStoredProcedure");

query.registerStoredProcedureParameter(1,String.class, ParameterMode.INOUT);

query.setParameter(1, "top10");

query.registerStoredProcedureParameter(2, Integer.class, ParameterMode.IN);

query.setParameter(2, 100);

query.execute();

String response = query.getOutputParameterValue(1);

Page 51: AnkaraJUG Nisan 2013 - Java Persistance API

51

JPA 2.1 New features

SELECT c FROM Customer c WHERE FUNCTION(‘hasGoodCredit’, c.balance, c.creditLimit)

Page 52: AnkaraJUG Nisan 2013 - Java Persistance API

52

JPA 2.1 New features

CriteriaUpdate<Customer> q = cb.createCriteriaUpdate(Customer.class); 

Root<Customer> c = q.from(Customer.class); q.set(c.get(Customer_.status), "outstanding") .where(cb.lt(c.get(Customer_.balance), 10000));

update/delete using Criteria

CriteriaDelete<Customer> q = cb.createCriteriaDelete(Customer.class); Root<Customer> c = q.from(Customer.class); q.where(cb.equal(c.get(Customer_.status), "inactive"),        cb.isEmpty(c.get(Customer_.orders)));

Page 53: AnkaraJUG Nisan 2013 - Java Persistance API

53

JPA 2.1 New features

CriteriaUpdate<Customer> q = cb.createCriteriaUpdate(Customer.class); 

Root<Customer> c = q.from(Customer.class); q.set(c.get(Customer_.status), "outstanding") .where(cb.lt(c.get(Customer_.balance), 10000));

update/delete using Criteria

CriteriaDelete<Customer> q = cb.createCriteriaDelete(Customer.class); Root<Customer> c = q.from(Customer.class); q.where(cb.equal(c.get(Customer_.status), "inactive"),        cb.isEmpty(c.get(Customer_.orders)));

Page 54: AnkaraJUG Nisan 2013 - Java Persistance API

54

Page 55: AnkaraJUG Nisan 2013 - Java Persistance API

55