Co to jest JDBC? Wprowadzenie do łączności z bazą danych Java

JDBC (Java Database Connectivity) to interfejs API języka Java, który zarządza łączeniem się z bazą danych, wysyłaniem zapytań i poleceń oraz obsługą zestawów wyników uzyskanych z bazy danych. Wydany jako część JDK 1.1 w 1997 roku, JDBC był jednym z pierwszych komponentów opracowanych dla warstwy trwałości Java.

JDBC został pierwotnie pomyślany jako interfejs API po stronie klienta, umożliwiający klientowi Java interakcję ze źródłem danych. Zmieniło się to w JDCB 2.0, który zawierał opcjonalny pakiet obsługujący połączenia JDBC po stronie serwera. Każde nowe wydanie JDBC od tego czasu zawierało aktualizacje zarówno pakietu po stronie klienta ( java.sql), jak i pakietu po stronie serwera ( javax.sql). JDBC 4.3, najbardziej aktualna wersja w chwili pisania tego tekstu, została wydana jako część Java SE 9 we wrześniu 2017 r.

W tym artykule przedstawiono przegląd JDBC, a następnie praktyczne wprowadzenie do korzystania z interfejsu API JDBC do łączenia klienta Java z lekką relacyjną bazą danych SQLite.

Jak działa JDBC

Opracowany jako alternatywa dla opartego na języku C interfejsu API ODBC (Open Database Connectivity), JDBC oferuje interfejs na poziomie programowania, który obsługuje mechanikę aplikacji Java komunikujących się z bazą danych lub RDBMS. Interfejs JDBC składa się z dwóch warstw:

  1. Interfejs API JDBC obsługuje komunikację między aplikacją Java a menedżerem JDBC.
  2. Sterownik JDBC obsługuje komunikację między menedżerem JDBC a sterownikiem bazy danych.

JDBC to wspólny interfejs API, z którym współdziała kod aplikacji. Poniżej znajduje się sterownik zgodny z JDBC dla używanej bazy danych.

Rysunek 1 to przegląd architektury JDBC w warstwie trwałości Java.

JavaWorld /

Używanie JDBC do łączenia się z bazą danych

Jednym z szczęśliwych faktów programowania w ekosystemie Java jest to, że prawdopodobnie znajdziesz stabilny konektor bazy danych JDBC dla dowolnej wybranej bazy danych. W tym tutorialu użyjemy SQLite do poznania JDBC, głównie dlatego, że jest tak łatwy w użyciu.

Kroki łączenia się z bazą danych za pomocą JDBC są następujące:

  1. Zainstaluj lub zlokalizuj bazę danych, do której chcesz uzyskać dostęp.
  2. Dołącz bibliotekę JDBC.
  3. Upewnij się, że potrzebny sterownik JDBC znajduje się w ścieżce klas.
  4. Użyj biblioteki JDBC, aby uzyskać połączenie z bazą danych.
  5. Użyj połączenia do wydawania poleceń SQL.
  6. Po zakończeniu zamknij połączenie.

Razem przejdziemy przez te kroki.

Znalezienie sterownika JDBC

Aby znaleźć sterownik dla bazy danych, której chcesz użyć, po prostu wyszukaj w Internecie swoją bazę danych i JDBC. Na przykład wpisanie „ mysql jdbc driver” otworzy sterownik MySQL. Wzywam Cię do znalezienia bazy danych zgodnej z Javą bez sterownika JDBC!

Krok 1. Pobierz i zainstaluj SQLite

SQLite to bardzo kompaktowa baza danych. Nie jest przeznaczony do użytku produkcyjnego, ale jest doskonałym wyborem do szybkiego wypróbowania. SQLite używa pliku jako swojej funkcjonalnej bazy danych, bez konieczności instalowania jakichkolwiek usług lub demonów.

Aby rozpocząć korzystanie z tego demo, pobierz przykładową bazę danych SQLite. Rozpakuj .dbplik i zapisz go w miejscu, którego nie zapomnisz.

Ten plik zawiera zarówno funkcjonalną bazę danych opartą na plikach, jak i przykładowy schemat oraz dane, których możemy użyć.

SQL i JDBC

NoSQL zyskał popularność w ciągu ostatniej dekady, ale relacyjne bazy danych pozostają najczęściej używanym typem magazynu danych. Relacyjna baza danych jest skonstruowany repozytorium składający się z tabel z kolumn i wierszy. SQL (Structured Query Language) to język używany przez architektów danych do wykonywania takich czynności, jak tworzenie, odczytywanie, aktualizowanie i usuwanie nowych rekordów w relacyjnej bazie danych. JDBC to warstwa adaptera od języka Java do języka SQL: zapewnia programistom języka Java wspólny interfejs do łączenia się z bazą danych, wysyłania zapytań i poleceń oraz zarządzania odpowiedziami.

