Сущности
Сущность (entity) — это класс Java, объекты которого хранятся в таблице базы данных. Одна строка таблицы — один объект, один столбец — одно поле. Связь между классом и таблицей задают аннотации JPA, а Hibernate по ним сам строит SQL.
Сущность статьи
Запись Post из прошлой главы заменим классом. Удалите старый Post.java и создайте новый:
// src/main/java/com/example/blog/Post.java
package com.example.blog;
import java.time.Instant;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
@Entity
@Table(name = "posts")
public class Post {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false, length = 120)
private String title;
@Column(nullable = false, length = 10000)
private String body;
@Column(nullable = false)
private String author;
@Column(nullable = false)
private Instant createdAt;
protected Post() {
}
public Post(String title, String body, String author, Instant createdAt) {
this.title = title;
this.body = body;
this.author = author;
this.createdAt = createdAt;
}
public Long getId() {
return id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public String getAuthor() {
return author;
}
public Instant getCreatedAt() {
return createdAt;
}
}Что значат аннотации
| Аннотация | Смысл |
|---|---|
@Entity | Класс хранится в базе |
@Table(name = "posts") | Имя таблицы; без неё было бы post |
@Id | Первичный ключ |
@GeneratedValue(strategy = IDENTITY) | Номер назначает база при вставке строки |
@Column(nullable = false, length = 120) | Столбец NOT NULL, длина до 120 символов |
Поля без аннотаций тоже становятся столбцами. Имена Hibernate переводит в стиль SQL: поле createdAt превращается в столбец created_at.
Почему не запись
Hibernate создаёт объект пустым, а потом заполняет поля из строки таблицы. Для этого ему нужен конструктор без параметров, а для изменения — изменяемые поля. У записей нет ни того, ни другого, поэтому сущности — обычные классы. Конструктор без параметров объявлен protected: он нужен Hibernate, а в своём коде мы пользуемся вторым конструктором.
Сеттеры есть только у заголовка и текста — автор и дата создания после публикации не меняются.
Что получилось в базе
При запуске с ddl-auto: update Hibernate сам создаст таблицу и напечатает SQL:
Hibernate: create table posts (id bigint generated by default as identity, author varchar(255) not null, body varchar(10000) not null, created_at timestamp(6) with time zone not null, title varchar(120) not null, primary key (id))Instant стал timestamp with time zone, Long — bigint, а длина author по умолчанию — 255 символов. Таблицу можно увидеть в консоли /h2-console. Самого хранилища статей пока нет — его заменит репозиторий из следующего урока.
Частая ошибка
Если забыть @Id, приложение не запустится:
Entity 'com.example.blog.Post' has no identifier (every '@Entity' class must declare or inherit at least one '@Id' or '@EmbeddedId' property)У каждой сущности должен быть первичный ключ. Проверьте и импорт: аннотации берутся из пакета jakarta.persistence. Старый пакет javax.persistence из примеров для Spring Boot 2 в современных версиях не работает.