- Работа с БД с помощью JDBC
- 2. Интерфейс Statement
- Пример 1. Создание таблицы
- 3. Интерфейс ResultSet
- Основные методы интерфейса ResultSet:
- Пример 2. Использование интерфейса ResultSet
- 4. Пакетное выполнение запросов
- Пример 3. Пакетное выполнение запросов
- 5. Интерфейс PreparedStatement
- Пример 4. Использование интерфейса PreparedStatement
- Пример 5. Использование интерфейса PreparedStatement
- 6. Использование properties файлов
- Пример 6. Содержимое database.properties файла
- Пример 7. Использование ResourceBundle для чтения данных для аутентификации
- 7. Data access object (DAO)
- Пример 8. Абстрактный класс DAO
- Пример 9. Абстрактный класс DAO
- Processing SQL Statements with JDBC
- Establishing Connections
- Creating Statements
- Executing Queries
- Processing ResultSet Objects
- Closing Connections
- Шаг 3. Подтверждение концепции: подключение к SQL с помощью Java
- Шаг 1. Подключение
- Шаг 2. Выполнение запроса
- Шаг 3. Вставка строки
Работа с БД с помощью JDBC
Взаимодействовать с БД мы можем с помощью трёх интерфейсов, которые реализуются каждым драйвером:
- Statement — этот интерфейс используется для доступа к БД для общих целей. Он крайне полезен, когда мы используем статические SQL – выражения во время работы программы. Этот интерфейс не принимает никаких параметров.
- PreparedStatement — этот интерфейс может принимать параметры во время работы программы.
- CallableStatement — этот интерфейс становится полезным в случае, когда мы хотим получить доступ к различным процедурам БД. Он также может принимать параметры во время работы программы.
2. Интерфейс Statement
Statement statement = connection.createStatement();
После этого мы можем использовать наш экземпляр statement для выполнения SQL – запросов. Для этой цели интерфейс Statement имеет три метода, которые реализуются каждой конкретной реализацией JDBC драйвера:
- boolean execute(String SQL) — позволяет вам выполнить Statement, когда неизвестно заранее, является SQL-строка запросом или обновлением. Метод возвращает true, если команда создала результирующий набор.
- int executeUpdate(String SQL) используется для выполнения обновлений. Он возвращает количество обновленных строк. Для выполнения операторов INSERT, UPDATE или DELETE.
- ResultSet executeQuery(String SQL) — используется для выполнения запросов (SELECT). Он возвращает для обработки результирующий набор.
Пример 1. Создание таблицы
import java.sql.Connection; import java.sql.DriverManager; import java.sql.Statement; import static jdbc.ConnectionData.URL; import static jdbc.ConnectionData.USER; import static jdbc.ConnectionData.PASSWORD; public class CreatingTable < private static final String CREATE_TABLE_QUERY = "CREATE TABLE users " + "(id INT(5) NOT NULL AUTO_INCREMENT," + " username VARCHAR(50), " + "PRIMARY KEY(id));"; public static void main(String[] args) < try (Connection connection = DriverManager.getConnection(URL, USER, PASSWORD); Statement statement = connection.createStatement()) < statement.executeUpdate(CREATE_TABLE_QUERY); >catch (Exception e) < System.out.println(e.getMessage()); >> >
public class ConnectionData < public static final String DRIVER = "com.mysql.jdbc.Driver"; public static final String DB = "catalog"; public static final String URL = "jdbc:mysql://localhost:3306/" + DB; public static final String USER = "root"; public static final String PASSWORD = "admin"; >
3. Интерфейс ResultSet
Этот интерфейс представляет результирующий набор базы данных. Он обеспечивает приложению построчный доступ к результатам запросов в базе данных.
Во время обработки запроса ResultSet поддерживает указатель на текущую обрабатываемую строку. Приложение последовательно перемещается по результатам, пока они не будут все обработаны или не будет закрыт ResultSet.
Основные методы интерфейса ResultSet:
- public boolean absolute(int row) throws SQLException — метод перемещает курсор на заданное число строк от начала, если число положительно, и от конца — если отрицательно.
- public void afterLast() throws SQLException — этот метод перемещает курсор в конец результирующего набора за последнюю строку.
- public void beforeFirst() throws SQLException — этот метод перемещает курсор в начало результирующего набора перед первой строкой.
- public void deleteRow() throws SQLException — удаляет текущую строку из результирующего набора и базы данных.
- public ResultSetMetaData getMetaData() throws SQLException — предоставляет объект метаданных для данного ResultSet. Класс ResultSetMetaData содержит информацию о результирующей таблице, такую как количество столбцов, их заголовок и т.д.
- public int getRow() throws SQLException — возвращает номер текущей строки.
- public Statement getStatement() throws SQLException — возвращает экземпляр Statement, который произвел данный результирующий набор.
- public boolean next() throws SQLException, public boolean previous() throws SQLException — эти методы позволяют переместиться в результирующем наборе на одну строку вперед или назад. Во вновь созданном результирующем наборе курсор устанавливается перед первой строкой, поэтому первое обращение к методу next() влечет позиционирование на первую строку. Эти методы возвращают true, если остается строка для дальнейшего перемещения. Если строк для обработки больше нет, возвращается false.
- public void close() throws SQLException — осуществляет немедленное закрытие ResultSet вручную. Обычно этого не требуется, так как закрытие Statement, связанного с ResultSet, автоматически закрывает ResultSet.
Пример 2. Использование интерфейса ResultSet
public class RetrieveData < private static final String SELECT_QUERY = "SELECT * FROM users;"; public static void main(String[] args) < try (Connection connection = DriverManager.getConnection(URL, USER, PASSWORD); Statement statement = connection.createStatement()) < ResultSet resultSet = statement.executeQuery(SELECT_QUERY); System.out.printf("%-20s%s%n", "id", "username"); System.out.println("-------------------------------"); while (resultSet.next()) < int String name = resultSet.getString("username"); System.out.printf("%-20d%s%n", id, name); >> catch (SQLException e) < System.out.println(e.getMessage()); >> >
4. Пакетное выполнение запросов
Для выполнения набора из нескольких запросов на обновление данных в интерфейс Statement были добавлены методы:
void addBatch(String) int[] executeBatch()
Пакетное выполнение запросов уменьшает трафик между клиентом и СУБД и может привести к существенному повышению производительности.
Пример 3. Пакетное выполнение запросов
import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; import static jdbc.ConnectionData.URL; import static jdbc.ConnectionData.USER; import static jdbc.ConnectionData.PASSWORD; public class InsertBatchData < public static void main(String[] args) < try (Connection connection = DriverManager.getConnection(URL, USER, PASSWORD); Statement statement = connection.createStatement()) < statement.addBatch("INSERT INTO users (username) VALUES ('sidorov')"); statement.addBatch("INSERT INTO users (username) VALUES ('petrov')"); statement.addBatch("INSERT INTO users (username) VALUES ('kozlov')"); statement.executeBatch(); >catch (SQLException e) < System.out.println(e.getMessage()); >> >
5. Интерфейс PreparedStatement
Особенностью SQL-выражений в PreparedStatement является то, что они могут иметь параметры. Параметризованное выражение содержит знаки вопроса в своем тексте. Например:
SELECT name FROM persons WHERE age=?
Перед выполнением запроса значение каждого вопросительного знака явно устанавливается методами setXxx(), например:
Использование PreparedStatement приводит к более быстрому выполнению запросов при их многократном вызове с различными параметрами.
Пример 4. Использование интерфейса PreparedStatement
import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import static jdbc.ConnectionData.URL; import static jdbc.ConnectionData.USER; import static jdbc.ConnectionData.PASSWORD; public class RetrieveDataPreparedStatement < private static final String SELECT_QUERY = "SELECT * FROM users WHERE id>? AND username LIKE ?"; public static void main(String[] args) < try (Connection connection = DriverManager.getConnection(URL, USER, PASSWORD); PreparedStatement preparedStatement = connection.prepareStatement(SELECT_QUERY)) < preparedStatement.setInt(1, 2); preparedStatement.setString(2, "P%"); ResultSet resultSet = preparedStatement.executeQuery(); while (resultSet.next()) < System.out.printf("%d%23s%n", resultSet.getInt("id"), resultSet.getString("username")); >> catch (Exception e) < e.printStackTrace(); >> >
Пример 5. Использование интерфейса PreparedStatement
import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; import static jdbc.ConnectionData.URL; import static jdbc.ConnectionData.USER; import static jdbc.ConnectionData.PASSWORD; public class InsertDataPreparedStatement < private static final String INSERT_QUERY = "INSERT INTO users (username) VALUES (?)"; public static void main(String[] args) < try (Connection connection = DriverManager.getConnection(URL, USER, PASSWORD); PreparedStatement preparedStatement = connection.prepareStatement(INSERT_QUERY)) < preparedStatement.setString(1, "misha"); preparedStatement.addBatch(); preparedStatement.setString(1, "grisha"); preparedStatement.addBatch(); preparedStatement.executeBatch(); >catch (SQLException e) < System.out.println(e.getMessage()); >> >
6. Использование properties файлов
Пример 6. Содержимое database.properties файла
db.driver = com.mysql.jdbc.Driver db.name = catalog db.url = jdbc:mysql://localhost:3306/ db.user = root db.password = admin
Пример 7. Использование ResourceBundle для чтения данных для аутентификации
import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.util.ResourceBundle; public class ConnectorDB < public static Connection getConnection() throws SQLException < ResourceBundle resource = ResourceBundle.getBundle("database"); String url = resource.getString("db.url"); String user = resource.getString("db.user"); String pass = resource.getString("db.password"); String dbName = resource.getString("db.name"); return DriverManager.getConnection(url + dbName, user, pass); >>
7. Data access object (DAO)
В программном обеспечении data access object (DAO) — это объект, который предоставляет абстрактный интерфейс к какому-либо типу базы данных или механизму хранения. DAO может использоваться для разных видов доступа к БД (JDBC, JPA).
Пример 8. Абстрактный класс DAO
import java.util.List; public abstract class AbstractDAO < public abstract ListfindAll(); public abstract T findEntityById(K id); public abstract boolean delete(K id); public abstract boolean delete(T entity); public abstract boolean create(T entity); public abstract T update(T entity); >
Пример 9. Абстрактный класс DAO
import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.Statement; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; public class UserDAO extends AbstractDAO < public static final String SQL_SELECT_ALL_USERS = "SELECT * FROM users"; public static final String SQL_SELECT_USER_ID = "SELECT * FROM users WHERE @Override public ListfindAll() < Listusers = new ArrayList<>(); try (Connection connection = ConnectorDB.getConnection(); Statement statement = connection.createStatement()) < ResultSet rs = statement.executeQuery(SQL_SELECT_ALL_USERS); while (rs.next()) < int String name = rs.getString(2); users.add(new User(id, name)); >> catch (SQLException e) < System.out.println(e.getMessage()); >return users; > @Override public User findEntityById(Integer id) < User user = null; try (Connection connection = ConnectorDB.getConnection(); PreparedStatement statement = connection.prepareStatement(SQL_SELECT_USER_ID)) < statement.setInt(1, id); ResultSet rs = statement.executeQuery(); if (rs.next()) < String name = rs.getString(2); user = new User(id, name); >> catch (SQLException e) < System.out.println(e.getMessage()); >return user; > @Override public boolean delete(Integer id) < throw new UnsupportedOperationException(); >@Override public boolean delete(User entity) < throw new UnsupportedOperationException(); >@Override public boolean create(User entity) < throw new UnsupportedOperationException(); >@Override public User update(User entity) < throw new UnsupportedOperationException(); >>
Processing SQL Statements with JDBC
In general, to process any SQL statement with JDBC, you follow these steps:
This page uses the following method, CoffeesTable.viewTable , from the tutorial sample to demonstrate these steps. This method outputs the contents of the table COFFEES . This method will be discussed in more detail later in this tutorial:
public static void viewTable(Connection con) throws SQLException < String query = "select COF_NAME, SUP_ID, PRICE, SALES, TOTAL from COFFEES"; try (Statement stmt = con.createStatement()) < ResultSet rs = stmt.executeQuery(query); while (rs.next()) < String coffeeName = rs.getString("COF_NAME"); int supplierID = rs.getInt("SUP_ID"); float price = rs.getFloat("PRICE"); int sales = rs.getInt("SALES"); int total = rs.getInt("TOTAL"); System.out.println(coffeeName + ", " + supplierID + ", " + price + ", " + sales + ", " + total); >> catch (SQLException e) < JDBCTutorialUtilities.printSQLException(e); >>
Establishing Connections
First, establish a connection with the data source you want to use. A data source can be a DBMS, a legacy file system, or some other source of data with a corresponding JDBC driver. This connection is represented by a Connection object. See Establishing a Connection for more information.
Creating Statements
A Statement is an interface that represents a SQL statement. You execute Statement objects, and they generate ResultSet objects, which is a table of data representing a database result set. You need a Connection object to create a Statement object.
For example, CoffeesTable.viewTable creates a Statement object with the following code:
There are three different kinds of statements:
- Statement : Used to implement simple SQL statements with no parameters.
- PreparedStatement : (Extends Statement .) Used for precompiling SQL statements that might contain input parameters. See Using Prepared Statements for more information.
- CallableStatement: (Extends PreparedStatement .) Used to execute stored procedures that may contain both input and output parameters. See Stored Procedures for more information.
Executing Queries
To execute a query, call an execute method from Statement such as the following:
- execute : Returns true if the first object that the query returns is a ResultSet object. Use this method if the query could return one or more ResultSet objects. Retrieve the ResultSet objects returned from the query by repeatedly calling Statement.getResultSet .
- executeQuery : Returns one ResultSet object.
- executeUpdate : Returns an integer representing the number of rows affected by the SQL statement. Use this method if you are using INSERT , DELETE , or UPDATE SQL statements.
For example, CoffeesTable.viewTable executed a Statement object with the following code:
ResultSet rs = stmt.executeQuery(query);
Processing ResultSet Objects
You access the data in a ResultSet object through a cursor. Note that this cursor is not a database cursor. This cursor is a pointer that points to one row of data in the ResultSet object. Initially, the cursor is positioned before the first row. You call various methods defined in the ResultSet object to move the cursor.
For example, CoffeesTable.viewTable repeatedly calls the method ResultSet.next to move the cursor forward by one row. Every time it calls next , the method outputs the data in the row where the cursor is currently positioned:
ResultSet rs = stmt.executeQuery(query); while (rs.next()) < String coffeeName = rs.getString("COF_NAME"); int supplierID = rs.getInt("SUP_ID"); float price = rs.getFloat("PRICE"); int sales = rs.getInt("SALES"); int total = rs.getInt("TOTAL"); System.out.println(coffeeName + ", " + supplierID + ", " + price + ", " + sales + ", " + total); >// .
Closing Connections
When you are finished using a Connection , Statement , or ResultSet object, call its close method to immediately release the resources it’s using.
Alternatively, use a try -with-resources statement to automatically close Connection , Statement , and ResultSet objects, regardless of whether an SQLException has been thrown. (JDBC throws an SQLException when it encounters an error during an interaction with a data source. See Handling SQL Exceptions for more information.) An automatic resource statement consists of a try statement and one or more declared resources. For example, the CoffeesTable.viewTable method automatically closes its Statement object, as follows:
public static void viewTable(Connection con) throws SQLException < String query = "select COF_NAME, SUP_ID, PRICE, SALES, TOTAL from COFFEES"; try (Statement stmt = con.createStatement()) < ResultSet rs = stmt.executeQuery(query); while (rs.next()) < String coffeeName = rs.getString("COF_NAME"); int supplierID = rs.getInt("SUP_ID"); float price = rs.getFloat("PRICE"); int sales = rs.getInt("SALES"); int total = rs.getInt("TOTAL"); System.out.println(coffeeName + ", " + supplierID + ", " + price + ", " + sales + ", " + total); >> catch (SQLException e) < JDBCTutorialUtilities.printSQLException(e); >>
The following statement is a try -with-resources statement, which declares one resource, stmt , that will be automatically closed when the try block terminates:
try (Statement stmt = con.createStatement()) < // . >
Шаг 3. Подтверждение концепции: подключение к SQL с помощью Java
Этот пример следует рассматривать только как подтверждение концепции. Пример кода упрощен для ясности и для него не гарантируется соблюдение рекомендаций корпорации Майкрософт.
Шаг 1. Подключение
Используйте класс подключения для подключения к базе данных SQL.
import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public class SQLDatabaseConnection < // Connect to your database. // Replace server name, username, and password with your credentials public static void main(String[] args) < String connectionUrl = "jdbc:sqlserver://yourserver.database.windows.net:1433;" + "database=AdventureWorks;" + "user=yourusername@yourserver;" + "password=yourpassword;" + "encrypt=true;" + "trustServerCertificate=false;" + "loginTimeout=30;"; try (Connection connection = DriverManager.getConnection(connectionUrl);) < // Code here. >// Handle any errors that may have occurred. catch (SQLException e) < e.printStackTrace(); >> >
Шаг 2. Выполнение запроса
В этом примере следует подключиться к базе данных SQL Azure, выполнить инструкцию SELECT и вернуть выбранные строки.
import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class SQLDatabaseConnection < // Connect to your database. // Replace server name, username, and password with your credentials public static void main(String[] args) < String connectionUrl = "jdbc:sqlserver://yourserver.database.windows.net:1433;" + "database=AdventureWorks;" + "user=yourusername@yourserver;" + "password=yourpassword;" + "encrypt=true;" + "trustServerCertificate=false;" + "loginTimeout=30;"; ResultSet resultSet = null; try (Connection connection = DriverManager.getConnection(connectionUrl); Statement statement = connection.createStatement();) < // Create and execute a SELECT SQL statement. String selectSql = "SELECT TOP 10 Title, FirstName, LastName from SalesLT.Customer"; resultSet = statement.executeQuery(selectSql); // Print results from select statement while (resultSet.next()) < System.out.println(resultSet.getString(2) + " " + resultSet.getString(3)); >> catch (SQLException e) < e.printStackTrace(); >> >
Шаг 3. Вставка строки
В этом примере следует выполнить инструкцию INSERT, передать параметры и извлечь автоматически созданное значение первичного ключа.
import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.Statement; public class SQLDatabaseConnection < // Connect to your database. // Replace server name, username, and password with your credentials public static void main(String[] args) < String connectionUrl = "jdbc:sqlserver://yourserver.database.windows.net:1433;" + "database=AdventureWorks;" + "user=yourusername@yourserver;" + "password=yourpassword;" + "encrypt=true;" + "trustServerCertificate=false;" + "loginTimeout=30;"; String insertSql = "INSERT INTO SalesLT.Product (Name, ProductNumber, Color, StandardCost, ListPrice, SellStartDate) VALUES " + "('NewBike', 'BikeNew', 'Blue', 50, 120, '2016-01-01');"; ResultSet resultSet = null; try (Connection connection = DriverManager.getConnection(connectionUrl); PreparedStatement prepsInsertProduct = connection.prepareStatement(insertSql, Statement.RETURN_GENERATED_KEYS);) < prepsInsertProduct.execute(); // Retrieve the generated key from the insert. resultSet = prepsInsertProduct.getGeneratedKeys(); // Print the ID of the inserted row. while (resultSet.next()) < System.out.println("Generated: " + resultSet.getString(1)); >> // Handle any errors that may have occurred. catch (Exception e) < e.printStackTrace(); >> >