Organogram készítése

Organogram

OrganogramAz Oracle HR sémából építünk organogramot, amivel megjeleníthető a szervezeti hierarchia. Személyenként készítünk csomópontokat. (Másképpen is lehetne: például részlegenként.) A megvalósítás során kétszer konvertálunk A-ból B-be. Először az adatbázisból/adatforrásból SQL lekérdezéssel jutunk hozzá a szükséges adatokhoz, amelyeket generikus listába képezzük le. Ezután a listát feldolgozva generálunk HTML fájlt, amely tartalmaz egy Organization Chart diagramot.

Hasonló feladat: Ki kinek a vezetője?, rekurzív lekérdezéssel. Érdemes összehasonlítani a kétféle szemléletmódot.

Tervezés

Most pedig azt használjuk fel, hogy az Oracle HR sémában az EMPLOYEES táblában reflexió van, amelyet az EMPLOYEE_ID és a MANAGER_ID mezők biztosítanak.

Az Organization Chartnál három adatsor adható meg. Ezek most testre szabva (mindegyik szöveges): 'Employee lastname', 'Job ID', valamint jelmagyarázatként további három mező összefűzve: 'Employee name, Department name, Job title'. Az organogramon megjelenő adatok például: "Raphaely", "PU_MAN", valamint a csomópontra fókuszálva megjelenő tooltip: "Employee: Den Raphaely, Department: Purchasing, Job: Purchasing Manager". A DEPARTMENTS táblából – az EMPLOYEES-zel a DEPARTMENT_ID-vel összekötve – megkapjuk a DEPARTMENT_NAME-t. A JOBS táblából pedig – az EMPLOYEES-zel a JOB_ID-vel összekötve – megkapjuk a JOB_TITLE-t.

A lekérdező parancs

SQL-organogram

Az EMPLOYEE_ID elsődleges kulcs, vagyis kötelező. A MANAGER_ID nem kötelező, a hierarchia tetején álló vezetőnél ez a mező null értékű. Mivel a MANAGER_ID nem kötelező, így külön lekérdező parancsban kell előállítani a 15 középvezetőt együtt a 2 felső vezetővel, valamint az egyetlen felső vezetőt, akinek a MANAGER_ID-ja null. Ezt a két részeredményt össze kell fűzni ( UNION).

Az eredménytábla

SQL-eredménytábla

Az adatfeldolgozás lépései

Java programozási nyelven kötelező a kivételkezelés a JDBC kapcsolatfelvétel, SQL parancs futtatása, valamint a fájlkezelés során. A JDBCConnection interfészben definiált szöveges konstansok: DRIVER, URL, USER, PASSWORD (az adatbázis-szerverrel való kommunikációhoz), SQL (a lefuttatandó lekérdező parancs). Az OrganizationChart interfészbe került a HTML_FILE_PATH (a generálandó HTML fájl Path útvonala) és a HTML (konstans váz az organogram testre szabott HTML+JavaScript forráskódja). Az SQL parancs ResultSet eredménytáblájának feldolgozása során áll elő az orgChartDataList generikus lista. A HTML konstans szövegben lévő #OrgChartData# elemet ki kell cserélni a generikus listából Stream API-val dinamikusan összefűzött adatokra. A fenti példa ide kapcsolódó része: "[{'v':'Raphaely', 'f':'Raphaely<div style="color:red; font-style:bold">PU_MAN</div>'}, 'King', 'Employee: Den Raphaely, Department: Purchasing, Job: Purchasing Manager']". Ezt követően a java.nio csomag Files osztályának write() metódusával fájlba menthető az előállított fájltartalom. A konkrét Java forráskódot most nem részletezem.

Az elkészült organogram

HR-organogram

A bejegyzéshez tartozó teljes forráskódot ILIAS e-learning tananyagban tesszük elérhetővé tanfolyamaink résztvevői számára.

A feladat a Java adatbázis-kezelő tanfolyam 9-12. óra: Oracle HR séma elemzése, 13-16. óra: Konzolos kliensalkalmazás fejlesztése JDBC alapon, 1. rész, 33-36. óra: Grafikus kliensalkalmazás fejlesztése JDBC alapon, 2. rész alkalomhoz kapcsolódik.

Gyűjtsünk össze adatokat névjegykártya készítéshez!

Induljunk ki az Oracle HR sémából!

