Vrste SQL pridruživanja

1. Uvod

U ovom uputstvu prikazat ćemo različite vrste SQL pridruživanja i kako ih je lako implementirati u Javi.

2. Definiranje modela

Počnimo s izradom dvije jednostavne tablice:

STVARI AUTORA TABLE (ID int NIJE NULL PRIMARNI KLJUČ, FIRST_NAME varchar (255), LAST_NAME varchar (255)); STVARI ČLANAK TABLE (ID int NIJE NULL PRIMARNI KLJUČ, NASLOV varchar (255) NIJE NULL, AUTHOR_ID int, STRANI KLJUČ (AUTHOR_ID) REFERENCE AUTOR (ID)); 

I napunite ih nekim testnim podacima:

UMESTI U AUTORSKE VRIJEDNOSTI (1, 'Siena', 'Kerr'), (2, 'Daniele', 'Ferguson'), (3, 'Luciano', 'Wise'), (4, 'Jonas', 'Lugo' ); INSERT IN TO ARTICLE VALUES (1, 'First steps in Java', 1), (2, 'SpringBoot tutorial', 1), (3, 'Java 12 insights', null), (4, 'SQL JOINS', 2) , (5, 'Uvod u proljetnu sigurnost', 3);

Imajte na umu da u našem uzorku podataka nemaju svi autori članaka i obrnuto. Ovo će igrati veliku ulogu u našim primjerima, koje ćemo vidjeti kasnije.

Definirajmo i POJO koji ćemo koristiti za spremanje rezultata JOIN operacija u cijelom našem vodiču:

class ArticleWithAuthor {naslov privatnog niza; private String authorFirstName; private String authorLastName; // standardni konstruktor, postavljači i dobivači}

U našim ćemo primjerima iz tablice ARTICLE izvući naslov, a iz tablice AUTHOR podatke o autorima.

3. Konfiguracija

Za naše primjere upotrijebit ćemo vanjsku bazu podataka PostgreSQL koja radi na portu 5432. Osim PUNOG PRIDRUŽIVANJA, koji nije podržan ni u MySQL-u ni u H2, svi pruženi isječci trebali bi raditi s bilo kojim SQL dobavljačem.

Za našu implementaciju Jave trebat će nam PostgreSQL upravljački program:

