Zobrazují se příspěvky se štítkemORM. Zobrazit všechny příspěvky
Zobrazují se příspěvky se štítkemORM. Zobrazit všechny příspěvky

pátek 15. května 2015

Hibernate 4.3.7 patch for schema name customization

The JPA standard allows to hardly define a concrete schema for tables/entites via annotations (for example @Table). For my project was necessary to modify these shema names according to configuration on the realtime, just before EntityManagerFactory is created. Generally, the Hibernate version 4.3.7 provides for a db-to-java name mapping special interface org.hibernate.cfg.naming.NamingStrategyDelegate.

This interface provides lots of nice method for define a mapping between JPA objects names and db objects names, but one thing is missing - schema names customization.

Extending interface

For assurance of backward compatibility, I decided to create new interface as extended existing interface:

package org.hibernate.cfg.naming;
public interface ExtendNamingStrategyDelegate extends NamingStrategyDelegate {
  public String determineSchemaName(String schemaName);
}

Modification of internal behavior of hibernate was not easy. All names modifications is present in very extensive class org.hibernate.cfg.AnnotationBinder. This class contains cca 2800 lines of code and really needs to be refactored :). I added this code fragment on multiple places:

NamingStrategyDelegate n =
  mappings.getNamingStrategyDelegator().getNamingStrategyDelegate(false);

if (n instanceof ExtendNamingStrategyDelegate) {
  schema = ((ExtendNamingStrategyDelegate) n).determineSchemaName(schema);
  if (schema == null) {
    schema = "";
  }
}
If you want to see whole class, please download sourcecode.

Patching of original hibernate

The Hibernate framework is opensource and for building purposes is used the Gradle system. Unfortunately, I haven't any knowledges about Gradle and also our processes in company are hardly maven-oriented. I've decided to do it "dirty" way with 2 maven projects.
  1. hibernate-core-patch (version 4.3.7.1) - contains my created class ExtendNamingStrategyDelegate and modified AnnotationBinder only.  Project version 4.3.7.1 defines that patch is based on hibernate 4.3.7.
  2. hibernate-core (version 4.3.7.1-Patched)- Combination of original hibernate binaries (hibernate-core version 4.3.7) and forced injection of my modifications (hibernate-core-patch 4.3.7.1). This project does not contain any java code and it is defined as a integrator for binaries via maven-dependency-plugin.
Download sourcecode here.

Using of patch

After building and installing patched hibernate-core project, Use in your project patched version of hibernate-core instead of original (replace version 4.3.7 with 4.3.7.1-Patched).

For using NamingStrategyDelegate, please read original documentation

https://docs.jboss.org/hibernate/orm/4.3/manual/en-US/html/ch03.html#configuration-namingstrategy

With difference that you will use ExtendedNamingStrategyDelegate interface.

Summary

I'm not a fan of "raping" of frameworks, tools and standard procedures as shows this article:). But sometimes it can be very usefull and it can save lots of time before you find better way to solve a problem. In this time, Hibernate version 5 is comming and according to release notes, it should be refactored and also support for schema name mapping should be added.


středa 11. března 2015

Práce s časem v Oracle databázi

Ve třetí části série článků o relačních databázích si ukážeme základy práce s časem.
 Databáze poskytuje mnoho funkcí pro práci s časem, v této kapitole se však budeme zabývat jen tím, jak čas a datum získat. Protože problémy způsobují časové zóny, rovněž se zmíním i o této problematice.

V Oracle databázi máme dva časové zdroje: systémový čas a databázový čas.

Sytémový čas


Máme dotaz:

select sysdate, systimestamp, SYS_EXTRACT_UTC(SYSTIMESTAMP) utc from dual;

Výše uvedený dotaz vrací čas operačního systému:

SYSDATE             SYSTIMESTAMP                        UTC                       
------------------- ----------------------------------- ----------------------------
03.03.15 13:26:41   03.03.15 13:26:41,365645000 +01:00  03.03.15 12:26:41,365645000 



Rozdíl mezi sysdate a systimestamp není jen v přesnosti. Důležité je, že sysdate neobsahuje informaci o časové zóně. V okamžiku volání sysdate se aktuální zóna "aplikuje" do hodnoty a ta se pak vrátí v dotazu. Takto zýskaný a ukládány čas může způsobit obrovské problémy:

