Proljetni JDBC

1. Pregled

U ovom ćemo članku proći kroz slučajeve praktične upotrebe modula Spring JDBC.

Svi razredi u proljetnom JDBC podijeljeni su u četiri zasebna paketa:

  • jezgra - osnovna funkcionalnost JDBC-a. Neke od važnih klasa u ovom paketu uključuju JdbcTemplate, SimpleJdbcInsert,SimpleJdbcCall i NamedParameterJdbcTemplate.
  • izvor podataka - klase korisnih programa za pristup izvoru podataka. Također ima različite implementacije izvora podataka za testiranje JDBC koda izvan spremnika EE Jakarte.
  • objekt - DB pristup objektno orijentiranom načinu. Omogućuje izvršavanje upita i vraćanje rezultata kao poslovni objekt. Također mapira rezultate upita između stupaca i svojstava poslovnih objekata.
  • podrška - časovi podrške za nastavu pod jezgra i objekt paketi. Npr. pruža SQLException prevoditeljska funkcionalnost.

2. Konfiguracija

Za početak, krenimo s nekom jednostavnom konfiguracijom izvora podataka (za ovaj ćemo primjer koristiti MySQL bazu podataka):

@Configuration @ComponentScan ("com.baeldung.jdbc") javna klasa SpringJdbcConfig {@Bean public DataSource mysqlDataSource () {DriverManagerDataSource dataSource = novi DriverManagerDataSource (); dataSource.setDriverClassName ("com.mysql.jdbc.Driver"); dataSource.setUrl ("jdbc: mysql: // localhost: 3306 / springjdbc"); dataSource.setUsername ("gost_korisnik"); dataSource.setPassword ("lozinka_gosta"); vratiti dataSource; }}

Alternativno, možemo dobro iskoristiti ugrađenu bazu podataka za razvoj ili testiranje - ovdje je brza konfiguracija koja stvara instancu ugrađene baze podataka H2 i prethodno je popunjava jednostavnim SQL skriptama:

@Bean public DataSource dataSource () {return new EmbeddedDatabaseBuilder () .setType (EmbeddedDatabaseType.H2) .addScript ("classpath: jdbc / schema.sql") .addScript ("classpath: jdbc / test-build.sql"). (); } 

Napokon - isto se, naravno, može učiniti pomoću XML konfiguriranja za izvor podataka:

3. The JdbcTemplate i pokretanje upita

3.1. Osnovni upiti

JDBC predložak glavni je API putem kojeg ćemo pristupiti većini funkcionalnosti koja nas zanima:

  • stvaranje i zatvaranje veza
  • izvršavanje izjava i pohranjenih poziva procedura
  • ponavljanje preko Postavi rezultat i vraćanje rezultata

Prvo, krenimo s jednostavnim primjerom da vidimo što je JdbcTemplate mogu:

int result = jdbcTemplate.queryForObject ("SELECT COUNT (*) FROM EMPLOYEE", Integer.class); 

a ovdje je i jednostavan INSERT:

javni int addEmplyee (int id) {return jdbcTemplate.update ("UMESTI U VRIJEDNOSTI ZAPOSLENIH (?,?,?,?)", id, "Bill", "Gates", "USA"); }

Primijetite standardnu ​​sintaksu pružanja parametara - pomoću znaka `?`. Dalje - pogledajmo alternativu ovoj sintaksi.

3.2. Upiti s imenovanim parametrima

Dobiti podrška za imenovane parametre, koristit ćemo drugi JDBC predložak koji pruža okvir - NamedParameterJdbcTemplate.

Uz to, ovo obavija JbdcTemplate i pruža alternativu tradicionalnoj sintaksi koristeći "?”Za specificiranje parametara. Ispod haube zamjenjuje imenovane parametre u JDBC "?" rezervirano mjesto i delegati u zamotane JDCTemplate za izvršavanje upita:

SqlParameterSource namedParameters = new MapSqlParameterSource (). AddValue ("id", 1); povratak namedParameterJdbcTemplate.queryForObject ("ODABERI FIRST_NAME IZ ZAPOSLENOG GDJE ID =: id", namedParameters, String.class);

Primijetite kako koristimo MapSqlParameterSource kako bi se osigurale vrijednosti za imenovane parametre.

Na primjer, pogledajmo donji primjer koji koristi svojstva graha za određivanje imenovanih parametara:

Zaposlenik zaposlenik = novi zaposlenik (); worker.setFirstName ("James"); Niz SELECT_BY_ID = "ODABERI BROJ (*) OD ZAPOSLENIKA GDJE FIRST_NAME =: firstName"; SqlParameterSource namedParameters = new BeanPropertySqlParameterSource (zaposlenik); vrati namedParameterJdbcTemplate.queryForObject (SELECT_BY_ID, namedParameters, Integer.class);

