Transcript Hibernate

Hibernate
Marcin Pamuła
Mateusz Stefek
Plan prezentacji
1. Wstęp
2. EJB i JDBC a Hibernate
3. Architektura
4. Instalacja
5. Tworzenie najprostszej aplikacji hibernatowej
6. Możliwości Hibernata
7. Połączenie z Hibernata z JBOSSem
8 Podsumowanie
Wstęp
Hibernate jest obiektowym narzędziem dostępu do
bazy danych. Hibernate pozwala tworzyć klasy
odpowiadające tabelkom w bazie danych. Umożliwia
modelowanie relacji, dziedziczenia, polimorfizmu,
kompozycji i kolekcji. W Hibernacie mamy możliwość
wykonywania SQL-owych zapytań do bazy danych.
Udostępnia też własny język zapytań (HQL), który
dorównuje możliwościami SQL-owi, a przewyższa go
pod względem przejrzystości.
EJB i JDBC a Hibernate
JDBC – pozwala na wykonywanie poleceń
SQL-owych z poziomu kodu JAVY
Entity Java Beans – komponent EJB odpowiada
pewnemu zbiorowi obiektów w bazie danych
Dlaczego Hibernate jest wygodniejszy?
Architektura Hibernata
Architektura Hibernata
Instalacja
Opis instalacji Hibernata:
- instalacja bazy danych na przykładzie
PostgreSQL
- ściągnięcie plików z klasami Hibernata
- ściągnięcie drivera JDBC do PostgreSQL
- konfiguracje
Tworzenie przykładowej aplikacji
hibernatowej






Klasy w Javie odpowiadające tabelkom
XMLe z mapowaniami klas
Konfiguracja Hibernata
Tworzenie nowego obiektu i zapamiętanie go w
bazie danych
Wczytywanie obiektu z bazy danych
Wykonywanie zapytań do bazy danych
Klasy w Javie odpowiadające
tabelkom
package events;
public class Person {
private
private
private
private
Long id;
int age;
String firstname;
String lastname;
public Person() {}
// Accessor methods for all properties, private setter for 'id'
}
XMLe z mapowaniami klas
<hibernate-mapping>
<class name="events.Person" table="PERSON">
<id name="id" column="PERSON_ID">
<generator class="native"/>
</id>
<property name="age"/>
<property name="firstname"/>
<property name="lastname"/>
</class>
</hibernate-mapping>
Konfiguracja Hibernata
<hibernate-configuration>
<session-factory>
<!-- Database connection settings -->
<property name="connection.driver_class">org.hsqldb.jdbcDriver</property>
<property name="connection.url">jdbc:hsqldb:hsql://localhost</property>
<property name="connection.username">sa</property>
<property name="connection.password"></property>
<!-- JDBC connection pool (use the built-in) -->
<property name="connection.pool_size">1</property>
<!-- SQL dialect -->
<property name="dialect">org.hibernate.dialect.HSQLDialect</property>
<!-- Enable Hibernate's automatic session context management -->
<property name="current_session_context_class">thread</property>
<!-- Disable the second-level cache -->
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
<!-- Drop and re-create the database schema on startup -->
<property name="hbm2ddl.auto">create</property>
<mapping resource="events/Event.hbm.xml"/>
</session-factory>
</hibernate-configuration>
Tworzenie nowego obiektu i
zapamiętanie go w bazie danych
private void createAndStoreEvent(String title, Date theDate) {
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
Event theEvent = new Event();
theEvent.setTitle(title);
theEvent.setDate(theDate);
session.save(theEvent);
session.getTransaction().commit();
}
Wczytywanie obiektu z bazy
danych i dokonywanie zmian
private void loadAndUpdateEvent(Long personId, Long eventId, String t) {
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
Event anEvent = (Event) session.load(Event.class, eventId);
anEvent.setTitle(t);
session.saveOrUpdate(anEvent);
session.getTransaction().commit();
}
Wykonywanie zapytań do bazy
danych
private List listEvents() {
Session session =
HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
List result = session.createQuery("from Event").list();
return result;
}
Możliwości Hibernata
W Hibernacie możemy zamodelować:
 Kolekcje
 Kompozycje
 Dziedziczenie
Dodatkowe możliwości:
 HQL
 Zapytania SQLowe
 Kryteria