Krok 2. Zaimportuj JDBC do aplikacji Java

Moglibyśmy kodować w IDE, ale kodowanie bezpośrednio w edytorze tekstu lepiej zademonstruje prostotę JDBC. Aby rozpocząć, musisz mieć kompatybilną instalację JDK dla swojego systemu operacyjnego.

Zakładając, że masz zainstalowane narzędzia programistyczne platformy Java, możemy zacząć od stworzenia prostego programu w języku Java. W edytorze tekstu wklej kod pokazany na liście 1. Wywołaj ten plik WhatIsJdbc.java.

Listing 1. Prosty program w języku Java

 class WhatIsJdbc{ public static void main(String args[]){ System.out.println("Hello JavaWorld"); } } 

Teraz skompilować kod, wprowadzając komendę: javac WhatIsJdbc.java. Kompilacja zwróci WhatIsJdbc.classplik. Wykonaj ten plik z poziomu wiersza poleceń z wezwaniem: java WhatIsJdbc.

[Zobacz „Co to jest JDK? Wprowadzenie do zestawu Java Developer Kit”, aby uzyskać więcej informacji na temat interakcji z zestawem JDK w wierszu poleceń.]

Gdy masz już podstawowy program Java, możesz dołączyć biblioteki JDBC. Wklej kod z listy 2 na początku swojego prostego programu Java.

Listing 2. Importy JDBC

 import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.ResultSet; import java.sql.Statement; 

Każdy z tych importów zapewnia dostęp do klasy, która ułatwia standardowe połączenie z bazą danych Java:

  • Connection reprezentuje połączenie z bazą danych.
  • DriverManageruzyskuje połączenie z bazą danych. (Inną opcją jest DataSourcepula połączeń).
  • SQLException obsługuje błędy SQL między aplikacją Java a bazą danych.
  • ResultSeti Statementmodeluj zestawy wyników danych i instrukcje SQL.

Wkrótce zobaczymy każdy z nich w akcji.

Krok 3. Dodaj sterownik JDBC do ścieżki klas

Następnie dodasz sterownik SQLite do swojej ścieżki klas. Sterownik JDBC jest klasa, która implementuje API JDBC dla bazy danych konkretnego.

Pobierz sterownik SQLite z GitHub. Pobierz najnowszy .jarplik i zapisz go w miejscu, które zapamiętasz.

The next time you execute your Java program, you will pull that .jar file in via the classpath. There are several ways to set the classpath. Listing 3 shows how to do it using a command-line switch.

Listing 3. Executing SQLite driver on the Java classpath

 java.exe -classpath /path-to-driver/sqlite-jdbc-3.23.1.jar:. WhatIsJdbc 

Notice that we've set the classpath to point at the driver and the local directory; this way Java will still find our class file.

Step 4. Obtain a database connection

The classpath now has access to the driver. Now, change your simple Java application file to look like the program in Listing 4.

Listing 4. Using the JDBC Connection class to connect to SQLite

 import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.ResultSet; import java.sql.Statement; class WhatIsJdbc{ public static void main(String[] args) { Connection conn = null; try { String url = "jdbc:sqlite:path-to-db/chinook/chinook.db"; conn = DriverManager.getConnection(url); System.out.println("Got it!"); } catch (SQLException e) { throw new Error("Problem", e); } finally { try { if (conn != null) { conn.close(); } } catch (SQLException ex) { System.out.println(ex.getMessage()); } } } } 

Compile and execute this code. Assuming all goes well, you will get an affirming message.

No suitable driver found?

If you've received an error that looks like "No suitable driver found for jdbc:sqlite," then you need to revisit the classpath and make sure it points to the driver you downloaded. Failed driver connection is the most common stumbling block for beginners using JDBC. Don't sweat it; just fix it.

Now we're ready for some SQL commands.

Step 5. Query the database

With the live connection object in hand, we can do something useful, like querying the database. Listing 5 shows how to query SQLite using the JDBC Connection and Statement objects.

Listing 5. Querying the database with JDBC

 import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.ResultSet; import java.sql.Statement; class WhatIsJdbc{ public static void main(String[] args) { Connection conn = null; try { String url = "jdbc:sqlite:path-to-db-file/chinook/chinook.db"; conn = DriverManager.getConnection(url); Statement stmt = null; String query = "select * from albums"; try { stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(query); while (rs.next()) { String name = rs.getString("title"); System.out.println(name); } } catch (SQLException e ) { throw new Error("Problem", e); } finally { if (stmt != null) { stmt.close(); } } } catch (SQLException e) { throw new Error("Problem", e); } finally { try { if (conn != null) { conn.close(); } } catch (SQLException ex) { System.out.println(ex.getMessage()); } } } } 

