1. Обзор
Hibernate не нуждается в представлении. Это самый популярный ORM для Java.
Аналогичным образом Spring Boot является наиболее мощной и простой в использовании инфраструктурой для Java.
Это руководство не о Hibernate или Spring Boot, их множество.
Мы рассмотрим некоторые распространенные ошибки, с которыми вы можете столкнуться при совместном использовании, и способы их устранения.
2. Зависимости
Мы будем использовать Gradle для создания нашего проекта. Я рекомендую использовать Spring Initializr для начальной загрузки вашего проекта.
Мы будем использовать:
- Spring Boot 2
- Spring Webflux
- Spring Data JPA
- Spring Data Envers
- Джексон Аннотации
- Джексон DataType Hibernate
- База данных H2
- Ломбок
Spring Data Envers позволяет нам получить доступ к ревизиям сущностей, управляемым Hibernate Envers.
Аннотации Джексона помогут нам избежать распространенных ошибок переполнения стека, вызванных отношениями JPA.
Модуль Jackson DataType Hibernate поможет с типами Hibernate и аспектами отложенной загрузки.
Мы рассмотрим все это через некоторое время.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
buildscript { ext { springBootVersion = '2.0.6.RELEASE' } ... } dependencies { implementation( 'org.springframework.boot:spring-boot-starter-data-jpa' ) implementation( 'org.springframework.boot:spring-boot-starter-webflux' ) implementation( "org.springframework.data:spring-data-envers" ) implementation( "com.fasterxml.jackson.core:jackson-annotations:2.9.7" ) implementation( "com.fasterxml.jackson.datatype:jackson-datatype-hibernate5:2.9.7" ) runtimeOnly( 'com.h2database:h2' ) compileOnly( 'org.projectlombok:lombok' ) ... } |
Мы будем использовать H2, чтобы запустить наш проект.
3. Сущности
В этом примере мы будем использовать JPA для создания университетов и студентов.
Всегда полезно хранить общую логику и свойства в суперклассе.
Мы создадим суперкласс для наших сущностей и будем хранить в нем общие свойства.
Давайте посмотрим на наш класс BaseEntity.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
@Getter @Setter @NoArgsConstructor @AllArgsConstructor @FieldDefaults (level = AccessLevel.PRIVATE) @MappedSuperclass @EntityListeners ({AuditingEntityListener. class }) @JsonIdentityInfo (generator = ObjectIdGenerators.PropertyGenerator. class , property = "id" ) public abstract class BaseEntity { @Id @GeneratedValue Long id; @CreatedDate LocalDateTime createdAt; @LastModifiedDate LocalDateTime updatedAt; } |
Вы можете заметить, что я не использовал аннотацию @Data
от Lombok в нашем классе. Аннотация @Data
автоматически добавляет аннотацию @ToString
которая может вызвать ошибки переполнения стека. Следовательно, лучше управлять аннотациями вручную.
Аннотация @MappedSuperclass
позволяет объектам наследовать свойства от базового класса. Эта аннотация очень важна, если вы хотите наследовать свойства от базового класса.
@EntityListeners({AuditingEntityListener.class})
включает аудит. Мы используем @CreatedDate
& @LastModifiedDate
для захвата, когда объект был создан или изменен. Об этом позаботится Spring Data JPA.
@JsonIdentityInfo
позволит избежать ошибок переполнения стека при преобразовании наших сущностей в JSON.
Эта аннотация требуется, чтобы разорвать бесконечный цикл из-за двунаправленных отношений между нашими объектами.
Вы также можете проверить @JsonBackReference
& @JsonManagedReference
чтобы убедиться, что они лучше соответствуют вашим требованиям.
Давайте посмотрим на наши университетские и студенческие организации.
1
2
3
4
5
6
7
|
@Getter @Setter @NoArgsConstructor @AllArgsConstructor @Builder @FieldDefaults (level = AccessLevel.PRIVATE) @Entity @Audited public class Student extends BaseEntity{ String name; @ManyToOne University university; } |
1
2
3
4
5
6
7
8
|
@Getter @Setter @NoArgsConstructor @AllArgsConstructor @Builder @FieldDefaults (level = AccessLevel.PRIVATE) @Entity @Audited public class University extends BaseEntity{ String name; String city; @OneToMany (mappedBy = "university" ) Set<Student> students = new HashSet<>(); } |
@Audited
позволит Hibernate управлять аудитом (отслеживанием изменений) на этом объекте.
4. Конфигурация
Давайте проверим конфигурации, необходимые для запуска нашего проекта.
4.1. Спящий модуль Джексона
1
2
3
4
|
@Bean public Module hibernateModule(){ return new Hibernate5Module(); } |
Мы регистрируем новый модуль Джексона.
Spring Boot автоматически обнаружит его и зарегистрирует в ObjectMapper
.
4.2. Спящий Энверс
Чтобы включить аудит Envers, мы должны расширить наши репозитории с помощью RevisionRepository
.
Давайте посмотрим на наш репозиторий UniversityRepository
.
1
2
|
public interface UniversityRepository extends RevisionRepository<University, Long, Long>, JpaRepository<University,Long> { } |
Мы должны сделать то же самое для нашего StudentRepository
.
1
2
|
public interface StudentRepository extends RevisionRepository<Student, Long, Long>, JpaRepository<Student,Long> { } |
Мы также должны аннотировать наш основной класс с помощью @EnableJpaRepositories(repositoryFactoryBeanClass = EnversRevisionRepositoryFactoryBean.class)
.
Мы рассмотрим основной класс через некоторое время, пройдя другие аннотации, которые нам нужны.
4,3. Spring Data Auditing
Чтобы включить это, нам нужно аннотировать наш основной класс с помощью @EnableJpaAuditing
.
Давайте посмотрим на это.
1
2
3
4
5
6
7
8
9
|
@SpringBootApplication @EnableJpaAuditing @EnableJpaRepositories (repositoryFactoryBeanClass = EnversRevisionRepositoryFactoryBean. class ) public class HibernateTipsApplication { public static void main(String[] args) { SpringApplication.run(HibernateTipsApplication. class , args); } } |
5. Заключение
Я попытался объяснить на простом примере, как создавать REST-приложения, используя Spring Boot & Hibernate.
Это может решить некоторые из ваших ошибок переполнения стека.
Иначе, вы можете подумать о написании своих собственных объектов передачи данных (DTO).
Если вам нужна поддержка типов данных, которые не поддерживаются ядром Hibernate ORM, вы можете воспользоваться этой библиотекой .
Вы можете прочитать больше о:
Вы можете найти полный пример на Github .