JavaRush/Курсы/Модуль 4. Работа с БД/Сохранение объектов в базу

Сохранение объектов в базу

Открыта

Полный список типов данных JDBC

Кроме известных тебе типов данных JDBC позволяет работать со многими родными типами данных для СУБД. Ниже я приведу список типов и функции для получения их:

Тип Метод
Array getArray()
AsciiStream getAsciiStream()
BigDecimal getBigDecimal()
BinaryStream getBinaryStream()
Blob getBlob()
Boolean getBoolean()
Blob getBlob()
Boolean getBoolean()
Byte getByte()
Bytes getBytes()
CharacterStream getCharacterStream()
Clob getClob()
Date getDate()
Double getDouble()
Float getFloat()
Int getInt()
Long getLong()
NCharacterStream getNCharacterStream()
Object getObject()
Ref getRef()
RowId getRowId()
Short getShort()
SQLXML getSQLXML()
String getString()
Time getTime()
Timestamp getTimestamp()
UnicodeStream getUnicodeStream()
URL getURL()

Примитивные типы мы с тобой уже рассматривали. Давай теперь попробуем поработать с объектами.

Тип данных BLOB

Если ты хочешь сохранить какой-то объект в базу данных, то самый простой способ сделать это — воспользовавшись SQL-типом BLOB. У JDBC есть его аналог, который называется Blob.

BLOB расшифровывается как Binary Large Object. Он используется для хранения массива байт. Тип Blob в JDBC является интерфейсом и в него можно класть (и получать) данные двумя способами:

  • С помощью InputStream
  • С помощью массива байт

Пример: колонка номер 3 содержит тип BLOB:

Statement statement = connection.createStatement();
    ResultSet results = statement.executeQuery("SELECT * FROM user");
    results.first();

    Blob blob = results.getBlob(3);
    InputStream is = blob.getBinaryStream();

Чобы создать свой объект Blob, нужно воспользоваться функцией createBlob(). Пример:

String insertQuery =INSERT INTO images(name, image) VALUES (?, ?);
PreparedStatement statement = connection.prepareStatement(insertQuery);

// Создаем объект Blob и получаем у него OtputStream для записи в него данных
Blob blob = connection.createBlob();

// Заполняем Blob данными  …
OutputStream os = blob.setBinaryStream(1);

// Передаем Вlob как параметр запроса
statement.setBlob(2, blob);
statement.execute();

Заполнить Blob данными можно двумя способами. Первый — через OutputSteam:

Path avatar = Paths.get("E:\\images\\cat.jpg");
OutputStream os = blob.setBinaryStream(1);
Files.copy(avatar, os);

И второй — через заполнение байтами:

Path avatar = Paths.get("E:\\images\\cat.jpg");
byte[] content = Files.readAllBytes(avatar);
blob.setBytes(1, content);

Сохраняем Java-объект в базу

Мы научились сохранять в базу бинарные объекты: массивы байт, байтовые потоки и так далее. А что насчет Java-объектов? Как нам сохранить Java-объект в базу данных?

Допустим, у нас есть Java-класс Employee, описывающий сотрудника компании:

public class Employee {
    public Integer id;
    public String name;
    public String occupation;
    public Integer salary;
    public Date joinDate;
}

Как нам сохранить объект этого класса в базу с помощью JDBC?

На самом деле ты уже знаешь все, что для этого нужно. Сначала необходимо создать таблицу в базе, которая соответствует этому классу. Например, такую:

CREATE TABLE employee {
    id INT PRIMARY KEY NOT NULL,
    name VARCHAR(100),
    occupation VARCHAR(100),
    salary INT,
    join_date DATE
}

А теперь напишем код, который добавит объект нашего класса Employee в базу:

public static boolean addEmployee(Connection connection, Employee employee) throws Exception {
    	// Создаем и подготавливаем запрос на вставку данных в таблицу
    	String insertQuery = "INSERT INTO employee(name, occupation, salary, join_date ) VALUES (?, ?, ?, ?)";
    	PreparedStatement statement = connection.prepareStatement(insertQuery);

    	// Заполняем запрос данными из объекта Employee
    	statement.setString(1, employee.name);
    	statement.setString(2, employee.occupation);
    	statement.setInt(3, employee.salary);
    	statement.setDate(4, employee.joinDate);

    	// Выполняем наш запрос, и он возвращает true, если новая строка добавилась
    	int count = statement.executeUpdate();
    	return count > 0;
    }

Просто и понятно. Метод будет отлично работать.

Читаем Java-объект из базы

Записывать объект в базу мы научились, теперь давай напишем код, чтобы читать объект из базы. Начнем с кода, который читает объект из базы по его ID:

public static Employee getEmployeeById(Connection connection, int id) throws Exception {
    	// Создаем и подготавливаем запрос для получения сотрудника из таблицы
    	PreparedStatement statement = connection.prepareStatement("SELECT * FROM employee WHERE id = ?");
    	statement.setInt(1, id);

    	// Выполняем наш запрос, и он возвращает null, если строк в результате запроса нет
    	ResultSet results = statement.executeQuery();
    	if (!results.first())
        	return null;

    	// Заполняем объект Employee данными из ResultSet
    	Employee employee = new Employee();
    	employee.id = results.getInt(1);
    	employee.name = results.getString(2);
    	employee.occupation = results.getString(3);
    	employee.salary = results.getInt(4);
    	employee.joinDate = results.getDate(5);
    	return employee;
}