Kolekcje
<set name="names" table="person_names">
<key column="person_id"/>
<element column="person_name" type="string"/>
</set>
<bag name="sizes"
table="item_sizes"
order-by="size asc">
<key column="item_id"/>
<element column="size" type="integer"/>
</bag>
Kolekcje – relacja jeden do wielu
<class name="Parent">
<id name="id" column="parent_id"/>
....
<set name="children" inverse="true">
<key column="parent_id"/>
<one-to-many class="Child"/>
</set>
</class>
<class name="Child">
<id name="id" column="child_id"/>
....
<many-to-one name="parent"
class="Parent"
column="parent_id"
not-null="true"/>
</class>
Kolekcje – relacja wiele do wielu
<class name="Category">
<id name="id" column="CATEGORY_ID"/>
...
<bag name="items" table="CATEGORY_ITEM">
<key column="CATEGORY_ID"/>
<many-to-many class="Item" column="ITEM_ID"/>
</bag>
</class>
<class name="Item">
<id name="id" column="CATEGORY_ID"/>
...
<bag name="categories" table="CATEGORY_ITEM" inverse="true">
<key column="ITEM_ID"/>
<many-to-many class="Category" column="CATEGORY_ID"/>
</bag>
</class>
Kompozycje
public class Person {
private Name name;
private String key;
public String getKey() {
return key;
}
private void setKey(String key) {
this.key=key;
}
public Name getName() {
return name;
}
public void setName(Name name) {
this.name = name;
}
}
Kompozycje
public class Name {
String first;
String last;
public String getFirst() {
return first;
}
void setFirst(String first) {
this.first = first;
}
public String getLast() {
return last;
}
void setLast(String last) {
this.last = last;
}
}
Kompozycje
<class name="eg.Person" table="person">
<id name="Key" column="pid" type="string">
<generator class="native"/>
</id>
<component name=„name" class="eg.Name">
<property name="first"/>
<property name="last"/>
</component>
</class>
Dziedziczenie
W Hibernacie mamy 3 sposoby na odwzorowanie
dziedziczenia:
 Jedna tabela na klasę i klasy z niej
dziedziczące
 Tabela na każdą klasę
 Tabela na każdą klasę nieabstrakcyjną
Tabela na schemat dziedziczenia
<class name="Payment" table="PAYMENT" discriminator-value=„PAYMENT">
<id name="id" type="long" column="PAYMENT_ID">
<generator class="native"/>
</id>
<discriminator column="PAYMENT_TYPE" type="string"/>
<property name="amount" column="AMOUNT"/>
...
<subclass name="CreditCardPayment" discriminator-value="CREDIT">
<property name="creditCardType" column="CCTYPE"/>
...
</subclass>
<subclass name="CashPayment" discriminator-value="CASH">
...
</subclass>
</class>
Tabela na każdą klasę
<class name="Payment" table="PAYMENT">
<id name="id" type="long" column="PAYMENT_ID">
<generator class="native"/>
</id>
<property name="amount" column="AMOUNT"/>
...
<joined-subclass name="CreditCardPayment" table="CREDIT_PAYMENT">
<key column="PAYMENT_ID"/>
<property name="creditCardType" column="CCTYPE"/>
...
</joined-subclass>
<joined-subclass name="CashPayment" table="CASH_PAYMENT">
<key column="PAYMENT_ID"/>
...
</joined-subclass>
</class>
Tabela na każdą klasę
nieabstrakcyjną
<class name="Payment">
<id name="id" type="long" column="PAYMENT_ID">
<generator class="sequence"/>
</id>
<property name="amount" column="AMOUNT"/>
...
<union-subclass name="CreditCardPayment" table="CREDIT_PAYMENT">
<property name="creditCardType" column="CCTYPE"/>
...
</union-subclass>
<union-subclass name="CashPayment" table="CASH_PAYMENT">
...
</union-subclass>
</class>
Hibernate Query Language (HQL)
Hibernate jest wyposażony we własny, bardzo
dobry język zapytań przypominający składnią
SQL-a. Jednak w przeciwieństwie do niego, HQL
jest językiem zorientowanym w pełni obiektowo,
rozumiejącym mechanizmy dziedziczenia i
polimorfizmu.
Hibernate Query Language (HQL)







