Stáhnout prezentaci
Prezentace se nahrává, počkejte prosím
ZveřejnilTerezie Sedláková
1
Identity Field Radim Veselý ČVUT v Praze 28. 4. 2013Radim Veselý ČVUT v Praze 28. 4. 2013 Michal Kouřík ČVUT v Praze 13.4.2014
2
Identity Field– úvod Návrhový vzor patřící do skupiny ORM design patterns Problém Zapsání dat do databáze – potřebujeme jasně namapovat řádek v databázi na objekt v paměti Jak na to? Vybrat vhodný klíč a uložit ho jako atribut třídy
3
Výběr klíče Meaningful / meaningless key Simple / compound key Table-unique / database-unique key Vždy pouze jedno ID pro danou hierarchii tříd (Concrete Table Inheritance) Typ klíče Simple – stejný typ jako je v databázi Compound – řešit přes samostatný objekt
4
Implementace – simple key class DomainObject { private long PLACEGOLDER_ID = -1; private long id = PLACEHOLDER_ID; public Boolean isNew() { return id == PLACEHOLDER_ID; }
5
Implementace – compound key class DomainObject { private Key key; protected DomainObject(Key ID) { this.key = ID; } public Key getKey() { return this.key; } public void setKey(Key key) { this.key = key; } class Key { private Object[] fields; public Key(Object[] fields) { this.fields = fields; }
6
Získání hodnoty klíče Předat zodpovědnost databázi Nejjednodušší, nic neřeším, databáze ID vygeneruje při insertu Problém – každý databázový stroj může mít implementováno jinak – problém s ORM Auto-generated field Nejběžnější Sekvence Nemusí být dostupná na všech DB strojích GUID Používat s rozvahou – příliš velký, špatně se s ním pracuje {25892e17-80f6-415f-9c65-7395632f0223}
7
Implementace – key table Tabulka obsahující další ID v řadě pro každou tabulku CREATE TABLE keys (name varchar primary key, nextID int); INSERT INTO keys VALUES (‘orders’, 1); CREATE TABLE keys (name varchar primary key, nextID int) INSERT INTO keys VALUES ('orders', 1)
8
Příklad z praxe - JPA @MappedSuperclass public abstract class DomainObject implements Serializable { private static final long serialVersionUID = -7869764477108781793L; @Id @GeneratedValue(strategy = GenerationType.AUTO, generator = “id_generator”) @Column(unique = true, nullable = false) private Long id; // getters & setters & hashcode & equals metody }
9
Shrnutí Základní stavební kámen pro veškeré aplikace ukládající do DB Jakou implementaci? Ve valné většině si vystačíme s jednoduchým klíčem typu long Související vzory Identity Map Domain Model Row Data Gateway
10
Dependent mapping
11
Dependent mapping – úvod Problém práce s databází spíš než objektový vzor ukládání kolekcí do databáze entity kolekce jsou jednoduché z hlediska vztahů (váží se pouze k jedinému objektu) snažíme se o minimalistické řešení Příklad: ukládání písniček k albu vybavení auta (rezerva, žárovky...) Jak na to? entity kolekce nemají vlastní ID nemají smysl samy o sobě při práci s entitami přistupujeme přes vlastníka kolekce
12
Dependent mapping – struktura - příklad Závislý objekt Databáze Vlastník Mapovací třída
13
Dependent mapping – účastníci Vlastník (owner) třída obsahující kolekci entity mají ID Závislý (dependent) třída tvořící entity kolekce entity nemají ID přistupuji k nim přes vlastníka můžou být imutabilní Mapovací třáda (mapper) obstarává komunikaci s db a spravuje kolekci
14
Dependent mapping – implementace Nahrávání kolekce většinou probíhá zároveň s vlastníkem při vyšší ceně nahrávání lazy load ID entity kolekce neosahují ID, musíme s tím počítat Hierarchie Key u závislé classy se používá composite Update vzhledem k tomu, že nemáme ID, tak updatujeme přes delete & insert při změně entity kolekce měníme vlastníka
15
Dependent mapping – implementace – model, find class Track { private final String title; public Track(String title) { this.title = title; } public String getTitle() { return title; } class Album { private List tracks = new ArrayList(); public void addTrack(Track arg) { tracks.add(arg); } public void removeTrack(Track arg) { tracks.remove(arg); }; public void removeTrack(int i) { tracks.remove(i); } public Track[] getTracks() { return (Track[]) tracks.toArray(new Track[tracks.size()]); } class AlbumMapper { protected String findStatement() { return "SELECT ID, a.title, t.title as trackTitle" + " FROM albums a, tracks t" + " WHERE a.ID = ? AND t.albumID = a.ID" + " ORDER BY t.seq"; }
16
Dependent mapping – implementace - load class AlbumMapper { protected DomainObject doLoad(Long id, ResultSet rs) throws SQLException { String title = rs.getString(2); Album result = new Album(id, title); loadTracks(result, rs); return result; } public void loadTracks(Album arg, ResultSet rs) throws SQLException { arg.addTrack(newTrack(rs)); while (rs.next()) { arg.addTrack(newTrack(rs)); } private Track newTrack(ResultSet rs) throws SQLException { String title = rs.getString(3); Track newTrack = new Track (title); return newTrack; }
17
Dependent mapping – implementace - update public void update(DomainObject arg) { PreparedStatement updateStatement = null; try { updateStatement = DB.prepare("UPDATE albums SET title = ? WHERE id = ?"); updateStatement.setLong(2, arg.getID().longValue()); Album album = (Album) arg; updateStatement.setString(1, album.getTitle()); updateStatement.execute(); updateTracks(album); } catch (SQLException e) { throw new ApplicationException(e); } finally {DB.cleanUp(updateStatement); } public void updateTracks(Album arg) throws SQLException { PreparedStatement deleteTracksStatement = null; try { deleteTracksStatement = DB.prepare("DELETE from tracks WHERE albumID = ?"); deleteTracksStatement.setLong(1, arg.getID().longValue()); deleteTracksStatement.execute(); for (int i = 0; i < arg.getTracks().length; i++) { Track track = arg.getTracks()[i]; insertTrack(track, i + 1, arg); } } finally {DB.cleanUp(deleteTracksStatement); }
18
Dependent mapping – implementace - update public void insertTrack(Track track, int seq, Album album) throws SQLException { PreparedStatement insertTracksStatement = null; try { insertTracksStatement = DB.prepare("INSERT INTO tracks (seq, albumID, title) VALUES (?, ?, ?)"); insertTracksStatement.setInt(1, seq); insertTracksStatement.setLong(2, album.getID().longValue()); insertTracksStatement.setString(3, track.getTitle()); insertTracksStatement.execute(); } finally {DB.cleanUp(insertTracksStatement); }
19
Dependent mapping – shrnutí Plusy zjednodušení entit pracujeme na „vyšší vrstvě“ Mínusy práce s tvorbou mapping class nepříjemnosti spojené s absencí ID omezení (pouze jeden vlastník, žádné jiné reference)
20
Dependent mapping – související vzory Identity Field entity obsahují ID Active record, Row Date Gateway mapování je prováděno pomocí vlastníka Value Object entity také nemají ID, porovnáváme podle obsahu neřeší chování vůči db Unit Of Work pro úpravu objektů používám pouze metody, které zaštiťují skupinu procesů neřeší vztahy mezi objekty z pohledu db
Podobné prezentace
© 2024 SlidePlayer.cz Inc.
All rights reserved.