61
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

Spring dao

Embed Size (px)

DESCRIPTION

 

Citation preview

Page 1: Spring dao

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

Page 2: Spring dao

Přístup k datůmJak efektivně používat Spring framework pro přístup k datům

Sunday 13 May 2012

Page 3: Spring dao

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

Page 4: Spring dao

Definice datového zdroje

Sunday 13 May 2012

Page 5: Spring dao

• 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

Page 6: Spring dao

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)

Page 7: Spring dao

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

Page 8: Spring dao

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

Page 9: Spring dao

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

Page 10: Spring dao

JDBC

Sunday 13 May 2012

Page 11: Spring dao

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

Page 12: Spring dao

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

Page 13: Spring dao

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

Page 14: Spring dao

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

Page 15: Spring dao

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

Page 16: Spring dao

JDBC se Springem

Sunday 13 May 2012

Page 17: Spring dao

Klíčové abstrakce

org.springframework.jdbc.core.JdbcTemplate

org.springframework.jdbc.core.support.JdbcDaoSupport

Sunday 13 May 2012

- resource management- exception handling

Page 18: Spring dao

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

Page 19: Spring dao

Ukázky

Sunday 13 May 2012

Page 20: Spring dao

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

Page 21: Spring dao

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

Page 22: Spring dao

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

Page 23: Spring dao

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

Page 24: Spring dao

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

Page 25: Spring dao

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

Page 26: Spring dao

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

Page 27: Spring dao

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

Page 28: Spring dao

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

Page 29: Spring dao

Co dál

• BLOB/CLOB handling

• Connection extractor

• Podpora volání stored procedures

• ...

Sunday 13 May 2012

Page 30: Spring dao

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

Page 31: Spring dao

Batch updates

batch size=25

Sunday 13 May 2012

Page 32: Spring dao

Batch updates - JdbcTemplate

Sunday 13 May 2012

Page 33: Spring dao

BatchSqlUpdate

Sunday 13 May 2012

Page 34: Spring dao

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

Page 35: Spring dao

JPA

Sunday 13 May 2012

Page 36: Spring dao

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

Page 37: Spring dao

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

Page 38: Spring dao

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

Page 39: Spring dao

Agenda

• Představení JPA

• koncepce

• mapování

• dotazy

• Konfigurace EntityManageru

• Implementace JPA DAO

Sunday 13 May 2012

Page 40: Spring dao

Koncept

• EntityManager

• Reprezentuje jednotku práce

• Umožňuje řídit lifeczcle persistentních objektů

• vznik, aktualizaci, smazání

Sunday 13 May 2012

Page 41: Spring dao

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

Page 42: Spring dao

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í

Page 43: Spring dao

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

Page 44: Spring dao

JPA Providers

• Implementace JPA specifikace

• EclipseLink/Toplink

• referenční implementace

• Apache OpenJPA

• Hibernate EntityManager

Sunday 13 May 2012

Page 45: Spring dao

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

Page 46: Spring dao

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

Page 47: Spring dao

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

Page 48: Spring dao

Jednoduché mapování

Sunday 13 May 2012

Page 49: Spring dao

Relační mapování

Sunday 13 May 2012

- podporovany vsechny mozne i nemozne způsoby mapování

Page 50: Spring dao

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ě

Page 51: Spring dao

Získání entity primarním klíčem

Sunday 13 May 2012

Page 52: Spring dao

Získání dotazem

Sunday 13 May 2012

Page 53: Spring dao

Konfigurace EntityManagerFactory ve Springu

• LocalEntityManagerFactoryBean

• LocalContainerEntityManagerFactoryBean

• JNDI lookup

• Všechny vyžadují persisten.xml pro konfiguraci

Sunday 13 May 2012

Page 54: Spring dao

persistence.xml

• Vždy na classpath v META-INF

• Specifikuje persistence unit a vendor konfiguraci

Sunday 13 May 2012

Page 55: Spring dao

LocalEntityManagerFactoryBean

• Standalone aplikace, testy

• Nelze specifikovat datasource

• JPA provider určen z• META-INF/services/javax.persistence.spi.PersistenceProvider

Sunday 13 May 2012

Page 56: Spring dao

LocalContainerEntityManagerFactoryBean

• Plně konfigurovatelné do nejmenších detailů• Datasource a Vendor specific konfigurace

Sunday 13 May 2012

Page 57: Spring dao

Jak funguje factory beana

Sunday 13 May 2012

Page 58: Spring dao

JNDI lookup

• EntityManagerFactory se získá z JNDI

• Použití v případe deploymentu do AS

Sunday 13 May 2012

Page 59: Spring dao

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

Page 60: Spring dao

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

Page 61: Spring dao

• 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