 org.postgresql postgresql 42.2.5 test 

Prvo konfigurirajmo a java.sql.Connection za rad s našom bazom podataka:

Class.forName ("org.postgresql.Driver"); Veza veze = DriverManager. getConnection ("jdbc: postgresql: // localhost: 5432 / myDb", "user", "pass");

Dalje, kreirajmo klasu DAO i neke korisne metode:

class ArticleWithAuthorDAO {privatna konačna veza veze; // konstruktor privatni popis ExecuteQuery (String upit) {try (Statement statement = connection.createStatement ()) {ResultSet resultSet = statement.executeQuery (query); vratiti mapToList (resultSet); } catch (SQLException e) {e.printStackTrace (); } vrati novi ArrayList (); } privatni popis mapToList (ResultSet resultSet) baca SQLException {Popis popisa = novi ArrayList (); while (resultSet.next ()) {ArticleWithAuthor articleWithAuthor = new ArticleWithAuthor (resultSet.getString ("TITLE"), resultSet.getString ("FIRST_NAME"), resultSet.getString ("LAST_NAME")); list.add (articleWithAuthor); } popis za povratak; }}

U ovom članku nećemo ulaziti u detalje o upotrebi Skup rezultata, Izjava, i Veza. Te su teme obrađene u našim člancima vezanim uz JDBC.

Počnimo s istraživanjem SQL pridruživanja u odjeljcima ispod.

4. Unutarnje pridruživanje

Počnimo s vjerojatno najjednostavnijom vrstom spajanja. UNUTARNJE PRIDRUŽIVANJE operacija je koja iz obje tablice odabire retke koji odgovaraju zadanom stanju. Upit se sastoji od najmanje tri dijela: odabir stupaca, spajanje tablica i uvjet pridruživanja.

Imajući to na umu, sama sintaksa postaje prilično jednostavna:

ODABERITE ARTICLE.TITLE, AUTHOR.LAST_NAME, AUTHOR.FIRST_NAME IZ ARTICLE INNER PRIDRUŽITE SE AUTORU NA AUTHOR.ID = ARTICLE.AUTHOR_ID

Također možemo ilustrirati rezultat UNUTARNJE PRIDRUŽIVANJE kao zajednički dio skupova koji se sijeku:

Primijenimo sada metodu za UNUTARNJO PRIDRUŽIVANJE u ArticleWithAuthorDAO razred:

Popis članakaInnerJoinAuthor () {String query = "SELECT ARTICLE.TITLE, AUTHOR.LAST_NAME, AUTHOR.FIRST_NAME" + "FROM ARTICLE INNER PRIDRUŽITE SE AUTORU NA AUTHOR.ID = ARTICLE.AUTHOR_ID"; povratak executeQuery (upit); }

I isprobajte:

@Test javna void whenQueryWithInnerJoin_thenShouldReturnProperRows () 

Kao što smo već spomenuli, INNER JOIN odabire samo uobičajene retke prema navedenom stanju. Gledajući naše umetke, vidimo da imamo jedan članak bez autora i jedan autor bez članka. Ovi se redovi preskaču jer ne ispunjavaju navedeni uvjet. Kao rezultat, dohvaćamo četiri spojena rezultata, a niti jedan nema prazne podatke o autorima niti prazan naslov.

5. Lijevo pridruživanje

Dalje, usredotočimo se na LIJEVO PRIDRUŽIVANJE. Ova vrsta spajanja odabire sve retke iz prve tablice i podudara se s odgovarajućim redovima iz druge tablice. Kad nema podudaranja, stupci se popunjavaju s null vrijednosti.

Prije nego što krenemo u implementaciju Jave, pogledajmo grafički prikaz LIJEVOG PRIDRUŽIVANJA:

U ovom slučaju, rezultat LEFT JOIN uključuje svaki zapis iz skupa koji predstavlja prvu tablicu s vrijednostima koje se sijeku iz druge tablice.

Sada, prijeđimo na implementaciju Jave:

Popis članakaLeftJoinAuthor () {String query = "SELECT ARTICLE.TITLE, AUTHOR.LAST_NAME, AUTHOR.FIRST_NAME" + "FROM ARTICLE LEFT PRIDRUŽITE SE AUTORU NA AUTHOR.ID = ARTICLE.AUTHOR_ID"; povratak executeQuery (upit); }

Jedina razlika u odnosu na prethodni primjer je ta što smo umjesto ključne riječi INNER koristili ključnu riječ LIJEVO.

Prije nego što testiramo našu metodu LIJEVOG PRIDRUŽIVANJA, pogledajmo ponovno naše umetke. U ovom ćemo slučaju dobiti sve zapise iz tablice ARTICLE i njihove odgovarajuće retke iz tablice AUTHOR. Kao što smo već spomenuli, još nema svaki članak autora, pa očekujemo da ima null vrijednosti umjesto podataka o autoru:

@Test public void whenQueryWithLeftJoin_thenShouldReturnProperRows () {List articleWithAuthorList = articleWithAuthorDAO.articleLeftJoinAuthor (); assertThat (articleWithAuthorList) .hasSize (5); assertThat (articleWithAuthorList) .anyMatch (redak -> redak.getAuthorFirstName () == null); }

6. Pravo pridruživanje

DESNO PRIDRUŽIVANJE je slično LIJEVOM PRIDRUŽENJU, ali vraća sve retke iz druge tablice i podudara se s retcima iz prve tablice. Kao u slučaju LIJEVOG PRIDRUŽIVANJA, prazne šibice zamjenjuju se sa null vrijednosti.

Grafički prikaz ove vrste spajanja zrcalni je odraz onog koji smo ilustrirali LIJEVIM PRIDRUŽIVANJEM:

Primijenimo PRAVO PRIDRUŽIVANJE u Javi:

Popis članakaRightJoinAuthor () {String query = "SELECT ARTICLE.TITLE, AUTHOR.LAST_NAME, AUTHOR.FIRST_NAME" + "FROM ARTICLE DESNO PRIDRUŽITE SE AUTORU NA AUTHOR.ID = ARTICLE.AUTHOR_ID"; povratak executeQuery (upit); }

Ponovno, pogledajmo naše testne podatke. Budući da ova operacija pridruživanja dohvaća sve zapise iz druge tablice, očekujemo dohvaćanje pet redaka, a budući da nije svaki autor već napisao članak, očekujemo neke null vrijednosti u stupcu TITLE:

@Test javna void whenQueryWithRightJoin_thenShouldReturnProperRows () {List articleWithAuthorList = articleWithAuthorDAO.articleRightJoinAuthor (); assertThat (articleWithAuthorList) .hasSize (5); assertThat (articleWithAuthorList) .anyMatch (redak -> redak.getTitle () == null); }

7. Potpuno vanjsko pridruživanje

Ova operacija spajanja je vjerojatno najzaslužnija. FULL JOIN odabire sve retke i iz prve i iz druge tablice, bez obzira je li uvjet zadovoljen ili ne.

Također možemo predstaviti istu ideju kao i sve vrijednosti iz svakog skupa koji se sijeku:

Pogledajmo implementaciju Jave:

Popis članakaOuterJoinAuthor () {String query = "SELECT ARTICLE.TITLE, AUTHOR.LAST_NAME, AUTHOR.FIRST_NAME" + "FROM ARTICLE FULL PRIDRUŽITE SE AUTORU NA AUTORU.ID = ARTICLE.AUTHOR_ID"; povratak executeQuery (upit); }

Sada možemo testirati našu metodu:

@Test public void whenQueryWithFullJoin_thenShouldReturnProperRows () {List articleWithAuthorList = articleWithAuthorDAO.articleOuterJoinAuthor (); assertThat (articleWithAuthorList) .hasSize (6); assertThat (articleWithAuthorList) .anyMatch (redak -> redak.getTitle () == null); assertThat (articleWithAuthorList) .anyMatch (redak -> redak.getAuthorFirstName () == null); }

Još jednom, pogledajmo podatke o ispitivanju. Imamo pet različitih članaka, od kojih jedan nema autora, i četiri autora, od kojih jedan nema dodijeljeni članak. Kao rezultat PUNOG PRIDRUŽIVANJA očekujemo dohvaćanje šest redaka. Četiri se međusobno podudaraju, a preostala dva nisu. Iz tog razloga, također pretpostavljamo da će postojati barem jedan redak s null vrijednosti u oba stupca podataka AUTHOR i onom s a null vrijednost u stupcu TITLE.

8. Zaključak

U ovom smo članku istražili osnovne tipove SQL pridruživanja. Pogledali smo primjere četiri vrste pridruživanja i kako se oni mogu implementirati u Javi.

Kao i uvijek, cjeloviti kôd korišten u ovom članku dostupan je na GitHubu.


$config[zx-auto] not found$config[zx-overlay] not found