Az EMPLOYEES táblából szükséges adatok: alkalmazottak neve konkatenálva a FIRST_NAME és LAST_NAME mezőkből, illetve a meglévő elérhetőségek: EMAIL (kiegészítve), PHONE_NUMBER és a hozzáadott WEBSITE. A JOBS táblából szükséges a munkakör megnevezése a JOB_TITLE mezőből, és a részleg neve a DEPARTMENTS tábla DEPARTMENT_NAME mezőből.

Építeni kell a DEPARTMENTS és EMPLOYEES táblák közötti 1:N kapcsolatra (azaz egy adott részlegben több alkalmazott is dolgozik), amelyet a DEPARTMENT_ID mező valósít meg. Nem szükséges az EMPLOYEES és DEPARTMENTS táblák közötti 1:N kapcsolat (azaz egy adott alkalmazott vezetőként több részleget is vezethet). Szükséges a JOBS és az EMPLOYEES táblák közötti 1:N kapcsolat, ami a JOB_ID mezővel valósul meg.

Hasznosak a köztes/átmeneti elnevezések a tábláknál ( D, J, E) és a mezőknél (például EMPLOYEE_NAME) egyaránt. Előbbieknél a mezőnevek minősítéséhez és egyértelmű hivatkozásaihoz kellenek, utóbbinál a metaadatokba kerülnek és utólag kiolvashatók ( ResultSetMetaData) és megjelenítéstől függően tartozhatnak például egy JTable vizuális komponens mögötti DefaultTableModel-hez.

A CONCAT függvénynek két paramétere lehet, ezért csak ott használtam, ahol ez kézenfekvő volt és elegendőnek bizonyult (az EMPLOYEE_NAME-nél nem akartam egymásba ágyazni két CONCAT-ot).

Az első lekérdezés a 107-ből 106 alkalmazott adatait adja vissza.
A második lekérdezés a hiányzó 1 alkalmazott adatai miatt szükséges, akinek nincs beállított részlege ( DEPARTMENT_ID IS NULL). Neki hiányos a COMPANY_DEPARTMENT_NAME adata, de így is egységes lehet az eredménytáblaként kapott adathalmaz (például oszlopok sorrendje és adattípusa).
A két lekérdezés eredményét egyesíteni kell ( UNION).

A lekérdező parancs


A lekérdező utasítást bele kell építeni egy Java kliensprogramba (MVC architekturális tervezési minta szerint a modell rétegbe), ami JDBC alapon kapcsolódik az Oracle adatbázis-szerver HR sémájához olyan felhasználó nevében, aki csatlakozhat és lekérdezhet. Meg kell tervezni és felügyelni kell a biztonságos kapcsolatot (kivételkezeléssel), annak életciklusát (nyit, lekérdez, zár), valamint gondoskodni kell az eredménytábla megjelenítéséről.

A keletkező eredménytábla exportálható Excel-be (XLS, XLSX formátumokba), és kiegészíthető például még egy oszloppal/mezővel (darabszám). Ezután átadható a grafikusnak, aki például felhasználja azt adatforrásként saját névjegykártya tervező szoftverében, vagy használja a Word körlevél varázslóját. Az adatforrás sorrendje ( ORDER BY) megkönnyítheti az elkészült névjegykártyák szétosztását.

A bejegyzéshez tartozó teljes forráskódot ILIAS e-learning tananyagban tesszük elérhetővé tanfolyamaink résztvevői számára.

A feladat a Java SE szoftverfejlesztő tanfolyam 45-48. óra: Adatbázis-kezelés JDBC alapon, 1. rész alkalmához, illetve a Java adatbázis-kezelő tanfolyam 9-12. óra: Oracle HR séma elemzése, 13-16. óra: Konzolos kliensalkalmazás fejlesztése JDBC alapon, 1. rész, 33-36. óra: Grafikus kliensalkalmazás fejlesztése JDBC alapon, 2. rész alkalomhoz kapcsolódik.

Az SQL forráskód formázásához a Free Online SQL Formatter-t használtam.

Ki kinek a vezetője?

Organogram

