Java Database Connectivity API (с JDK 1.1) - Это стандарт взаимодействия (спецификация) выступает в качестве посредника Java-приложения и различными СУБД. Это упрощает как процесс создания приложения, так и переход на базу данных другого типа.
Java Application
v
JDBC API
v
JDBC Driver Manager
v v v
JDBC Driver JDBC Driver JDBC Driver
v v v
Oracle Postgres Casandra
Чтобы с базой данных можно было работать из Java приложения поставщик базы данных пишет драйвер, который является своего образа адаптером.
Два способа подключения к БД (DriverManager, DataSource)
DriverManager.getConnection("jdbc:h2:mem:test", user, passwd);
ResultSet предоставляет методы для получения и манипуляции результатами выполненных запросов. next() для перемещения по строкам.
Раньше разработчики каждый раз сталкивались с Boilerplate code для тривиальных операций по сохранению Java объектов в БД и наоборот, созданию Java объектов по данным из БД. И тогда для решения этих проблем на свет появилось ORM.
— (англ. Object-relational mapping). В двух словах ORM — это отображение объектов какого-либо объектно-ориентированного языка в структуры реляционных баз данных. Именно объектов, со всеми полями, значениями, отношениями м/у друг другом.
JPA (Java Persistence API) это спецификация Java EE и Java SE, описывающая систему управления сохранением или извлечением java объектов из таблиц в реляционных DB. Сама Java не содержит реализации JPA, однако есть существует много реализаций данной спецификации например Hibernate.
java persistence api - модуль упрощает процесс создания приложений которые работают с базой данных, маппит сущности (объекты) в соответствующие им таблицы.
When we use JPQL for a query definition, then Spring Data can handle sorting without any problem — all we have to do is add a method parameter of type Sort:
@Query(value ="SELECT u FROM Author u")
List<Author>findAllAuthor(Sort sort);
We can call this method and pass a Sort parameter, which will order the result by the name property of the User object:
authorRepository.findAllAuthor(Sort.by("name"));
Spring Data JPA
Дополнительный механизм для взаимодействия с сущностями базы данных, организации их в репозитории, извлечение данных, изменение, в каких то случаях для этого будет достаточно объявить интерфейс и метод в нем, без имплементации.
// Теперь можно выполнять NamedQueryes точно также как и дефолтные методы в репозитории
// тоже самое что и findAllAuthor(), Spring формирует NamedQuery из названия метода
List<Author> a = authorRepository.findByFirstName("Thorben");
Pagination
Позволяет возвращать подмножество каких-то строк из БД. К примеру когда мы ходим подгружать только по нескольку товаров в каталоге на сайте а не сразу все. Минимизирует нагрузку на сеть, отсылая маленькие куски информации по запросу.
A Named Query defines a query with a predefined, unchangeable query string. These queries are fail-fast since they’re validated during the creation of the session factory. Let’s define a Named Query using the org.hibernate.annotations.NamedQuery annotation:
@NamedQuery(name ="Employee_FindByEmployeeId", query ="from Employee where id = :id")
The main advantage of Criteria Queries over HQL is the nice, clean, object-oriented API. As a result, we can detect errors in Criteria API during the compile time.
In addition, JPQL queries and Criteria queries have the same performance and efficiency.
Criteria queries are more flexible and provide better support for writing dynamic queries as compared to HQL and JPQL.
But HQL and JPQL provide native query support that isn’t possible with the Criteria queries. This is one of the disadvantages of the Criteria query.
We can easily write complex joins using JPQL native queries, whereas it gets difficult to manage while applying the same with Criteria API.
), но также предоставляет средства для автоматического построения запросов и извлечения данных и может значительно уменьшить время разработки, которое обычно тратится на ручное написание SQL и
кода. Hibernate генерирует SQL вызовы и освобождает разработчика от ручной обработки результирующего набора данных и конвертации объектов, сохраняя приложение портируемым во все SQL базы данных.
@Entity//аннотация, регистрирующая класс как сущность БД
@Table(name ="sessions")//связываем с конкретной таблицей по названию
publicclassSessionBeanimplementsSerializable{
@Column(name ="username")//название таблицы в БД
privateString username;//название поля класса
@Id// поле является ID и будет использоваться для поиска по умолчанию
@Column(name ="series")
privateString series;
}
Level 1 Cache- Session
Session cache(Всегда включен) - кэш в рамках одной session (аналог EntityManager в JPA).
L1 Cache используется в save(),update(),saveOrUpdate(),load(),get(),list(),iterate(),scroll() всегда.
Em em1 = session.get(Em.class,4);
Em em2 = session.get(Em.class,4);
// assert(em1 != em2)
assert(em1.equals(em2));
После первого запроса в базу объект Em будет закэширован. При повторном запросе в той же сессии, вернет объект с такими же полями.
Session – обёртка вокруг подключения JDBC к БД, используется один раз.
Session кэширует объект-сущность в Map:
key - id сущности, value - ResultSet (поля объекта).
Перед тем, как отправить объект в БД:
Поиск в кэше по id
Если есть - вернет сущность, без select в DB
Если нет - сделает select и сохранит ResultSet в кэш
Level 2 Cache- SessionFactory
SessionFactory cache(Включается отдельно) - общий кэш всех сессий SessionFactory (для нескольких сессий).
var session = factory.openSession();
Em director1 = session.get(Em.class,4);
session.close();
var session = factory.openSession();
Em director2 = session.get(Em.class,4);
session.close();
// только один запрос в базу
То есть одна сессия извлекла сущность, а другая может получить к этой сущности потом доступ. Очевидно, что с такой прослойкой есть проблема — данные могут устареть: в базе данные одни, а в кэше второго уровня — другие.
L2 Cash можно включить в настройках hibernate.cfg.xml, требуется провайдер кеша.
L2 Query Cache (Кэш запросов)
В Hibernate предусмотрен кэш для запросов, и он интегрирован с L2 Cache.
Это требует двух дополнительных физических мест для хранения кэшированных запросов и временных меток для обновления таблицы БД. Этот вид кэширования эффективен только для часто используемых запросов с одинаковыми параметрами.
Важно: хранит результат запроса, причём ключом является сам запрос и те параметры, которые были переданы в запросе. Хитро устроен: сохраняет не объекты целиком, а их id -шники.
Аннотации
@Transactional - метод выполняется в рамках транзакции. То есть в начале и в конце теста неявно выполняется begin() и commit() транзакции. Мы эти методы не видим, их вызывает Spring с помощью AOP.
@Cache - L2 Стратегии кэширования. Несколько потоков могут одновременно в разных транзакциях работать с одним и тем же объектом. В Hibernate существует четыре стратегии одновременного доступа к объектам в кэше:
Read-only - Для сущностей, которые никогда не изменяются (будет исключение, если попытаться обновить сущность).