«1. Введение
В этом руководстве мы узнаем об основах сущностей, а также о различных аннотациях, которые определяют и настраивают сущность в JPA.
2. Сущность
Сущности в JPA — это не что иное, как POJO, представляющие данные, которые могут быть сохранены в базе данных. Сущность представляет собой таблицу, хранящуюся в базе данных. Каждый экземпляр объекта представляет собой строку в таблице.
2.1. Аннотация объекта
Допустим, у нас есть POJO под названием Student, который представляет данные студента, и мы хотели бы сохранить его в базе данных.
public class Student {
// fields, getters and setters
}
Чтобы сделать это, мы должны определить сущность, чтобы JPA знал о ней.
Итак, давайте определим его, используя аннотацию @Entity. Мы должны указать эту аннотацию на уровне класса. Мы также должны убедиться, что сущность имеет конструктор без аргументов и первичный ключ:
@Entity
public class Student {
// fields, getters and setters
}
Имя сущности по умолчанию совпадает с именем класса. Мы можем изменить его имя, используя элемент name.
@Entity(name="student")
public class Student {
// fields, getters and setters
}
Поскольку различные реализации JPA будут пытаться создать подкласс нашей сущности, чтобы обеспечить свою функциональность, классы сущностей не должны объявляться окончательными.
2.2. Аннотация Id
Каждый объект JPA должен иметь первичный ключ, который однозначно идентифицирует его. Аннотация @Id определяет первичный ключ. Мы можем генерировать идентификаторы разными способами, которые указаны в аннотации @GeneratedValue.
Мы можем выбрать одну из четырех стратегий генерации идентификатора с элементом стратегии. Значение может быть AUTO, TABLE, SEQUENCE или IDENTITY.
@Entity
public class Student {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
private String name;
// getters and setters
}
Если мы укажем GenerationType.AUTO, провайдер JPA будет использовать любую стратегию, которую он хочет, для генерации идентификаторов.
Если мы аннотируем поля объекта, провайдер JPA будет использовать эти поля для получения и установки состояния объекта. В дополнение к доступу к полю мы также можем использовать доступ к свойствам или смешанный доступ, что позволяет нам использовать доступ к полям и свойствам в одном и том же объекте.
2.3. Аннотация к таблице
В большинстве случаев имя таблицы в базе данных и имя объекта не будут совпадать.
В этих случаях мы можем указать имя таблицы, используя аннотацию @Table:
@Entity
@Table(name="STUDENT")
public class Student {
// fields, getters and setters
}
Мы также можем указать схему, используя элемент schema:
@Entity
@Table(name="STUDENT", schema="SCHOOL")
public class Student {
// fields, getters and setters
}
Имя схемы помогает различать один набор таблицы из другой,
Если мы не используем аннотацию @Table, имя сущности будет считаться именем таблицы.
2.4. Аннотация столбца
Так же, как и аннотация @Table, мы можем использовать аннотацию @Column, чтобы упомянуть детали столбца в таблице.
Аннотация @Column имеет множество элементов, таких как имя, длина, значение, допускающее значение NULL, и уникальность.
@Entity
@Table(name="STUDENT")
public class Student {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
@Column(name="STUDENT_NAME", length=50, nullable=false, unique=false)
private String name;
// other fields, getters and setters
}
Элемент name указывает имя столбца в таблице. Элемент length определяет его длину. Элемент nullable указывает, допускает ли столбец значение null или нет, а элемент unique указывает, является ли столбец уникальным.
Если мы не укажем эту аннотацию, имя поля будет считаться именем столбца в таблице.
2.5. Временная аннотация
Иногда нам может понадобиться сделать поле непостоянным. Для этого мы можем использовать аннотацию @Transient. Указывает, что поле не будет сохранено.
Например, мы можем рассчитать возраст студента по дате рождения.
Итак, давайте аннотируем поле age аннотацией @Transient:
@Entity
@Table(name="STUDENT")
public class Student {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
@Column(name="STUDENT_NAME", length=50, nullable=false)
private String name;
@Transient
private Integer age;
// other fields, getters and setters
}
В результате возраст поля не будет сохранен в таблице.
2.6. Временная аннотация
В некоторых случаях нам может понадобиться сохранить временные значения в нашей таблице.
Для этого у нас есть аннотация @Temporal:
@Entity
@Table(name="STUDENT")
public class Student {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
@Column(name="STUDENT_NAME", length=50, nullable=false, unique=false)
private String name;
@Transient
private Integer age;
@Temporal(TemporalType.DATE)
private Date birthDate;
// other fields, getters and setters
}
Однако в JPA 2.2 у нас также есть поддержка java.time.LocalDate, java.time.LocalTime, java.time.LocalDateTime, java. time.OffsetTime и java.time.OffsetDateTime.
2.7. Перечисленная аннотация
Иногда нам может понадобиться сохранить тип перечисления Java.
Мы можем использовать аннотацию @Enumerated, чтобы указать, должно ли перечисление сохраняться по имени или по порядковому номеру (по умолчанию).
public enum Gender {
MALE,
FEMALE
}
@Entity
@Table(name="STUDENT")
public class Student {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
@Column(name="STUDENT_NAME", length=50, nullable=false, unique=false)
private String name;
@Transient
private Integer age;
@Temporal(TemporalType.DATE)
private Date birthDate;
@Enumerated(EnumType.STRING)
private Gender gender;
// other fields, getters and setters
}
«На самом деле, нам вообще не нужно указывать аннотацию @Enumerated, если мы собираемся сохранять пол по порядковому номеру перечисления.
Однако, чтобы сохранить пол по имени перечисления, мы настроили аннотацию с помощью EnumType.STRING.
3. Заключение
В этой статье мы узнали, что такое объекты JPA и как их создавать. Мы также узнали о различных аннотациях, которые можно использовать для дальнейшей настройки объекта.