OrganogramAz SQL lekérdezések újabb típusát adják a hierarchikus lekérdezések. Az Oracle adatbázis-szerver már régóta támogatja ezt a lehetőséget. A hierarchia legtöbbször valamilyen fa adatszerkezethez kötődik. Ezek természetesen nem közvetlenül tárolódnak egy normalizált, relációs adatbázisban, de az adatok közötti kapcsolat értelmezése során felépíthető rekurzív módon a fa struktúra.

Hasonló feladat: Organogram készítése, reflexióra építve. Érdemes összehasonlítani a kétféle szemléletmódot.

Ki kinek a vezetője?

Az Oracle HR sémában az EMPLOYEES és DEPARTMENTS táblák között kétirányú 1:N kapcsolat van. Egy EMPLOYEE_ID egyedi kulccsal azonosított alkalmazotthoz tartozik egy nem kötelező DEPARTMENT_ID külső kulcs az EMPLOYEES táblában. Egy kivétellel minden alkalmazott részleghez hozzárendelt.

Oracle HR séma

Egy DEPARTMENT_ID egyedi kulccsal azonosított részleghez tartozik egy nem kötelező MANAGER_ID külső kulcs a DEPARTMENTS táblában. Minden olyan részlegnek van vezetője, amelyikhez legalább egy alkalmazott hozzárendelt. A DEPARTMENTS táblában csak olyan MANAGER_ID szerepelhet, amelyik megtalálható az EMPLOYEES táblában EMPLOYEE_ID-ként. A „legfelsőbb” szinten lévő vezetőnek nincs vezetője.

Előfordulhat, hogy egy-egy részlegen belül többszintű hierarchiát találunk az organogramban, ha a részlegek helyett az alkalmazottak oldaláról közelítjük meg a problémát. Ekkor építhetünk arra, hogy az EMPLOYEES tábla saját magával is kapcsolatban áll (reflexió): egy MANAGER_ID-hez több EMPLOYEE_ID is tartozhat. Másképpen: egy adott vezetőnek több beosztottja is lehet.

A hierarchikus (rekurzív) lekérdező parancs

Ki kinek a vezetője? - Hierarchikus SQL lekérdező parancs

A lekérdező utasítást bele kell építeni egy Java kliensprogramba (MVC architekturális tervezési minta szerint a modell rétegbe), ami JDBC alapon kapcsolódik az Oracle adatbázis-szerver HR sémájához olyan felhasználó nevében, aki csatlakozhat és lekérdezhet. Meg kell tervezni és felügyelni kell a biztonságos kapcsolatot (kivételkezeléssel), annak életciklusát (nyit, lekérdez, zár), valamint gondoskodni kell az eredménytábla megjelenítéséről.

Az eredménytábla (részlet)

Ki kinek a vezetője? - Eredménytábla

A keletkező eredménytábla exportálható Excel-be (XLS, XLSX formátumokba). Az első vagy utolsó oszlop adatait feldolgozva könnyen készíthető egy dinamikus adatmodellel rendelkező, fa struktúrát megjeleníteni képes komponens/felület, ahol szabadon böngészhető a szervezeti hierarchia.

A bejegyzéshez tartozó teljes forráskódot ILIAS e-learning tananyagban tesszük elérhetővé tanfolyamaink résztvevői számára.

A feladat a Java adatbázis-kezelő tanfolyam 9-12. óra: Oracle HR séma elemzése, 13-16. óra: Konzolos kliensalkalmazás fejlesztése JDBC alapon, 1. rész, 33-36. óra: Grafikus kliensalkalmazás fejlesztése JDBC alapon, 2. rész alkalomhoz kapcsolódik.

Az SQL forráskód formázásához a Free Online SQL Formatter-t használtam.

Tagadós lekérdezések

Tagadós lekérdezések

Tagadós lekérdezésekAz SQL nyelv utasításai többféleképpen csoportosíthatók. Például: adatdefiníciós utasítások (DDL), adatmanipulációs utasítások (DML), lekérdező utasítások (DQL), adatelérést vezérlő nyelv (DCL). A lekérdezések tanítása során másféle rendszerezés is adható. Például a tagadást tartalmazó lekérdezések önálló kategóriát alkothatnak.

Az Oracle HR sémát használjuk és bemutatunk tagadást tartalmazó lekérdezésre öt példát.

Oracle HR séma

1. Kik dolgoznak olyan részlegekben, ahonnan senki sem vett részt korábban projektmunkában?