Składnia
Złączenia
Klauzula SELECT
Klauzula WHERE
Funkcje agregujące i operatory
order by, group by
podzapytania
Użycie HQLa
List mothers = session.createQuery(
"select mother from Cat as cat join cat.mother as mother
where cat.name = ?")
.setString(0, name)
.list();
List kittens = session.createQuery(
"from Cat as cat where cat.mother = ?")
.setEntity(0, pk)
.list();
Użycie HQLa
Iterator results = sess.createQuery(
"select cat.color, min(cat.birthdate), count(cat) from Cat cat " +
"group by cat.color")
.list()
.iterator();
while ( results.hasNext() ) {
Object[] row = (Object[]) results.next();
Color type = (Color) row[0];
Date oldest = (Date) row[1];
Integer count = (Integer) row[2];
.....
}
Zapytania SQL-owe
Zapytania nazwane w plikach z mapowaniami
<query name="eg.DomesticCat.by.name.and.minimum.weight"><![CDATA[
from eg.DomesticCat as cat
where cat.name = ?
and cat.weight > ?
] ]></query>
Query q =
sess.getNamedQuery("eg.DomesticCat.by.name.and.minimum.weight");
q.setString(0, name);
q.setInt(1, minWeight);
List cats = q.list();
Zapytania SQL-owe
Zapytania w kodzie klas
List cats = session.createSQLQuery(
"SELECT {cat.*} FROM CAT {cat} WHERE ROWNUM<10",
"cat",
Cat.class
).list();
Kryteria
Kryteria udostępniają programiście możliwość
dynamicznego budowania zapytań. Ułatwiają też
abstrahowanie od języka zapytań.
Kryteria udostępniają metodę list, która zwraca listę
wyników
List studenci =
sess.createCriteria(Student.class).list()
Kryteria
List studenci = sess.createCriteria(Student.class)
.add(Restrictions.like("imie", "M%"))
.list()
List studenci = sess.createCriteria(Student.class)
.add(Restrictions.sqlRestriction({alias}.imie like "M%"))
.list()
Kryteria
List studenci = sess.createCriteria(Student.class)
.addOrder(Order.asc("imie")
.list()
List pracownicy = sess.createCriteria(Pracownik.class)
.createCriteria("przelozony").
.add(Restriction.like("imie", "Z")
.list()
Połączenie Hibernata z JBossem
Chcemy tak skonfigurować serwer aplikacji, aby
hibernate był dostępny jako usługa, a SessionFactory
była widoczna w JNDI.
1.
2.
Skonfigurowanie Jbossa, tak aby używał
odpowiedniego drivera JDBC
Skopiowanie plików cglib.jar, commonscollections.jar, commons-logging.jar, commonslang.jar, jcs.jar,odmg.jar i hibernate.jar do
${HIBERNATE_HOME}/lib i
${JBOSS_HOME}/server/default/lib
Połączenie Hibernata z JBossem
1.
Utworzenie archiwum SAR o następującej
strukturze:
1.
2.
3.
mojpakiet/Student.class
mappings/Student.hbm.xml
META-INF/jboss-service.xml
Połączenie Hibernata z JBossem
1.
Jboss-service.xml
<server>
<mbean code="net.sf.hibernate.jmx.HibernateService" name="jboss.jca:service=HibernateFactory,
name=HibernateFactory">
<depends>jboss.jca:service=RARDeployer</depends>
<depends>jboss.jca:service=LocalTxCM,name=MySqlDS</depends>
<!-- Make it deploy ONLY after DataSource had been started -->
<attribute name="MapResources">mappings/Student.hbm.xml</attribute>
<attribute name="JndiName">java:/hibernate/HibernateFactory</attribute>
<attribute name="Datasource">java:/MySqlDS</attribute>
<attribute name="Dialect">net.sf.hibernate.dialect.MySQLDialect</attribute>
Połączenie Hibernata z JBossem
<attribute name="TransactionStrategy">net.sf.hibernate.transaction.JTATransactionFactory</attribute>
<attribute
name="TransactionManagerLookupStrategy">net.sf.hibernate.transaction.JBossTransactionManagerLookup</
attribute>
<attribute name="UseOuterJoin">false</attribute>
<attribute name="ShowSql">false</attribute>
<attribute name="UserTransactionName">UserTransaction</attribute>
</mbean>
</server>
Po zdeplojowaniu wszystkie pisane przez nas
komponenty mogą wyciąg SessionFactory z JNDI.
Podsumowanie
Główną zaletą Hibernata, jest jego prostota i
łatwość użycia. Dzięki niemu nie trzeba pisać
setek poleceń w SQLu. Hibernate robi to za nas.
Poza tym jest intuicyjny i łatwy do nauki. Wydaję
się on być najlepszą technologią umożliwiającą
dostęp do bazy danych, występującą obecnie na
rynku.