- Работа с MySQL в Java
10.1. Установка MySQL
10.2. Подключение через JDBC
10.3. Запросы без ResultSet
10.4. Домашняя работа 10.1
10.5. Hibernate — подключение и настройка
10.6. Домашняя работа 10.2
10.7. Hibernate изменение данных в базе
10.8. Связи ManyToOne и OneToMany
10.9. Связь ManyToMany
10.10. Домашняя работа 10.3
10.11. Hibernate query builder
10.12. Ленивая загрузка данных
10.13. Where и OrderBy
10.14. HQL
10.15. Домашняя работа 10.4
TASK_10_1: JDBCExperiments
TASK_10_2: HibernateExperiements
TASK_10_3: HibernateExperiements
TASK_10_4: HibernateExperiements
Цель задания
Научиться подключать MySQL в проекте и писать запрос в коде.
Что нужно сделать
Напишите код, который выведет среднее количество покупок в месяц для каждого курса за 2018 год. Учитывайте диапазон месяцев, в течение которого были продажи. Подробнее в примере.
Старайтесь использовать только SQL, при этом группировку по месяцам можно сделать и с помощью Java.
Пример расчёта для курса «Веб-разработчик c нуля до PRO»
SELECT pl.course_name, pl.subscription_date FROM PurchaseList pl
WHERE pl.course_name = "Веб-разработчик c 0 до PRO"
ORDER BY pl.subscription_date;
+----------------------------+---------------------+
| course_name | subscription_date |
+----------------------------+---------------------+
| Веб-разработчик c 0 до PRO | 2018-01-02 00:00:00 |
| Веб-разработчик c 0 до PRO | 2018-02-16 00:00:00 |
| Веб-разработчик c 0 до PRO | 2018-04-02 00:00:00 |
| Веб-разработчик c 0 до PRO | 2018-05-17 00:00:00 |
| Веб-разработчик c 0 до PRO | 2018-07-01 00:00:00 |
| Веб-разработчик c 0 до PRO | 2018-08-15 00:00:00 |
+----------------------------+---------------------+
Курсы продавались с января по август, то есть восемь месяцев. Всего было продано шесть подписок. Значит, среднее значение продаж для курса «Веб-разработчик c нуля до PRO» = 0,75.
Для получения значения месяца из даты в числовом значении используйте функцию
MONTH(date_value)
https://oracleplsql.ru/function-sql-server-month.html
Пример использования:
SELECT * FROM Students s
WHERE MONTH(s.registration_date ) = 4;
запрос выведет всех студентов, зарегистрированных в апреле:
+----+--------------------+------+---------------------+
| id | name | age | registration_date |
+----+--------------------+------+---------------------+
| 14 | Кутяков Ефрем | 31 | 2016-04-01 00:00:00 |
| 15 | Бондарев Игорь | 32 | 2016-04-08 00:00:00 |
| 16 | Журавлев Севастьян | 33 | 2016-04-15 00:00:00 |
| 17 | Иньшов Геннадий | 34 | 2016-04-22 00:00:00 |
| 18 | Шабанов Клавдий | 35 | 2016-04-29 00:00:00 |
| 67 | Бугаков Валерий | 34 | 2017-04-07 00:00:00 |
| 68 | Гайденко Илья | 35 | 2017-04-14 00:00:00 |
| 69 | Перехваткин Сергей | 36 | 2017-04-21 00:00:00 |
| 70 | Барсуков Виктор | 37 | 2017-04-28 00:00:00 |
+----+--------------------+------+---------------------+
- Если у вас ошибка не назначенного часового пояса.
ERROR: The server time zone value ‘�й���ʱ��’ is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specific time zone value if you want to utilize time zone support.
Решение:
Добавьте в вашу строку соединения с базой данных параметр, указывающий часовой пояс, serverTimezone=UTC
или укажите конкретный часовой пояс, например serverTimezone=Europe/Moscow
.
Ваша строка будет выглядеть так:
jdbc:mysql://localhost:3306/skillbox?useSSL=false&serverTimezone=UTC
Решение
TASK_10_1: JDBCExperiments
Критерии оценки
«Зачёт» — в консоль выводятся средние количества покупок курсов в месяц за 2018 год.
«Незачёт» — задание не выполнено.
Цель задания
Научиться подключать библиотеку Hibernate к проекту.
Что нужно сделать
- Подключите в ваш проект библиотеку Hibernate.
- Создайте класс для таблицы Courses.
- Напишите код, который выводит имя и количество студентов любого курса.
Решение
TASK_10_2: HibernateExperiements
Критерии оценки
«Зачёт» — выведена информация о курсе.
«Незачёт» — задание не выполнено.
Цель задания
Научиться создавать классы @Entity
со связями для работы с базой данных.
Что нужно сделать
Создайте классы @Entity
для всех таблиц базы данных и связи между ними для всей базы данных Skillbox.
Рекомендации
Изучите каждую таблицу и найдите связи между ними. Например, в таблице Subscriptions есть поле с идентификатором студента (student_id). В классе, связанном с Subscriptions, можно сделать связь @ManyToOne
со студентом, а у студента будет @OneToMany
. То есть у одного студента может быть много подписок, а у каждой подписки может быть только один студент. Аналогично посмотрите, где и какие связи можно прописать между классами.
Решение
TASK_10_3: HibernateExperiements
Критерии оценки
«Зачёт» — написаны все классы для таблиц базы данных с указанием связей между таблицами.
«Незачёт» — задание не выполнено.
Цель задания
С помощью Hibernate создайте новую таблицу в базе данных и заполните её.
В базе Skillbox есть таблица PurchaseList. В ней указаны имена студентов и названия курсов, которые они купили.
Что нужно сделать
Напишите код новой таблицы LinkedPurchaseList, которая заполняется на основании данных таблицы PurchaseList.
Таблица должна содержать следующие поля:
- student_id
- course_id
В таблице нет отдельной колонки с привычным идентификатором записи. В роли идентификатора здесь выступает пара student_id и course_id. Это значит, что пара значений student_id и course_id уникальна для каждой записи.
Связка student_id и course_id называется «составной ключ» (Composite key).
Один из вариантов создания составного ключа — написать отдельный класс, в котором поля будут содержать значения полей, входящих в составной ключ.
На примере класса Subscription:
public class Key implements Serializable {
@Column(name = "student_id")
private int studentId;
@Column(name = "course_id")
private int courseId;
//setters, getters, equals(), hashcode()
}
Класс составного ключа обязан:
- быть
public
; - иметь публичный конструктор по умолчанию;
- реализовывать собственные
equals()
,hashCode()
, публичные геттеры и сеттеры; - имплементировать
Serializable
.
Используется класс-ключ в @Entity
следующим образом:
@Entity
@Table(name = "Subscriptions")
public class Subscription {
@EmbeddedId
private Key id;
@Column(name = "student_id", insertable = false, updatable = false)
private int studentId;
@Column(name = "course_id", insertable = false, updatable = false)
private int courseId;
...
Аннотация @EmbeddedId
говорит, что данный параметр является составным ключом.
Если поля ключа использовать и в основном классе @Entity
, то необходимо запретить использовать поля для вставки и обновления данных дополнительными параметрами в аннотации @Column
.
Для получения объекта из базы данных по составному ключу необходимо в метод get()
объекта Session
передавать экземпляр составного ключа, например:
Subscription subscription = session.get(Subscription.class, new PK(studentId, courseId));
аналогично и для создания новой записи.
Дополнительные примеры найдёте в статье.
Рекомендации
- Измените параметр
hbm2ddl.auto
наupdate
в hibernate.cfg, чтобы структура базы данных обновлялась в зависимости от написанного кода классов@Entity
. - Список возможных вариантов
hbm2ddl.auto
:
validate
— проверить схему, не вносить изменения в базу данных;update
— обновить схему;create
— создаёт схему, уничтожая предыдущие данные;create-drop
— отказаться от схемы, когдаSessionFactory
закрывается явно — обычно, когда приложение остановлено.
TASK_10_4: HibernateExperiements
Критерии оценки
«Зачёт» — в базе данных создана таблица LinkedPurchaseList и заполнена на основе PurchaseList.
«Незачёт» — задание не выполнено.