Příklad
Představte si, že Vaše aplikace vkládá do sloupečku hodnotu SYSDATE pro zaznamání vzniku řádku a db server běží v Praze. Pokud db server přesune do Austrálie - nově vzniklé hodnoty budou ukládány s aplikovaným časovým posunem +11 ale staré hodnoty byly uloženy např. s posunem +2. Pokud tedy vznikly dva řádky v rozmezí 1 minuty ale v jiných zónách (+11 a +2), výpočty nad těmito časy (např. doba mezi vložením dvou záznamů) nebudou odpovídat realitě.

Jak tedy správně ukládat čas (a datum) v databázi? Existují 2 způsoby:
  • Záznam bude uložen včetně časové zóny a pro zjištění se užije SYSTIMESTAMP
  • Záznam bude uložen v UTC (bez časového posunu, +0h).
Právě druhý zminovaný způsob je šetrný na diskový prostor a často i na výkon. K získání času v UTC je ukázáno v třetím sloupečku předchozího příkladu, tedy SYS_EXTRACT_UTC(SYSTIMESTAMP). Nyní je jedno, ve které časové zóně se server nachází, všechny časy budou v UTC.

Pro práci s časem se může hodit časová zóna operačního systému:

select to_char(SYSTIMESTAMP,'TZR') timezone from dual;

Výslekek je pak například

 TIMEZONE                     
--------------------------------
+01:00     


Databázový čas 


S databázovým časem  se pracuje podobně jako se systémovým časem. Hlavní rozdíl je v možnosti nastavení časových zón platných v rámci databáze (tedy ne pro celý operační systém) nebo pro jedno sezení (session).

Analogický dotaz k systémovému času

select CURRENT_DATE,CURRENT_TIMESTAMP,SYS_EXTRACT_UTC(CURRENT_TIMESTAMP) utc from dual;

Výsledek je pro tentokrát zcela totožný se systémovým časem:

 CURRENT_DATE        CURRENT_TIMESTAMP                   UTC                      
------------------- ----------------------------------- ----------------------------
03.03.15 14:10:41   03.03.15 14:10:41,411721000 +01:00  03.03.15 13:10:41,411721000  


Stejne tak zjištění časové zony databáze (aktuálního sezení)

select SESSIONTIMEZONE timezone from dual;

Oproti systémovému času si můžeme nyní časovou zónu upravit podle potřeby:

ALTER SESSION SET TIME_ZONE = '+11:0'; 

Nastavíme si časový posun +11 hod a okamžitě zkusíme opět dotaz k získání času databáze. Můžeme porovnat výsledky:

CURRENT_DATE        CURRENT_TIMESTAMP                   UTC                       
------------------- ----------------------------------- ----------------------------
04.03.15 00:15:23   04.03.15 00:15:23,064275000 +11:00  03.03.15 13:15:23,064275000  


Zatímco UTC čas se nezměnil, hodnota CURRENT_DATE a CURRENT_TIMESTAMP se změnila. U hodnoty CURRENT_TIMESTAMP nám to ovšem nevadí, časová zóna je je součástí hodnoty. Zato však CURRENT_DATE nám bude vracet jiné hodnoty, které (vysvětleno výše na příkladu) nesmí být smýchány s hodnotami před změnou časové zóny.

Závěr

V databázi existuje pochopitelně nepřeberné množství funkcí pro práci s časem. Účelem tohoto článku bylo jen naťuknout tuto problematiku a poukázat na nejpalčivější problém týkající se časových zón. Nyní je již vše na samotném čtenáři, jak se tohoto tématu chopí:) 
Času zdar.



úterý 3. března 2015

Tabulka dual

Z mých zkušeností zná tuto tabulku každý databázový vývojář a v podstatě žádný Java/ORM vývojář, což není překvapující - pokud programujete přímo v databázi, některé konstrukce nejsou bez této tabulky zbytečně obtížné, ne-li nemožné. Pro programátora užívající ORM pak "ztácí" tabulka význam. Slovo "ztrácí" je v uvozovkách oprávněně: Na běžnou práci v ORM skutečně tabulka není potřeba. Pokud chceme databázi používat efektivně a nebo jsme nuceni volat některé databázové funkce přímo, tabulka se nám náramě hodí. 