A DEPARTMENTS és EMPLOYEES táblák között 1:N fokszámú kapcsolat van, és a DEPARTMENT_ID köti össze ezeket. A belső lekérdezés visszaadja azoknak a részlegeknek az azonosítóját ( DEPARTMENT_ID), amelyekből már legalább egyszer legalább egy alkalmazott részt vett korábban projektmunkában (ez most egy 6 elemből álló halmaz). A külső lekérdezésben a NOT IN predikátum – építve a belső lekérdezés eredményeire – megadja azon részlegek nevét ( DEPARTMENT_NAME), illetve az ott dolgozó alkalmazottak nevét ( EMPLOYEE_NAME), ahol az alkalmazotthoz tartozó részleg azonosítója nincs benne a belső lekérdezés által visszaadott eredménytáblában. 5 részlegben 15 alkalmazottra teljesül a feltétel. A NOT IN predikátum adja a tagadást.

SQL-1

Az eredmény:

SQL-1-eredmény

2. Melyek azok a részlegek, ahol nem minden alkalmazott azonos munkakörben dolgozik?

A DEPARTMENTS és EMPLOYEES táblák között 1:N fokszámú kapcsolat van, és a DEPARTMENT_ID köti össze ezeket. A lekérdezés csoportosítást végez részleg azonosítóra és névre ( DEPARTMENT_ID, DEPARTMENT_NAME), és aggregálja – most megszámolja – a csoportban előforduló egyedi munkakör azonosítókat ( JOB_ID), majd ezek közül kihagyja azokat, ahol a megszámolás 1-et ad (másképpen: azokat hagyja meg, ahol a megszámolás különbözik 1-től, 0 nem lehet, igazából 1-nél több) – ez biztosítja a tagadást. 7 részleget kapunk eredményül.

SQL-2

Az eredmény:

3. Kik azok az alkalmazottak, akik az életpálya modell alapján már nem kaphatnak fizetésemelést?

A JOBS és az EMPLOYEES táblák között 1:N fokszámú kapcsolat van, és a JOB_ID köti össze ezeket. Az életpálya modellhez tartozik egy munkakörhöz tartozó minimális és maximális fizetés ( MIN_SALARY és MAX_SALARY). Azok az alkalmazottak listázandók, akiknél a fizetés megegyezik a betöltött munkakörükhöz adható legmagasabb fizetéssel ( SALARY=MAX_SALARY). Ez jelenti a tagadást. Eredményül egyetlen alkalmazottat kapunk.

SQL-3

Az eredmény:

SQL-3-eredmény

4. Kik a nem vezető munkakörben dolgozó alkalmazottak?

A belső lekérdezés 18 olyan alkalmazott vezetőjének azonosítóját ( MANAGER_ID) adja vissza, akik lehetnek részlegvezetők vagy középvezetők. A külső lekérdezés minden olyan alkalmazott azonosítóját és nevét ( EMPLOYEE_ID, EMPLOYEE_NAME) adja vissza, akik nincsenek benne a belső lekérdezés által visszaadott eredményhalmazban. Ez adja a tagadást. Eredményül 89 alkalmazottat kapunk.

SQL-4

Az eredmény:

SQL-4-eredmény

5. Milyen részlegek találhatók nem amerikai régió területén lévő országokban?

A REGIONS, COUNTRIES, LOCATIONS, DEPARTMENTS táblák között balról-jobbra páronként 1:N fokszámú kapcsolat van és ugyanebben a sorrendben a REGION_ID, COUNTRY_ID, LOCATION_ID köti ezeket össze. A belső lekérdezés azért szükséges, mert vannak üres/fiktív részlegek is, amelyeket ki kell hagyni. Az amerikai régió azonosítója 2 ( REGION_ID), ezt adja most a tagadást. Eredményül 3 részleget kapunk 2 országban és 1 régióban.

SQL-5

Az eredmény:

SQL-5-eredmény

A bejegyzéshez tartozó teljes forráskódot ILIAS e-learning tananyagban tesszük elérhetővé tanfolyamaink résztvevői számára.

A feladatok megoldása során nem foglalkoztam külön azzal az egy alkalmazottal, akinek nincs részlege. A feladatok a Java adatbázis-kezelő tanfolyam 13-16. óra: Konzolos kliensalkalmazás fejlesztése JDBC alapon, 1. rész alkalmához és a 33-36. óra: Grafikus kliensalkalmazás fejlesztése JDBC alapon, 1. rész alkalmához kötődnek.