Primijetite kako sada koristimo BeanPropertySqlParameterSource implementacije umjesto ručnog specificiranja imenovanih parametara kao prije.

3.3. Mapiranje rezultata upita u Java objekt

Još jedna vrlo korisna značajka je sposobnost mapiranja rezultata upita u Java objekte - implementacijom Mapa za redove sučelje.

Na primjer - za svaki redak vraćen upitom Spring koristi mapper reda za popunjavanje java graha:

javna klasa EmployeeRowMapper implementira RowMapper {@Override public Employee mapRow (ResultSet rs, int rowNum) baca SQLException {zaposlenik zaposlenik = novi zaposlenik (); zaposlenik.setId (rs.getInt ("ID")); worker.setFirstName (rs.getString ("FIRST_NAME")); worker.setLastName (rs.getString ("LAST_NAME")); worker.setAddress (rs.getString ("ADDRESS")); povratak zaposlenika; }}

Nakon toga sada možemo proslijediti mapiranje redaka API-ju upita i dobiti potpuno naseljene Java objekte:

String query = "SELECT * FROM EMPLYYE WHERE ID =?"; Zaposlenik zaposlenik = jdbcTemplate.queryForObject (upit, novi Object [] {id}, novi EmployeeRowMapper ());

4. Prijevod iznimke

Proljeće dolazi s vlastitom hijerarhijom izuzetaka podataka koja se isporučuje s okvirom DataAccessException kao korijenska iznimka - i u nju prevodi sve temeljne sirove iznimke.

I tako održavamo zdrav razum ne morajući se nositi s iznimkama upornosti na niskoj razini i koristimo činjenicom da Proljeće umotava iznimke na niskoj razini u DataAccessException ili jedna od njegovih podrazreda.

Također, ovo zadržava mehanizam rukovanja iznimkama neovisno o osnovnoj bazi podataka koju koristimo.

Osim toga, zadani SQLErrorCodeSQLExceptionTranslator, također možemo osigurati vlastitu implementaciju SQLExceptionTranslator.

Evo kratkog primjera prilagođene implementacije, prilagođavanja poruke o pogrešci kada postoji duplicirano kršenje ključa, što rezultira kodom pogreške 23505 kada se koristi H2:

javna klasa CustomSQLErrorCodeTranslator proširuje SQLErrorCodeSQLExceptionTranslator {@Override zaštićen DataAccessException customTranslate (zadatak niza, String sql, SQLException sqlException) {if (sqlException.getErrorCode5) Izjeta-pretplataExceptionExceptionTextExceptionDececertExceptionTextExceptionTextExceptionTextExt ); } return null; }}

Da bismo koristili ovaj prilagođeni prevoditelj iznimki, moramo ga proslijediti na JdbcTemplate pozivanjem setExceptionTranslator () metoda:

CustomSQLErrorCodeTranslator customSQLErrorCodeTranslator = novi CustomSQLErrorCodeTranslator (); jdbcTemplate.setExceptionTranslator (customSQLErrorCodeTranslator);

5. JDBC operacije pomoću klasa SimpleJdbc

SimpleJdbc klase pružaju jednostavan način konfiguriranja i izvršavanja SQL izraza. Te klase koriste metapodatke baze podataka za izgradnju osnovnih upita. SimpleJdbcInsert i SimpleJdbcCall klase pružaju lakši način izvođenja poziva umetnutih i pohranjenih procedura.

5.1. SimpleJdbcInsert

Pogledajmo izvršavanje jednostavnih izjava za umetanje s minimalnom konfiguracijom.

Izjava INSERT generira se na temelju konfiguracije SimpleJdbcInsert i sve što trebamo je navesti naziv tablice, nazive stupaca i vrijednosti.

Prvo, izradimo a SimpleJdbcInsert:

SimpleJdbcInsert simpleJdbcInsert = novo SimpleJdbcInsert (dataSource) .withTableName ("EMPLOYEE");

Dalje, navedimo imena i vrijednosti stupaca i izvršimo operaciju:

public int addEmplyee (Employee emp) {Parametri mape = novi HashMap (); parameters.put ("ID", emp.getId ()); parameters.put ("FIRST_NAME", emp.getFirstName ()); parameters.put ("LAST_NAME", emp.getLastName ()); parameters.put ("ADDRESS", emp.getAddress ()); vrati simpleJdbcInsert.execute (parametri); }

Nadalje, dopustiti baza podataka za generiranje primarnog ključa, možemo iskoristiti executeAndReturnKey () API; trebat ćemo konfigurirati i stvarni stupac koji se automatski generira:

SimpleJdbcInsert simpleJdbcInsert = novo SimpleJdbcInsert (dataSource) .withTableName ("EMPLOYEE") .usingGeneratedKeyColumns ("ID"); Broj id = simpleJdbcInsert.executeAndReturnKey (parametri); System.out.println ("Generirani id -" + id.longValue ());

Konačno - ove podatke možemo proslijediti i pomoću BeanPropertySqlParameterSource i MapSqlParameterSource.

5.2. Pohranjeni postupci s SimpleJdbcCall

Također, pogledajmo izvršavanje pohranjenih procedura - iskoristit ćemo SimpleJdbcCall apstrakcija:

SimpleJdbcCall simpleJdbcCall = novi SimpleJdbcCall (izvor podataka) .withProcedureName ("READ_EMPLOYEE"); 
javni Employee getEfficieeUsingSimpleJdbcCall (int id) {SqlParameterSource in = new MapSqlParameterSource (). addValue ("in_id", id); Karta van = simpleJdbcCall.execute (in); Zaposlenik emp = novi zaposlenik (); emp.setFirstName ((Niz) out.get ("FIRST_NAME")); emp.setLastName ((String) out.get ("LAST_NAME")); vratiti emp; }

6. Šaržne operacije

Još jedan jednostavan slučaj upotrebe - skupljanje više operacija zajedno.

6.1. Osnovne batch operacije pomoću JdbcTemplate

Koristeći JdbcTemplate, skupne operacije može se izvršiti putem batchUpdate () API.

Ovdje je zanimljiv jezgrovit, ali vrlo koristan BatchPreparedStatementSetter provedba:

public int [] batchUpdateUsingJdbcTemplate (Popis zaposlenika) {return jdbcTemplate.batchUpdate ("INSERT IN TO EMPLOYE VALUES (?,?,?,?)", new BatchPreparedStatementSetter () {@Override public void setValuceQ, Prepared iSepleStalueQ, Prepared inSetVacesQ {ps.setInt (1, zaposlenici.get (i) .getId ()); ps.setString (2, zaposlenici.get (i) .getFirstName ()); ps.setString (3, zaposlenici.get (i). getLastName ()); ps.setString (4, zaposlenici.get (i) .getAddress ();} @Override public int getBatchSize () {return 50;}});}

6.2. Skupne operacije pomoću NamedParameterJdbcTemplate

Također imamo mogućnost doziranja sa NamedParameterJdbcTemplatebatchUpdate () API.

Ovaj je API jednostavniji od prethodnog - nema potrebe za implementacijom dodatnih sučelja za postavljanje parametara, jer ima unutarnji pripremljeni postavljač izraza za postavljanje vrijednosti parametara.

Umjesto toga, vrijednosti parametara mogu se proslijediti u batchUpdate () metoda kao niz od SqlParameterSource.

SqlParameterSource [] batch = SqlParameterSourceUtils.createBatch (zaposlenici.toArray ()); int [] updateCounts = namedParameterJdbcTemplate.batchUpdate ("INSERT IN TO EMPLOYE VALUES (: id,: firstName,: lastName,: address)", batch); vratiti updateCounts;

7. Proljetni JDBC s proljetnim čizmom

Spring Boot nudi starter opruga-čizma-starter-jdbc za upotrebu JDBC-a s relacijskim bazama podataka.

Kao i kod svakog pokretača Spring Boot-a, i ovaj nam pomaže u brzom pokretanju i pokretanju aplikacije.

7.1. Ovisnost Mavena

Trebat će nam opruga-čizma-starter-jdbc ovisnost kao primarnu, kao i ovisnost baze podataka koju ćemo koristiti. U našem slučaju, ovo je MySQL:

 org.springframework.boot spring-boot-starter-jdbc mysql mysql-connector-java runtime 

7.2. Konfiguracija

Spring Boot automatski konfigurira izvor podataka za nas. Samo trebamo osigurati svojstva u a Svojstva datoteka:

spring.datasource.url = jdbc: mysql: // localhost: 3306 / springjdbc spring.datasource.username = gost_korisnik spring.datasource.password = guest_password

To je to, samo radeći samo ove konfiguracije, naša je aplikacija pokrenuta i možemo je koristiti za druge operacije baze podataka.

Eksplicitna konfiguracija koju smo vidjeli u prethodnom odjeljku za standardnu ​​aplikaciju Spring je sada uključena kao dio automatske konfiguracije Spring Boot.

8. Zaključak

U ovom smo članku pogledali JDBC apstrakciju u Spring Framework-u, pokrivajući različite mogućnosti koje pruža Spring JDBC s praktičnim primjerima.

Također, ispitali smo kako možemo brzo započeti s Spring JDBC-om pomoću Spring Boot JDBC startera.

Izvorni kod za primjere dostupan je na GitHubu.