А если нам нужен не один объект, а несколько? Такой запрос тоже написать просто. Давай получим всех сотрудников нашей компании:

public static List<Employee> getAllEmployees(Connection connection) throws Exception {
	// Создаем и выполняем запрос для получения сотрудников из таблицы
	Statement statement = connection.createStatement();
	ResultSet results = statement.executeQuery("SELECT * FROM employee");

	ArrayList<Employee> list = new ArrayList<Employee>();
	while (results.next()) {
        // Заполняем объект Employee данными из текущей строки ResultSet
	        Employee employee = new Employee();
	        employee.id = results.getInt(1);
	        employee.name = results.getString(2);
	        employee.occupation = results.getString(3);
	        employee.salary = results.getInt(4);
	        employee.joinDate = results.getDate(5);

	        list.add(employee);
	}
	return list;
}

Кстати, если таких методов будет много, то в каждом из них придется писать одинаковый код по преобразованию строки ResultSet в объект Employee. Так что этот код можно вынести в отдельный метод.

Особенно это может быть полезно, если класс Employee содержит сложные поля типа Enum, InputStream, или ссылки на другие объекты, которые мы тоже хотим хранить в базе.

1
Задача
Модуль 4. Работа с БД,  8 уровень3 лекция
Недоступна
task0805
task0805
1
Задача
Модуль 4. Работа с БД,  8 уровень3 лекция
Недоступна
task0806
task0806
Комментарии (24)
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
Дмитрий
Уровень 77
Expert
22 февраля, 18:05
перед началом чтения статьи думал, что будет связано что-то с сериализацией или мы будет объект класса хранить как blob, а оказалось все вроде и проще, но странно
Виктор
Уровень 83
19 февраля, 07:55
Пошла жара
Равиль Хакимов
Уровень 107
24 октября 2025, 09:58
Я вот на чем завис. Нам пишут, что мы "Сохраняем Java-объект в базу" но мы же не объект сохраняем, а данные объекта сохраняем (состояние или значение полей)? или это одно и тоже? или это для упрощения так написано? или я где то упустил и считается что данные объекта это и есть сам объект? тогда методы тоже сохраняем где то в таблице?
СтудентJava
Уровень 109
1 февраля 2025, 17:11
Мммдддааа, это не задачки по SQL, их не пощелкаешь☺️ Олег щелкун аж потерялся😂
Анастасия
Уровень 112
20 октября 2025, 13:19
😂😂😂
Роман
Уровень 88
7 января 2025, 04:28
впервые за долгое время запотел на задачах
Олег
Уровень 106
Expert
26 сентября 2024, 20:21
В какой-то момент я люто потерялся.
И. Ж.
Уровень 41
29 апреля 2024, 18:18
Смысл этого не ясно: if (!results.first()) return null; В описании метода first() сказано, что устанавливает курсор на первую строку результата запроса. Первая и последняя строки как известно пустые. Что тут это значит непонятно
Ольга Николенко
Уровень 109
Expert
24 мая 2024, 18:28
ошибка в коде, проверяем не первый ли элемент не переведя курсор
Andrey Vysotsky
Уровень 32
11 апреля 2024, 06:30
пытаюсь повторить запись блоб из урока в свою базу и получаю вот что Exception in thread "main" java.sql.SQLFeatureNotSupportedException: Метод org.postgresql.jdbc.PgConnection.createBlob() ещё не реализован поптыки найти решение в интернете подсказывают что проблема с Hybertate но я вроде только JDBC использую...
Andrey Vysotsky
Уровень 32
12 апреля 2024, 05:58
А, классика Джавараша - ответ прямо в следующей статье
Anonymous #3322801
Уровень 2
Expert
7 ноября 2023, 20:42
Не знаю как у остальных, у меня пример с чтением employee кидает ошибку на метод
if (!results.first()) return null;
Получилось избежать ошибки только с помощью добавления специальных типов в запрос
PreparedStatement statement = connection.prepareStatement(sqlQuery,
                ResultSet.TYPE_SCROLL_SENSITIVE,
                ResultSet.CONCUR_UPDATABLE);
Либо использовать
if (!results.next()) return null;
Виктор
Уровень 109
Expert
31 января 2024, 16:38
Правильное замечание у вас! После этого исправления у меня тоже все заработало! :)
Ольга Николенко
Уровень 109
Expert
24 мая 2024, 18:29
на практике не проверяла, но есть ощущение что тут просто забыли вызвать results.next() перед if-блоком
Anonymous #3322801
Уровень 2
Expert
7 ноября 2023, 19:00
Если мы начинаем заполнение таблицы с имени, а не с id тогда правильнее было бы сделать такую таблицу
CREATE TABLE employee
(
    id         INT PRIMARY KEY NOT NULL AUTO_INCREMENT,
    name       VARCHAR(100),
    occupation VARCHAR(100),
    salary     INT,
    join_date  DATE
);