Tabulka dual je tabulka vlastní všem Oracle databázím a obsahuje typicky  jeden sloupec jménem DUMMY a jeden řádek s hodnotou 'X' typu VARCHAR2(1).
select * from dual;

Proč je tedy tak důležitá? Pomocí této tabulky lze libovolnou hodnotu, literál či výstup funkce převést do relace - t.j. tabulky.

na příklad:

select 'hello world' from dual;
select 1+1 from dual;
select sysdate from dual;

Všechny tyto příklady mají jednu věc společnou - vytvářejí z "ničeho" tabulku. Velmi často se tabulka hodí pro volání databázových funkcí. 

select 1+9/4, trunc(1+9/4),DBMS_RANDOM.RANDOM from dual;

Dotaz ukazuje volání funkce "trunc", jež slouží oříznutí desetinné části z čísla a zároveň volá funkci pro generování náhodného čísla.

Výsledek dotazů je pak třísloupcová tabulka:

1+9/4 TRUNC(1+9/4) RANDOM
----- ------------ ------
 3,25            3 610212023


Z předchozích příkladů je patrný význam tabulky dual: slouží nám jako jakýsi můstek mezi konvenčním procedurálním a relačním přístupem. Článek ukázal nejzákladnější použití tabulky. V dalších dílech bude tabulka využita v mnohem větší míře a její účel bude pak jasnější. Tak zase příště.


pondělí 27. října 2014

Relace a teorie relačních databází

Vítejte v prvním díle ze série kratkých článků o relačních databázích. Seriál je určen především pro vývojáře používající ORM, kteří nemají hlubší znalosti o relačních databázích.
Je třeba ještě zmínit, že v rámci zjednodušení a zrychlení výkladu se můžou v textu vyskytnout drobné formální nedokonalosti či nepřesnosti. Berte proto, prosím, uvedené teorie s nadhledem:)

Pěkně od začátku


Mějme nějakou běžnou, obyčejnou aplikaci:

Tato aplikace se skládá z několika částí:
  • UI - (uživatelské) rozhranní (WEB, GUI, WebServices apod.)
  • BL - business logika a datový model (který musí být persistentní)
  • ORM - vrstva ORM (framework, např. Hibernate)
  • RDB - relační databáze, úložište pro aplikaci
 A tato aplikace může řešit například evidenci zaměstnanců. Její zjednodušený datový model vypadá proto takto:

Nyní nastává ta správná otázka. Jak je v obrázku zakreslena relace (z pohledu relační databáze)?

Pokud je odpověď "relace je přece ta vidlička mezi tabulkama, ten vztah 1 ku N mezi entitami ....", čtěte dále, odpověď není zcela správná.

Proč? provedli jste záměnu dvou relativně podobných (nikoli totožných) pojmů:
  • Pojem "relation", jehož význam se chápe jako přirozený "vztah mezi subjekty" a který vnukne představu "vidličky" v modelu.
  • Pojem "relation", který se běžně překládá jako relace a který se užívá v matematice v teorii množin.
a právě relační databáze vychází z druhého uvedého pojmu. Než se posuneme k relačním databázím, bude vhodné si drobné základy z teorie množin připomenout.

Teorie množin

 

Z teorie množin si velmi lehce rozeberem čtyři pojmy:
  • množina
  • uspořádaná n-tice
  • kartézský součin
  • relace

Množiny není nutné nějak hluboce rozebírat. Mějme např. tyto možiny:
  • A = {“karel”, ”franta”, “pepa”}
  • B = {”franta”, “pepa”, “karel”}
  • C = {“karel”, “pepa”, 1,2}
  • D = {“karel”, “pepa”, 1,1,2}
S množinami je možné provádět různé operace (sjednocení, průnik...), možiny jsou navzájem disjunktní, konjuktní atd. atd.

Důležité jsou však dvě vlastnosti obecných množin:
  • Nezáleží na pořadí prvků v množině (tedy platí A=B).
  • Každý prvek může být v množině max. jednou (tedy platí C=D).
