В этом руководстве вы узнаете, как вызвать хранимую процедуру в SQL Server из программы Java с использованием JDBC.
Это руководство начинается с того места, где закончилось руководство «Выполнение транзакции в Java».
Как вызвать хранимую процедуру из Java с помощью JDBC
Ниже приведены шаги для вызова хранимой процедуры в SQL Server из Java с использованием JDBC:
- Сначала подключитесь к базе данных SQL Server с помощью JDBC.
- Во-вторых, создайте CallableStatement для выполнения хранимой процедуры.
- В-третьих, свяжите входные параметры оператора, вызывающего хранимую процедуру.
- В-четвертых, выполните CallableStatement, который вызывает хранимую процедуру.
- В-пятых, обработайте набор результатов, возвращаемый хранимой процедурой.
- Наконец, закройте ресурсы, включая ResultSet, CallableStatement и Connection, чтобы освободить ресурсы. Если вы используете оператор try-with-resources, вам не нужно выполнять этот шаг вручную.
Создание новой хранимой процедуры
Шаг 1. Запустите Microsoft SQL Server Management Studio(SSMS) и подключитесь к SQL Server.
Шаг 2.Создайте новую хранимую процедуру, выполнив следующий оператор:
CREATE PROCEDURE GetBooksByPublishedDate @StartDate DATE, @EndDate DATE AS BEGIN -- Check for valid date range IF @StartDate > @EndDate BEGIN PRINT 'Error: Start date must be less than or equal to end date.' RETURN END -- Retrieve books within the date range SELECT BookID, Title, Publisher, ISBN, PublishedDate FROM Books WHERE PublishedDate BETWEEN @StartDate AND @EndDate ORDER BY PublishedDate; END
Хранимая процедура GetBooksByPublishedDate возвращает список книг с датами публикации между начальной и конечной датами.
Вызов хранимой процедуры
Шаг 1. Определите класс Book, который представляет каждую строку в таблице Books:
import java.time.LocalDate; public class Book { private int bookId; private String title; private String publisher; private String isbn; private LocalDate publishedDate; public Book(int bookId, String title, String publisher, String isbn, LocalDate publishedDate) { this.bookId = bookId; this.title = title; this.publisher = publisher; this.isbn = isbn; this.publishedDate = publishedDate; } public Book(String title, String publisher, String isbn, LocalDate publishedDate) { this(0, title, publisher, isbn, publishedDate); } public int getBookId() { return bookId; } public void setBookId(int bookId) { this.bookId = bookId; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getPublisher() { return publisher; } public void setPublisher(String publisher) { this.publisher = publisher; } public String getIsbn() { return isbn; } public void setIsbn(String isbn) { this.isbn = isbn; } public LocalDate getPublishedDate() { return publishedDate; } public void setPublishedDate(LocalDate publishedDate) { this.publishedDate = publishedDate; } }
Шаг 2. Определите класс BookDB для взаимодействия с базой данных BookStore:
import java.sql.Date; import java.sql.SQLException; import java.sql.ResultSet; import java.time.LocalDate; import java.sql.Connection; import java.util.ArrayList; import java.util.List; public class BookDB { private final Connection connection; public BookDB(Connection connection) { this.connection = connection; } private Book createBookFrom(ResultSet rs) throws SQLException { return new Book( rs.getInt("BookID"), rs.getString("Title"), rs.getString("Publisher"), rs.getString("ISBN"), rs.getDate("PublishedDate").toLocalDate() ); } public List findByPublishedDate(LocalDate fromDate, LocalDate toDate) throws DBException { var books = new ArrayList(); String sql = "{CALL GetBooksByPublishedDate(?, ?)}"; try(var stmt = connection.prepareCall(sql)) { stmt.setDate(1, Date.valueOf(fromDate)); stmt.setDate(2, Date.valueOf(toDate)); try(var rs = stmt.executeQuery()) { while(rs.next()) { books.add(createBookFrom(rs)); } return books; } } catch(SQLException e) { throw new DBException(e.getMessage()); } } }
Как это работает.
Сначала определите частное поле соединения:
private final Connection connection;
Во-вторых, инициализируйте объект соединения в конструкторе:
public BookDB(Connection connection) { this.connection = connection; }
В-третьих, определите метод createBookFrom() для создания нового объекта Book из объекта ResultSet:
private Book createBookFrom(ResultSet rs) throws SQLException { return new Book( rs.getInt("BookID"), rs.getString("Title"), rs.getString("Publisher"), rs.getString("ISBN"), rs.getDate("PublishedDate").toLocalDate() ); }
В-четвертых, определите метод findByPublishedDate, который возвращает список объектов Book с датой публикации между fromDate и toDate:
public List findByPublishedDate(LocalDate fromDate, LocalDate toDate) throws DBException {
В-пятых, инициализируем объект списка книг:
var books = new ArrayList();
В-шестых, создайте оператор T-SQL, который вызывает хранимую процедуру:
String sql = "{CALL GetBooksByPublishedDate(?, ?)}";
Вопросительные знаки(?) являются заполнителями для параметров хранимой процедуры GetBooksByPublishedDate. При выполнении хранимой процедуры необходимо задать фактические значения этих параметров.
В-седьмых, создайте объект CallableStatemen:
try(var stmt = connection.prepareCall(sql)) {
В-восьмых, привяжите даты к параметрам запроса:
stmt.setDate(1, Date.valueOf(fromDate)); stmt.setDate(2, Date.valueOf(toDate));
Девятое, выполните вызов хранимой процедуры:
try(var rs = stmt.executeQuery()) {
В-десятых, выполните итерацию по строкам в результирующем наборе, преобразуйте каждую строку в объект Book и добавьте его в список книг:
while(rs.next()) { books.add(createBookFrom(rs)); }
Одиннадцатое, верните список книг:
return books;
Наконец, выдайте исключение DBException, если во время вызова возникнет какая-либо ошибка:
} catch(SQLException e) { throw new DBException(e.getMessage()); }
Шаг 3. Измените метод main() класса Main, чтобы использовать метод findByPublishedDate класса BookDB:
import java.sql.SQLException; import java.time.LocalDate; public class Main { public static void main(String[] args) { try(var connection = SQLServerConnection.connect()) { // var bookDB = new BookDB(connection); var fromDate = LocalDate.of(2021,1,1); var toDate = LocalDate.of(2022,12,31); var books = bookDB.findByPublishedDate(fromDate, toDate ); for(var book: books) { System.out.println(book.getTitle() + '\t' + book.getPublishedDate()); } } catch(SQLException | DBException e) { System.err.println(e.getMessage()); } } }
Как это работает.
Сначала подключитесь к SQL Server:
try(var connection = SQLServerConnection.connect()) {
Во-вторых, создайте объект BookDB:
var bookDB = new BookDB(connection);
В-третьих, инициализируйте переменные, хранящие даты для передачи в метод findByPublishedDate:
var fromDate = LocalDate.of(2021, 1, 1); var toDate = LocalDate.of(2022, 12, 31);
В-четвертых, выполните метод findByPublishedDate объекта bookDB для вызова хранимой процедуры:
var books = bookDB.findByPublishedDate(fromDate, toDate );
В-пятых, пройдитесь по списку книг и отобразите название книги и дату публикации:
for(var book: books) { System.out.println(book.getTitle() + '\t' + book.getPublishedDate()); }
Наконец, отобразите сообщение об ошибке:
} catch(SQLException | DBException e) { System.err.println(e.getMessage()); }
Шаг 4. Запустите программу.
Будет выведен следующий результат:
Inside SQL Server 2021-07-20 SQL Server Performance Tuning 2022-04-15 SQL Server Internals: A Deep Dive 2022-12-15
Загрузите исходный код проекта
Загрузите исходный код проекта
Краткое содержание
- Используйте объект CallableStatement для вызова хранимой процедуры.