Кроме класса Statement в java.sql мы можем использовать для выполнения запросов еще один класс - PreparedStatement. Кроме собственно выполнения запроса этот класс позволяет подготовить запрос, отформатировать его должным образом.
Например, в прошлых темах была создана таблица, которая имеет три столбца:
CREATE TABLE products ( Id INT PRIMARY KEY AUTO_INCREMENT, ProductName VARCHAR(20), Price INT )
С помощью PreparedStatement добавим в нее один объект:
import java.sql.*;
import java.util.Scanner;
public class Program{
public static void main(String[] args) {
try{
String url = "jdbc:mysql://localhost/store?serverTimezone=Europe/Moscow&useSSL=false";
String username = "root";
String password = "password";
Scanner scanner = new Scanner(System.in);
Class.forName("com.mysql.cj.jdbc.Driver").getDeclaredConstructor().newInstance();
System.out.print("Input product name: ");
String name = scanner.nextLine();
System.out.print("Input product price: ");
int price = scanner.nextInt();
try (Connection conn = DriverManager.getConnection(url, username, password)){
String sql = "INSERT INTO Products (ProductName, Price) Values (?, ?)";
PreparedStatement preparedStatement = conn.prepareStatement(sql);
preparedStatement.setString(1, name);
preparedStatement.setInt(2, price);
int rows = preparedStatement.executeUpdate();
System.out.printf("%d rows added", rows);
}
}
catch(Exception ex){
System.out.println("Connection failed...");
System.out.println(ex);
}
}
}
В данном случае данные вводятся с консоли и затем добавляются в базу данных. Для создания объекта PreparedStatement применяется
метод prepareStatement() класса Connection. В этот метод передается выражение sql INSERT INTO Products (ProductName, Price) Values (?, ?). Это выражение может
содержать знаки вопроса ? - знаки подстановки, вместо которых будут вставляться реальные значения.
Чтобы связать отдельные знаки подстановки с конкретными значениями у класса PreparedStatement определен ряд методов для различных типов данных. Все методы, которые поставляют значения вместо знаков подстановки, в качестве первого параметра принимают порядковый номер знака подстановки (нумерация начинается с 1), а в качестве второго параметра - собственно значение, которое вставляется вместо знака подстановки.
Например, первый знак подстановки ? в выражении sql представляет значение для столбца ProductName, который хранит строку. Поэтому
для связи значения с первым знаком подстановки применяется метод preparedStatement.setString(1, name).
Второй знак подстановки должен передавать значение для столбца Price, который хранит целые числа. Поэтому для вставик значения используется
метод preparedStatement.setInt(2, price)
Кроме setString и setInt PreparedStatement имеет еще ряд подобных методов, которые работают подобным образом. Некоторые из них:
setBigDecimal
setBoolean
setDate
setDouble
setFloat
setLong
setNull
setTime
Для выполнения запроса PreparedStatement имеет три метода:
boolean execute(): выполняет любую SQL-команду
ResultSet executeQuery(): выполняет команду SELECT, которая возвращает данные в виде ResultSet
int executeUpdate(): выполняет такие SQL-команды, как INSERT, UPDATE, DELETE, CREATE и возвращает количество измененных строк
При этом в отличие от методов Statement эти методы не принимают SQL-выражение.
Пример выполнения программы:
C:\Java>javac Program.java C:\Java>java -classpath c:\Java\mysql-connector-java-8.0.11.jar;c:\Java Program Inpit product name: Xiaomi Mi 8 Input product price: 35000 1 rows added C:\Java>
Подобным образом мы можем выполнять и другие выражения. Например, получим товары, у которых цена меньше 50000:
int maxPrice = 50000;
PreparedStatement preparedStatement = conn.prepareStatement("SELECT * FROM Products WHERE Price < ?");
preparedStatement.setInt(1, maxPrice);
ResultSet resultSet = preparedStatement.executeQuery();
while(resultSet.next()){
int id = resultSet.getInt("Id");
String name = resultSet.getString("ProductName");
int price = resultSet.getInt("Price");
System.out.printf("%d. %s - %d \n", id, name, price);
}