A zde se dostáváme k uspořádaným n-ticím:
Uspořádaná n-tice vypadá na první pohled jako klasická množina, oproti výše popsané množině má právě tyto speciální vlastnosti:
  • Záleží na pořadí prvků v množin.
  • Každý prvek se může v n-tici opakovat.
 Proto pokud bychom měli tyto uspořádané n-tice (zapisované v hranatých závorkách)
  • A = [“karel”, ”franta”, “pepa”]
  • B = [”franta”, “pepa”, “karel”]
  • C = [“karel”, “pepa”, 1,2]
  • D = [“karel”, “pepa”, 1,1,2]
tak v porovnání s množinám již neplatí rovnost A a B, a C a D, což se nám hodí pro vysvětlení dalšího pojmu: kartézský součin.

Kartézksý součin lze poměrně složitě definovat, pro jedoduchost ho popíšem slovně selským rozumem a příkladem:

Kartézksý součin dvou množin A a B je množina uspořádaných dvojic vytvořená jako "každý prvek z A s každým prvkem B".


Příklad 1 (z wikipedie):
pokud A = {x, y, z} a B = {1, 2, 3} pak 
AxB = { [x,1],[x,2],[x,3],[y,1],[y,2],[y,3],[z,1],[z,2],[z,3] }



Další praktičtější příklad (rovněž z wikipedie), který popisuje hrací karty:  
  • A = { sedma, osma, devítka, desítka, spodek, svršek, král, eso} 
  • B = { srdce, listy, kule, žaludy }

Výsledek: 
A × B = {  [sedma,   srdce   ],
       [sedma,   listy   ],
       [sedma,   kule    ],
       [sedma,   žaludy  ],
       [osma,    srdce   ],
        …,
       [eso,     kule    ],
       [eso,     žaludy  ]}.
 
Jak je vidět, kartézský součin nám v tomto případě definoval celý hrací balíček karet, ve kterém je jedna karta tvořená uspořádanou dvojcí [číslo, barva].

Ted je čas na poslední zajímavý pojem, pojem jež dal relačním databázím jméno - relace. Definice je velice jednoduchá a zní:

Relace je podmožina kartézského součinu.
 

 

Samo o sobě to nezní užitečně, ovšem můžem si ukázat nějaké příklady relace z kartézským součinu vytvořeného v předchozím příkladu:

R1 = { [sedma,   srdce    ],
       [devítka, žaludy   ], 

       [svršek,  kule     ]} 

R2 = { [sedma,   srdce    ],
       [devítka, žaludy   ],
       [svršek,  žaludy   ],
       [desítka, kule     ],
       [eso,     kule     ]}

Takto definované relace nám můžou představovat jakoukoliv část balíčku (například karty hráče, talón či nerozdané karty). Důležité je, že relace je množina, takže s ní můžeme formálně provádět operace jako sjednocení. odečtení, porovnání apod.

Pokud se podíváme na relace R1 a R2 příkladu karetních her, možná nám nápadně pripomínají ještě něco - ano, tabulky. Pověstné tabulky které jsou srdcem všech relačních databází, tabulkových procesorů a kostičkových papírů. Relace R1 i R2 vypadají jako tabulky, buď dvě různé a nebo se může jednat o jednu a tu samou tabulku v jiném čase. 

Nyní je čas se podívat zpátky k úvodní otázce ze začátku kapitoly: Jak je v obrázku zakreslená relace (z pohledu relační databáze)? Odpověď je tedy "tabulkou". Již zmíněné "vydličky", tedy vztahy mezi tabulkami, nejsou v původním slova smyslu relace.



Teorie relačních databází, relační algebra


K plnému využití relačních databází je nutné pochopit, na jakém principu byly tyto databáze postaveny. V předchozí části jsme si ukázali, z jakého matematického základu relační databáze čerpají. Nyní se posuneme z matematické teorie do teorie relačních databází.

Základy relačních databází definoval pan Edgar F. Codd kolem roku 1970 ve své práci "A Relational Model of Data for Large Shared Data Banks". V této práci formalizoval relační model, relace (tabulky) a  definoval tzv. relační algebru.