Az SQL forráskód formázásához a Free Online SQL Formatter-t használtam.

Munkakör, létszám, névsor lekérdezése

Az a fela­da­tunk, hogy az Oracle HR sé­má­ból le­kér­dez­ve állít­suk elő munka­kö­rön­ként cso­por­to­sít­va az al­kal­ma­zottak lét­szá­mát és név­so­rát. Adott a JOBS és az EMPLOYEES táb­lák kö­zötti 1:N kap­cso­lat. A JOBS táb­lá­ban (szó­tár) lé­vő JOB_ID egye­di kulcs­hoz tar­to­zik egy hosszabb szö­ve­ges JOB_TITLE le­í­rás (mun­ka­kör), va­la­mint az EMPLOYEES táb­lá­ban meg­ta­lál­ha­tó a JOB_ID kül­ső kulcs­ként. Az EMPLOYEES táb­lá­ban elér­he­tő az al­kal­ma­zottak neve: FIRST_NAME és LAST_NAME. Min­den mun­ka­kört be­tölt leg­alább 1 al­kal­ma­zott és min­den al­kal­ma­zott­hoz van hozzá­ren­delt mun­ka­kör.

Oracle HR séma

Tanfolyamainkon többféleképpen modellezzük és tervezzük meg a feladat megoldását.

Megoldás (Java SE szoftverfejlesztő tanfolyam)

A Java SE szoftverfejlesztő tanfolyam 45-52. óra: Adatbázis-kezelés JDBC alapon alkalmain a következők szerint modellezünk és tervezünk.

Kiindulunk az alábbi egyszerű SQL parancsból:

Munkakör, létszám, névsor SQL-1

Eredményül ezt kapjuk (részlet):

Munkakör, létszám, névsor eredmény 1

A kapott eredménytáblát a Java kliensprogram fejlesztése során leképezzük egy generikus POJO listába, a rekordonként összetartozó 3 adatból előállítva az objektumok tulajdonságait. A generikus listát csoportváltás algoritmussal feldolgozva, könnyen listázzuk a létszámot és a névsort munkakörönként csoportosítva. A munkakörönkénti létszámot a listafeldolgozás során megkapjuk. Ezt most nem részletezzük, de tanfolyamaink hallgatói számára ILIAS e-learning tananyagban tesszük elérhetővé a teljes forráskódot. Ennél a megoldásnál egyszerűbb a lekérdező parancs, de összetett az eredmény feldolgozása.

Megoldás (Java adatbázis-kezelő tanfolyam)

A Java adatbázis-kezelő tanfolyam 9-12. óra: Oracle HR séma elemzése, 13-16. óra: Konzolos kliensalkalmazás fejlesztése JDBC alapon, 1. rész, 33-36. óra: Grafikus kliensalkalmazás fejlesztése JDBC alapon, 2. rész alkalmával a következők szerint modellezünk és tervezünk.

Denormalizált eredményt közvetlenül visszaadni képes összetett SQL parancsot készítünk:

Munkakör, létszám, névsor SQL-2

Eredményül ezt kapjuk (részlet):

Munkakör, létszám, névsor eredmény 2

A kapott eredménytáblát a Java kliensprogram fejlesztése során közvetlenül kiíratjuk, hiszen minden szükséges adatot tartalmaz. Az utolsó oszlopban összefűzve megkapjuk az adott részleghez tartozó alkalmazottak névsorát. Ezt most nem részletezzük, de tanfolyamaink hallgatói számára ILIAS e-learning tananyagban tesszük elérhetővé a teljes forráskódot. Ennél a megoldásnál összetettebb a lekérdező parancs, de egyszerű az eredmény feldolgozása.

Érdemes átgondolni és összehasonlítani a kétféle különböző megközelítés lehetőségeit, korlátait. Ha egyensúlyozni kell a kliensprogram és az adatbázis-szerver terhelése között, valamint az MVC modell összetettsége, karbantarthatósága, könnyen dokumentálhatósága a/is szempont, akkor többféle alternatív módszer is bevethető, valamint építhetünk a különböző Oracle verziók (dialektusok) képességeire is.

Az SQL forráskódok formázásához a Free Online SQL Formatter-t használtam.