In Listing 5 we use our Connection object to obtain a Statement object: conn.createStatement(). We then use this object to execute an SQL query: stmt.executeQuery(query).

The executeQuery command returns a ResultSet object, which we then use to iterate over the data with while (rs.next()). In this example, you should see the album titles we've queried on as output.

Notice that we also closed the connection, via a call to conn.close().

Network connections with JDBC

The database connection string in Listing 5 is for a local connection: jdbc:sqlite:path-to-db-file/chinook/chinook.db. To access the database via a network, the connection string would need to include the network URL and (usually) credentials for accessing it.

Doing more with JDBC

So far we've covered the basics of using JDBC to connect to a database and issue SQL commands. While Statementss and ResultSets work well for common scenarios, you'll likely need additional options for larger or more complex applications. Fortunately, the JDBC library continues evolving to meet most database access needs.

PreparedStatements

One easy way to increase the flexibility of your code is to replace the Statement class with PreparedStatement, as shown in Listing 6.

Listing 6. Using JDBC PreparedStatements

 String prepState = "insert into albums values (?, ?);"; PreparedStatement prepState = connection.prepareStatement(sql); prepState.setString(1, "Uprising"); prepState.setString(2, "Bob Marley and the Wailers "); int rowsAffected = preparedStatement.executeUpdate(); 

PreparedStatement replaces Statement's hard-coded values with question marks (?). Using PreparedStatements optimizes your code for reuse: a PreparedStatement is compiled only once, and can then be reused with a variety of parameters. As your code base grows, you simply insert new values into the statement, instead of hacking the string object itself.

Batch updates

Whenever an application has several updates to issue, doing them in batches can greatly benefit performance. The essence of batching is to take the multiple updates and collect them together, then issue them all at once. Listing 7 uses JDBC's batch methods to perform a batch update of several PreparedStatements.

Listing 7. Batching with PreparedStatement

 prepState.setString(1, "Uprising"); prepState.setString(2, "Bob Marley and the Wailers"); preparedStatement.addBatch(); prepState.setString(1, "Wildflowers"); prepState.setString(2, "Tom Petty and the Heartbreakers"); preparedStatement.addBatch(); int[] rowsAffected = preparedStatement.executeBatch(); 

JDBC transactions

Transactions in relational databases allow for a set of updates to be wrapped in an interaction that either succeeds or fails altogether. The basics of using a transaction via JDBC are to tell the system to turn off auto-commit, and then manually tell the system to commit when you are done. By default, auto-commit is on, which means whenever an executeUpdate or executeInsert is run, the command is committed.

Listing 8 shows a small slice of a JDBC transaction.

Listing 8. JDBC transactions

 connection.setAutoCommit(false); // Use executeUpdate multiple times connection.commit(); 

When connection.commit() is encountered, all the updates wrapped inside will be attempted, and if any fail, they all will be rolled back.

There are many more features in JDBC 4.3 worth exploring, including using CallableStatement for stored procedures, using DataSource objects for improved application performance (especially via connection pooling), and converting a JDBC ResultSet to a Java Stream.

Database-specific features

Although every JDBC-compliant database offers the same core features for connecting and interacting with a database via SQL, some databases do more than others. As an example, Oracle DB offers result caching, which is not required by the JDBC specification. Here's an example:

 conn.prepareStatement ("select /*+ result_cache */ * from employees where employee_id < : 1"); 

This example is taken from the documentation for Oracle's JDBC OCI Driver.

Conclusion

JDBC is one of Java's oldest APIs, providing an easy-to-use solution for one of the perennial needs of Java application development. Knowing just the few JDBC calls demonstrated in this article will get you started using JDBC to connect to virtually any database. Once you've got those commands down, you can begin to explore some of the more sophisticated options that have been built into JDBC.

Podczas gdy JDBC jest wystarczające dla prostszych aplikacji, większość programistów ostatecznie sięgnie po Java Persistence API (JPA) w celu opracowania bardziej formalnej warstwy dostępu do danych. JPA wymaga bardziej wstępnej pracy i bardziej wyrafinowanego zrozumienia architektury aplikacji, ale zapewnia bardziej spójną, izolowaną i dobrze zdefiniowaną warstwę dostępu do danych. Więcej informacji na temat tworzenia warstwy trwałości danych dla aplikacji Java można znaleźć w towarzyszącym artykule „Co to jest JPA? Wprowadzenie do interfejsu API Java Persistence”.

Artykuł „Co to jest JDBC? Wprowadzenie do łączności z bazą danych w języku Java” został pierwotnie opublikowany przez JavaWorld.