Date post: | 25-Jan-2015 |
Category: |
Documents |
Upload: | roman-pichlik |
View: | 785 times |
Download: | 4 times |
Spring frameworkMotto: 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
Přístup k datůmJak efektivně používat Spring framework pro přístup k datům
Sunday 13 May 2012
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
Definice datového zdroje
Sunday 13 May 2012
• 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
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)
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
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
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 handlingSunday 13 May 2012
- Spring všechny tyto věci řeší za nás- poskytuje high level API, které odstiňuje
JDBC
Sunday 13 May 2012
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
Jak vypadá typický kód• Kde jsou problémy?
• NPE ignorujte
Connection con = null;PreparedStatement ps = null;ResultSet rs = null;try{ con = getConnection(); 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
Jak vypadá typický kód• Kde jsou problémy?
• Často se opakující kód
• Návrhový vzor Copy&Paste
• Uvolnění zdrojů
• Míchání odpovědností
• Vykonání/Zpracování výsledku
Connection con = null;PreparedStatement ps = null;ResultSet rs = null;try{ con = getConnection(); 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
Jak vypadá typický kód• Kde jsou problémy?
• Často se opakující kód
• Návrhový vzor Copy&Paste
• Uvolnění zdrojů
• Míchání odpovědností
• Vykonání/Zpracování výsledku
Connection con = null;PreparedStatement ps = null;ResultSet rs = null;try{ con = getConnection(); 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) {}}
Řešen
í je v
návrh
ovém vz
oru
Template
method
Sunday 13 May 2012
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
JDBC se Springem
Sunday 13 May 2012
Klíčové abstrakce
org.springframework.jdbc.core.JdbcTemplate
org.springframework.jdbc.core.support.JdbcDaoSupport
Sunday 13 May 2012
- resource management- exception handling
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.NamedParameterJdbcTemplate
Sunday 13 May 2012
Ukázky
Sunday 13 May 2012
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"} );
SQL
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
DML a DDLjdbcTemplate.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
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
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
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
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
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.xmlsql-error-codes.xml do rootu classpathzkopirovat z originalu beanu/DB kterou chceme zmenit
Autom. překlad @Repository
@Repositorypublic class ProductDaoImpl implements ProductDao {
// class body here...
}
<beans>
<!-- Exception translation bean post processor --> <bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
<bean class="product.ProductDaoImpl"/>
</beans>
• Post-processor zajišťující automatický překlad vyjímek na @Repository třídách
• PersistenceExceptionTranslationPostProcessor
• vytváří proxy
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
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
Co dál
• BLOB/CLOB handling
• Connection extractor
• Podpora volání stored procedures
• ...
Sunday 13 May 2012
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
Batch updates
batch size=25
Sunday 13 May 2012
Batch updates - JdbcTemplate
Sunday 13 May 2012
BatchSqlUpdate
Sunday 13 May 2012
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
JPA
Sunday 13 May 2012
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
ORM přibližuje oba světy
public class User { private List<Order> orders; private String email; private String name; private Address address; private class Address { private String street; private String zipCode; } }
public class Order { private List<Item> orderItems; private long number; }
public class Item { private long id; private String name; }
Svět objektů
User
Order
Item
1*
1*
Svět relací a tabulek
Sunday 13 May 2012
ORM přibližuje oba světy
public class User { private List<Order> orders; private String email; private String name; private Address address; private class Address { private String street; private String zipCode; } }
public class Order { private List<Item> orderItems; private long number; }
public class Item { private long id; private String name; }
Svět objektů
User
Order
Item
1*
1*
Svět relací a tabulekORM
Sunday 13 May 2012
Agenda
• Představení JPA
• koncepce
• mapování
• dotazy
• Konfigurace EntityManageru
• Implementace JPA DAO
Sunday 13 May 2012
Koncept
• EntityManager
• Reprezentuje jednotku práce
• Umožňuje řídit lifeczcle persistentních objektů
• vznik, aktualizaci, smazání
Sunday 13 May 2012
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
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í
EntityManager API
Metoda v EntityManager API Popis SQL příkaz
persist(Entity instance) Přidání instance entity do PersistenContext insert into table
remove(Entity instance) Odstranění entity z PersistentContext delete from table where id=?
find(Entity class, Primary key) Nahrání podle primárního klíče select * from table where id=?
merge(Entity instance) Aktualizace stavu entity v PersistentContext update table set ... where id=?
createQuery(String jpql) Vytvoří objekt reprezentující dotaz
flush() Vynutí synchronizaci PersistenContext s databází
další metody Transakce, zjištování existence entity atd.
Sunday 13 May 2012
JPA Providers
• Implementace JPA specifikace
• EclipseLink/Toplink
• referenční implementace
• Apache OpenJPA
• Hibernate EntityManager
Sunday 13 May 2012
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
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
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 - excludeSunday 13 May 2012
Jednoduché mapování
Sunday 13 May 2012
Relační mapování
Sunday 13 May 2012
- podporovany vsechny mozne i nemozne způsoby mapování
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ě
Získání entity primarním klíčem
Sunday 13 May 2012
Získání dotazem
Sunday 13 May 2012
Konfigurace EntityManagerFactory ve Springu
• LocalEntityManagerFactoryBean
• LocalContainerEntityManagerFactoryBean
• JNDI lookup
• Všechny vyžadují persisten.xml pro konfiguraci
Sunday 13 May 2012
persistence.xml
• Vždy na classpath v META-INF
• Specifikuje persistence unit a vendor konfiguraci
Sunday 13 May 2012
LocalEntityManagerFactoryBean
• Standalone aplikace, testy
• Nelze specifikovat datasource
• JPA provider určen z• META-INF/services/javax.persistence.spi.PersistenceProvider
Sunday 13 May 2012
LocalContainerEntityManagerFactoryBean
• Plně konfigurovatelné do nejmenších detailů• Datasource a Vendor specific konfigurace
Sunday 13 May 2012
Jak funguje factory beana
Sunday 13 May 2012
JNDI lookup
• EntityManagerFactory se získá z JNDI
• Použití v případe deploymentu do AS
Sunday 13 May 2012
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
Ukázka DAO s překladem výjimek
@Repositorypublic class UserJPADao implements UserDao{
@PersitenceContext private EntityManager entityManager; public void saveUser(User user) { entityManager.persiste(user); }}
Sunday 13 May 2012
• 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