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

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

Модуль 4. Работа с БД
8 уровень , 3 лекция
Открыта

Полный список типов данных 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
Комментарии (22)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Равиль Хакимов Уровень 104
24 октября 2025
Я вот на чем завис. Нам пишут, что мы "Сохраняем Java-объект в базу" но мы же не объект сохраняем, а данные объекта сохраняем (состояние или значение полей)? или это одно и тоже? или это для упрощения так написано? или я где то упустил и считается что данные объекта это и есть сам объект? тогда методы тоже сохраняем где то в таблице?
СтудентJava Уровень 109
1 февраля 2025
Мммдддааа, это не задачки по SQL, их не пощелкаешь☺️ Олег щелкун аж потерялся😂
Анастасия Уровень 105
20 октября 2025
😂😂😂
Роман Уровень 88
7 января 2025
впервые за долгое время запотел на задачах
Олег Уровень 106 Expert
26 сентября 2024
В какой-то момент я люто потерялся.
И. Ж. Уровень 41
29 апреля 2024
Смысл этого не ясно: if (!results.first()) return null; В описании метода first() сказано, что устанавливает курсор на первую строку результата запроса. Первая и последняя строки как известно пустые. Что тут это значит непонятно
Ольга Николенко Уровень 109 Expert
24 мая 2024
ошибка в коде, проверяем не первый ли элемент не переведя курсор
Andrey Vysotsky Уровень 32
11 апреля 2024
пытаюсь повторить запись блоб из урока в свою базу и получаю вот что Exception in thread "main" java.sql.SQLFeatureNotSupportedException: Метод org.postgresql.jdbc.PgConnection.createBlob() ещё не реализован поптыки найти решение в интернете подсказывают что проблема с Hybertate но я вроде только JDBC использую...
Andrey Vysotsky Уровень 32
12 апреля 2024
А, классика Джавараша - ответ прямо в следующей статье
Anonymous #3322801 Уровень 2 Expert
7 ноября 2023
Не знаю как у остальных, у меня пример с чтением 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
Правильное замечание у вас! После этого исправления у меня тоже все заработало! :)
Ольга Николенко Уровень 109 Expert
24 мая 2024
на практике не проверяла, но есть ощущение что тут просто забыли вызвать results.next() перед if-блоком
Anonymous #3322801 Уровень 2 Expert
7 ноября 2023
Если мы начинаем заполнение таблицы с имени, а не с id тогда правильнее было бы сделать такую таблицу

CREATE TABLE employee
(
    id         INT PRIMARY KEY NOT NULL AUTO_INCREMENT,
    name       VARCHAR(100),
    occupation VARCHAR(100),
    salary     INT,
    join_date  DATE
);
Кирилл Уровень 111 Expert
24 октября 2023
в последних 2-х примерах в названиях методов не хватает буквы m: getEployeeById getAllEployees
Елизавета Уровень 108 Expert
30 августа 2023
для тех, кому лень искать, что такое 1 вот тут: blob.setBinaryStream(1) blob.setBinaryStream(long pos) pos - the position in the BLOB value at which to start writing; the first position is 1