Nemá smysl zacházet příliš do hloubky, je však vhodné uvést operátory relační algebry, které se používají pro práci s relacemi:
  • Selection (výběr, selekce)
  • Projection (projekce)
  • Inner and outer joins (sjednocení)
  • Division (rozdíl)
  • Cartesian product (kartézský součin)
  • Rename (přejmenování )
Vstupem do operátoru jsou relace, výstupem jsou (to je velice důležité) rovněž relace. Díky tomu lze operátory a relace libovolně skládat a řetězit stejně, jako jsme zvyklí u běžných matematických operátoru a vytvořit komplexní výrazy.

Relační algebra je implementována v relační databázi a zapisuje se pomocí SQL takto:

select <projection>
from   <relation>,<relation>… (kartézský součin)
where  <selection>
inner/outer join <relations>
union  <relation> 


Jak je vidět, každý sql dotaz se v databázi interpretuje jako sada relačních operátorů nad tabulkami (relacemi), kde výsledkem je opět relace. SQL dotazy lze tedy libovolně skládat, používat několikásobně vnořené selekty a vůbec provádět všeljaká kouzla.

Závěr


Ukázali jsme si základy teorie množin a relačních databází, čímž jsme si otevřeli cestu do praxe. V dalších dílech se objeví ukázky, které uvedenou teorii maximálně využijí. Příkady budou psány pro databízi Oracle, ale principiálně fungují stejně téměř ve všech relačníc databázích. Tak si je nenechte ujít:)

David

pátek 18. července 2014

ORM skrývá pravou sílu relačních db

Úvod

Přestoupil jsem z dobře zajeté staré firmy pracují tradičním způsobem let devadesátých  (Oracle Forms a RDB, částečně Java1.4 či 5), do mladé, agilnější firmy používající modernější a více sexy nástroje (např. Java7, OSGi, Vaadin...).

Zde bylo krásně vidět, jak se posouvají trendy ve vývoji aplikací a jaký je rozdíl v přemýšlení mladých a starších vývojářů.

Jedním takovým ukázkovým příkladem je použití objektově relačního mapování (ORM):
  • Ve firmě "ze staré školy" se kladl veliký důraz na relační databázi. Systémy byly obvykle psané v PL\SQL a v Javě tak, aby obě technologie byly v symbióze - Náročné datové operace se soustředily do databáze, uživatelské rozhraní do Javy. ORM byl "pouze" druhotný nástroj pro snažší propojení těchto technologií.
  • Naproti tomu nadšení vývojáři v mladé firmě všechny úlohy systému soustředí jen a jen do Javy. ORM se stalo středobodem datové struktury a relační databáze je pouze skrytým úložištěm.
Nemusím ani naznačovat, že v produkčním prostředí se s rostoucími daty začaly vznikat vážné výkonnostní problémy způsobené chybějícími indexy, neefektivními dotazy a někdy i nevhodnými  programátorskými postupy.

A právě to mě přivedlo k zamyšlení se nad příčinou vzniku celé věci:

Automatickým přidáním ORM vrstvy do systému se vývojáři velice zjednodušil svět. Vytvořit a udržovat datový model aplikace se zmenšil na pár anotací v POJO objektu, kde všechno funguje snadno a automaticky. K vývoji stačí několik málo jednoduchých metod typu findByXXX a systém (v laboratorních podmínkách) běží jako po másle. Dochází k jakémusi "přeskočení" principů relační databáze a vkročení rovnou do světa Javy. Pro vývojáře je pohodlnější iterovat a filtrovat nad výsledkem dotazu než napsat takový dotaz, aby dostal do Javy jen minimální potřebné záznamy.

Právě proto jsem se rozhodl v naší firmě provést menší osvětu v podobě školní s ukázkami a předvést i méně zkušeným kolegům, co všechno se dá v relační databázi dělat a k čemu vlastně relační db původně sloužily. 

Výsledkem mého snažení se stala zajímavá sada jednoduchých ukázek, ze kterých bych rád vytvořil krátký seriál.

Jednotlivá témata:

  1. Relace a teorie relačních databází
  2. Tabulka dual
  3. Práce s časem
  4. Hrací karty
  5. Analytické funkce
  6. Rekurze v SQL