1. Spring framework
Motto: Musíte rozbít vejce když chcete udělat omeletu
Spring framework training materials by Roman Pichlík is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
Sunday 13 May 2012
2. Přístup k datům
Jak efektivně používat Spring framework pro přístup k datům
Sunday 13 May 2012
3. Práce s daty
• Různé oblasti
• Definice datového zdroje
• Údržba zdrojů
• Ošetření výjimek
• Řízení transakcí
Sunday 13 May 2012
- bez ohledu na použiti konkretního frameworku
5. • Datasource je beana
• java.sql.Datasource
• Lokální/Poskytovaný
• JNDI aplikačního serveru
Sunday 13 May 2012
- datasource participuje v dependency injection jako jákákoliv jiná beana
6. Lokální datasource
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
<property name="url" value="jdbc:hsqldb:mem:test"/>
<property name="username" value="sa"/>
<property name="password" value=""/>
</bean>
• Connection pool s využitím
• Apache DBCP http://commons.apache.org/dbcp/
• Pozor na DBCP v produkci
• http://blog.novoj.net/2010/02/07/commons-dbcp-industrialni-
standard-s-chybami/
Sunday 13 May 2012
- zduraznit, ze nezalezi na tom odkud pochazi trida, ktera reprezentuje datasource
- DBCP alternativy C3PO, pool aplikacniho serveru (pokud to neni Tomcat)
7. Lokální ds. pro embedded DB
• Spring 3.x namespace embedded DB
• HSQL, H2, Derby
• Inicializace skripty
<jdbc:embedded-database id="dataSource">
<jdbc:script location="classpath:schema.sql"/>
<jdbc:script location="classpath:test-data.sql"/>
</jdbc:embedded-database>
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
EmbeddedDatabase db =
builder.setType(H2).addScript("schema.sql").addScript("test-data.sql").build();
// do stuff against the db (EmbeddedDatabase extends javax.sql.DataSource)
db.shutdown()
Sunday 13 May 2012
- rozsiritelne, muznost konfigurovat jinou embedded DB
- programový i deklarativní způsob
8. Data Access Object
• Návrhový vzor pro
přístup k datům
• Pouze DAO
implementuje logiku pro
práci s DB
• Motivace
• změna implementace
• odpovědnost v jedné
vrstvě
Sunday 13 May 2012
9. Implementační možnosti
• Přímé použití JDBC
• ORM či Semi-ORM framework
• JPA, Hibernate, iBatis, JDO...
• Co budeme řešit
• Konfigurace
• Resource management
• Exception handling
Sunday 13 May 2012
- Spring všechny tyto věci řeší za nás
- poskytuje high level API, které odstiňuje
11. Co obnáší práce s JDBC
• Získání databázového připojení
• Vytvoření java.sql.Statement
• Nastavení parametru
• Vykonání
• Procházení výsledků a zpracování
Sunday 13 May 2012
12. Jak vypadá typický kód
Connection con = null;
PreparedStatement ps = null; • Kde jsou problémy?
ResultSet rs = null;
try{
con = getConnection(); • NPE ignorujte
ps = con.prepareStatement("select * x");
rs = ps.executeQuery();
while(rs.next()){
//zpracuj hodnoty
}
} catch(SQLException e) {
throw new RuntimeException(e);
} finally {
try {
rs.close();
ps.close();
con.close();
} catch(SQLException e) {}
}
Sunday 13 May 2012
13. Jak vypadá typický kód
Connection con = null;
PreparedStatement ps = null; • Kde jsou problémy?
ResultSet rs = null;
try{
con = getConnection(); • Často se opakující kód
ps = con.prepareStatement("select * x");
rs = ps.executeQuery();
while(rs.next()){
//zpracuj hodnoty
• Návrhový vzor
}
} catch(SQLException e) {
Copy&Paste
throw new RuntimeException(e);
} finally {
try { • Uvolnění zdrojů
rs.close();
ps.close();
con.close(); • Míchání odpovědností
} catch(SQLException e) {}
}
• Vykonání/Zpracování
výsledku
Sunday 13 May 2012
14. Jak vypadá typický kód
Connection con = null;
r u
o
PreparedStatement ps = null; • Kde jsou problémy?
ResultSet rs = null;
try{
v z
m
con = getConnection(); • Často se opakující kód
é • Návrhový vzor
ps = con.prepareStatement("select * x");
rs = ps.executeQuery();
v
o h od
h t Copy&Paste
while(rs.next()){
r e
//zpracuj hodnoty
}
} catch(SQLException e) { v
á m
} finally { n e • Uvolnění zdrojů
throw new RuntimeException(e);
v at
je pl
try {
í m
rs.close();
n e
ps.close();
e T
con.close(); • Míchání odpovědností
}
e š
} catch(SQLException e) {}
Ř • Vykonání/Zpracování
výsledku
Sunday 13 May 2012
15. Template method
• Společný kód v
předkovi
• Potomek přepisuje
jenom to je pro něj
specifické
• zpracování
výsledků
Sunday 13 May 2012
18. JdbcTemplate
• Centrální třídá pro práci s JDBC
• Thread safe
• Překlad výjimek
• Resource management
• Alternativy
• org.springframework.jdbc.core.simple.SimpleJdbcTe
mplate
• org.springframework.jdbc.core.namedparam.NamedPar
ameterJdbcTemplate
Sunday 13 May 2012
20. SQL
int rowCount =
jdbcTemplate.queryForInt("select count(0) from t_accrual");
int countOfActorsNamedJoe =
jdbcTemplate.queryForInt(
"select count(0) from t_actors where first_name = ?",
new Object[]{"Joe"}
);
Actor actor =
(Actor) jdbcTemplate.queryForObject(
"select first_name, surname from t_actor where id = ?",
new Object[]{new Long(1212)},
new RowMapper() {
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
Actor actor = new Actor();
actor.setFirstName(rs.getString("first_name"));
actor.setSurname(rs.getString("surname"));
return actor;
}
});
Sunday 13 May 2012
21. DML a DDL
jdbcTemplate.update(
"insert into t_actor (first_name, surname) values (?, ?)",
new Object[] {"Leonor", "Watling"});
jdbcTemplate.execute(
"create table mytable (id integer, name varchar(100))");
Sunday 13 May 2012
22. Pojmenované parametry
NamedParameterJdbcTemplate namedParameterJdbcTemplate =
new NamedParameterJdbcTemplate(dataSource);
String sql = "select count(0) from T_ACTOR where first_name = :first_name";
Map namedParameters = new HashMap();
namedParameters.put("first_name", firstName);
int count = namedParameterJdbcTemplate.queryForInt(sql, namedParameters);
Sunday 13 May 2012
23. Podpora generik
simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource);
String sql = "select id, first_name, last_name from T_ACTOR where id = ?";
ParameterizedRowMapper<Actor> mapper = new ParameterizedRowMapper<Actor>() {
public Actor mapRow(ResultSet rs, int rowNum) throws SQLException {
Actor actor = new Actor();
actor.setId(rs.getLong("id"));
actor.setFirstName(rs.getString("first_name"));
actor.setLastName(rs.getString("last_name"));
return actor;
}
};
Actor actor = simpleJdbcTemplate.queryForObject(sql, mapper, id);
Sunday 13 May 2012
24. Překlad výjimek
• Spring překládá checked výjimky
DAO tříd na vlastní rodinu
runtime výjimek
Sunday 13 May 2012
- překlad podle vendor codes
25. Překlad SQLException
• SQLException
• Spring zpracuje error code
• Namapování na konkrétní
DataAccessException
• Rozšiřitelné
• custom kódy z triggeru
Sunday 13 May 2012
26. Přidání custom error kódu
• classpath kontext v rootu sql-error-
codes.xml
Sunday 13 May 2012
default org/springframework/jdbc/support/sql-error-codes.xml
sql-error-codes.xml do rootu classpath
zkopirovat z originalu beanu/DB kterou chceme zmenit
27. Autom. překlad @Repository
• Post-processor zajišťující @Repository
public class ProductDaoImpl implements
automatický překlad ProductDao {
vyjímek na @Repository // class body here...
třídách
}
• PersistenceExceptionTra
nslationPostProcessor <beans>
<!--
Exception translation bean post processor
• vytváří proxy -->
<bean
class="org.springframework.dao.annotation.Pe
rsistenceExceptionTranslationPostProcessor"/
>
<bean class="product.ProductDaoImpl"/>
</beans>
Sunday 13 May 2012
využití v případě, že pracujeme přímo s JDBC, Hibernatem, JPA případně dalšími
technologiemi podporovanými Spring frameworkem
28. SimpleJdbcInsert
insertActor =
new SimpleJdbcInsert(dataSource).withTableName("t_actor");
Map<String, Object> parameters = new HashMap<String, Object>(3);
parameters.put("id", actor.getId());
parameters.put("first_name", actor.getFirstName());
parameters.put("last_name", actor.getLastName());
insertActor.execute(parameters);
Sunday 13 May 2012
29. Co dál
• BLOB/CLOB handling
• Connection extractor
• Podpora volání stored procedures
• ...
Sunday 13 May 2012
30. Batch updates
• Více update/insert příkazů
• menší počet round-trips do DB
• DB může lépe optimalizovat
• Použití pokud pracujeme s jednou
tabulkou
Sunday 13 May 2012
34. DAO Support
• JdbcDaoSupport,
• HibernateDaoSupport
• JpaDaoSupport...
• Každý z těchto objektů obsahuje třídu
založenou na vzoru TemplateMethod
• JdbcTemplate, HibernateTemplate
Sunday 13 May 2012
- automaticky preklad vyjimek
36. JPA == ORM
• ORM
• Object To Relational Mapping
• Snaží se řešit střet dvou světů
• Objektového a Relačního
• Není specifické pro Javu
• každý jazyk/platforma má svůj
ORM framework
Sunday 13 May 2012
- snaží se pomáhat při prekonávání rozdílů mezi Objektovým a Relačním světem
- odstínění od konkrétní databázove technologie
37. ORM přibližuje oba světy
Svět objektů Svět relací a tabulek
public class User {
private List<Order> orders;
private String email;
private String name;
User
private Address address; 1
*
private class Address {
private String street;
Order
private String zipCode; 1
} *
}
Item
public class Order {
private List<Item> orderItems;
private long number;
}
public class Item {
private long id;
private String name;
}
Sunday 13 May 2012
38. ORM přibližuje oba světy
Svět objektů ORM Svět relací a tabulek
public class User {
private List<Order> orders;
private String email;
private String name;
User
private Address address; 1
*
Order
private class Address {
private String street;
private String zipCode; 1
} *
}
Item
public class Order {
private List<Item> orderItems;
private long number;
}
public class Item {
private long id;
private String name;
}
Sunday 13 May 2012
39. Agenda
• Představení JPA
• koncepce
• mapování
• dotazy
• Konfigurace EntityManageru
• Implementace JPA DAO
Sunday 13 May 2012
40. Koncept
• EntityManager
• Reprezentuje jednotku práce
• Umožňuje řídit lifeczcle
persistentních objektů
• vznik, aktualizaci, smazání
Sunday 13 May 2012
41. Koncept
• EntityManagerFactory
• thread-safe objekt
• reprezentuje jeden datový zdroj (DB)
• faktory pro EntityManager
• PersistenceUnit (persistence.xml)
• združuje skupinu persistentních tříd
• umožňue napojení na transakční
infrastrukturu
• konfiguruje JPA poskytovatele
Sunday 13 May 2012
persistence.xml musi lezet v rootu classpath
42. PersistentContext a EntityManager
Sunday 13 May 2012
- entity manager umoznuje pristup k persistentnimu contextu
- persistentni context predstavuje in-memory stav pers. entit a stara se o jeho synchronizaci
s databází
43. EntityManager API
Metoda v EntityManager API Popis SQL příkaz
Přidání instance entity do
persist(Entity instance) insert into table
PersistenContext
Odstranění entity z
remove(Entity instance) delete from table where id=?
PersistentContext
Nahrání podle primárního
find(Entity class, Primary key) select * from table where id=?
klíče
Aktualizace stavu entity v
merge(Entity instance) update table set ... where id=?
PersistentContext
Vytvoří objekt reprezentující
createQuery(String jpql)
dotaz
Vynutí synchronizaci
flush()
PersistenContext s databází
Transakce, zjištování existence
další metody
entity atd.
Sunday 13 May 2012
45. Hibernate JPA
• Hibernate EntityManager
• bridge pro JPA rozhrani
• Starý dobrý Hibernate pod
kapotou
• Lze používat Hibernate anotace
nad rámec JPA specifikace
Sunday 13 May 2012
46. JPA mapování
• Metadata pro popis vztahu
• Entita/Tabulka
• Field/Sloupec
• Vazby (one2one, one2many)
• Využití smart defaults
• pokud DB schéma
koresponduje s obj. modelem
Sunday 13 May 2012
47. Co můžeme anotovat
• Třídy
• propojení na tabulku
• aplikuje se na celou třídu pokud
na fieldech neřekneme jinak
• Fieldy
• propojení na sloupečky
• všechny fieldy jsou persitentí
• @Transient - exclude
Sunday 13 May 2012
50. JPA a dotazy
• Získání entity podle primárního
klíče
• Použití JPQL
• Použití SQL
Sunday 13 May 2012
- při použití SQL padá výhoda odstínění od konkrétní databáze, přesto je to někdy nutné
- pokud už musíte držte SQL kód na jednom místě
58. JNDI lookup
• EntityManagerFactory se získá z
JNDI
• Použití v případe deploymentu do
AS
Sunday 13 May 2012
59. Implementace DAO
• Žadná závislost na Spring třídách
• nemusíme dědit
• inject @PersistentContext
• překlad vyjímek přes
• PersistentExceptionTranslationPostProces
sor
Sunday 13 May 2012
60. Ukázka DAO s překladem výjimek
@Repository
public class UserJPADao implements UserDao{
@PersitenceContext
private EntityManager entityManager;
public void saveUser(User user) {
entityManager.persiste(user);
}
}
Sunday 13 May 2012
61. • springdao projekt
• dodejte chybějící implementaci do
• cz.sweb.pichlik.springdao.hibernate.UserStorageDaoHibernate
• cz.sweb.pichlik.springdao.jdbc.UserStorageDaoJdbc
• samozřejmostí je zelený test
• cz.sweb.pichlik.springdao.UserStorageDaoTest
• cz.sweb.pichlik.springdao.hibernate.UserStorageDaoHibernateTest
Sunday 13 May 2012
ukazata konfiguraci Springu