Какие знаешь элементы JPA?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Элементы JPA (Java Persistence API)
JPA — это спецификация для управления персистентностью объектов в Java, которая предоставляет стандартный способ взаимодействия приложений с реляционными базами данных. Расскажу об основных элементах, которые регулярно использую.
1. Entity (Сущность)
Entity — это основной класс JPA, который представляет таблицу в БД. Каждый объект сущности соответствует строке в таблице.
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
private UUID id;
@Column(name = "username", nullable = false, unique = true)
private String username;
@Column(name = "email")
private String email;
@CreationTimestamp
@Column(name = "created_at", nullable = false)
private LocalDateTime createdAt;
// конструктор, getters, setters
}
2. Annotations (Аннотации)
@Entity — отмечает класс как JPA сущность @Table — указывает имя таблицы в БД @Id — обозначает первичный ключ @GeneratedValue — конфигурирует генерацию значений Id @Column — маппит поле на колонку БД @Transient — исключает поле из сохранения @Enumerated — сохраняет enum значения @Temporal — для хранения дат и времени
@Entity
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;
@Column(name = "status")
@Enumerated(EnumType.STRING)
private OrderStatus status;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "order_date")
private Date orderDate;
@Transient
private String temporaryCalculation;
}
3. Relationships (Связи)
Четыре типа связей между сущностями.
@OneToOne — один к одному
@Entity
public class User {
@OneToOne(mappedBy = "user", cascade = CascadeType.ALL)
private UserProfile profile;
}
@Entity
public class UserProfile {
@OneToOne
@JoinColumn(name = "user_id", unique = true)
private User user;
}
@OneToMany и @ManyToOne — один ко многим
@Entity
public class Author {
@OneToMany(mappedBy = "author", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Book> books = new ArrayList<>();
}
@Entity
public class Book {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "author_id")
private Author author;
}
@ManyToMany — многие ко многим
@Entity
public class Student {
@ManyToMany
@JoinTable(
name = "student_course",
joinColumns = @JoinColumn(name = "student_id"),
inverseJoinColumns = @JoinColumn(name = "course_id")
)
private Set<Course> courses = new HashSet<>();
}
@Entity
public class Course {
@ManyToMany(mappedBy = "courses")
private Set<Student> students = new HashSet<>();
}
4. EntityManager
EntityManager — это объект, который управляет жизненным циклом сущностей. Это главное API для работы с БД.
@Service
public class UserService {
@PersistenceContext
private EntityManager entityManager;
// Сохранение
public User save(User user) {
entityManager.persist(user);
return user;
}
// Получение по ID
public User findById(UUID id) {
return entityManager.find(User.class, id);
}
// Обновление
@Transactional
public User update(User user) {
return entityManager.merge(user);
}
// Удаление
@Transactional
public void delete(User user) {
entityManager.remove(entityManager.merge(user));
}
}
5. Persistence Context (Контекст сохраняемости)
Persistence Context — это кэш сущностей в памяти. Он отслеживает изменения объектов и синхронизирует их с БД при коммите транзакции.
Статусы сущностей:
- New — только создана, не в контексте
- Managed — в контексте, JPA отслеживает изменения
- Detached — была в контексте, теперь нет
- Removed — помечена на удаление
@Transactional
public void demoLifecycle() {
User user = new User(); // NEW
user.setUsername("john");
entityManager.persist(user); // MANAGED
user.setUsername("jane"); // изменение отслеживается
// В конце транзакции UPDATE выполнится автоматически
}
6. Queries (Запросы)
JPQL — это объектно-ориентированный язык запросов.
@Repository
public interface UserRepository extends JpaRepository<User, UUID> {
@Query("SELECT u FROM User u WHERE u.username = :username")
Optional<User> findByUsername(@Param("username") String username);
@Query("SELECT u FROM User u WHERE u.email LIKE %:email%")
List<User> searchByEmail(@Param("email") String email);
@Query("SELECT COUNT(u) FROM User u WHERE u.active = true")
long countActiveUsers();
}
Native queries — использование SQL напрямую
public interface UserRepository extends JpaRepository<User, UUID> {
@Query(
value = "SELECT * FROM users WHERE created_at > :date",
nativeQuery = true
)
List<User> findRecentUsers(@Param("date") LocalDateTime date);
}
7. Cascading (Каскадные операции)
Cascade определяет, как операции на родительской сущности влияют на дочерние.
@Entity
public class Company {
@OneToMany(
mappedBy = "company",
cascade = {CascadeType.PERSIST, CascadeType.REMOVE},
orphanRemoval = true
)
private List<Employee> employees = new ArrayList<>();
}
Типы каскада:
- PERSIST — если сохранить родителя, сохранятся дети
- REMOVE — если удалить родителя, удалятся дети
- MERGE — обновление распространяется на детей
- REFRESH — обновление из БД распространяется на детей
- DETACH — отсоединение распространяется на детей
- ALL — все операции
8. Fetch Strategies (Стратегии загрузки)
EAGER — данные загружаются сразу LAZY — данные загружаются по необходимости
@Entity
public class Order {
@ManyToOne(fetch = FetchType.EAGER)
private Customer customer; // загружается сразу
@OneToMany(fetch = FetchType.LAZY)
private List<OrderItem> items; // загружается лениво
}
9. Validation (Валидация)
Aннотации для валидации данных перед сохранением.
@Entity
public class User {
@NotNull
@Size(min = 3, max = 50)
private String username;
@NotNull
@Email
private String email;
@Min(18)
@Max(150)
private int age;
}
10. Lifecycle Callbacks (Callbacks жизненного цикла)
Методы, которые вызываются автоматически при определённых событиях.
@Entity
public class User {
@PrePersist
protected void onCreate() {
createdAt = LocalDateTime.now(UTC);
}
@PreUpdate
protected void onUpdate() {
updatedAt = LocalDateTime.now(UTC);
}
@PostLoad
protected void afterLoad() {
// логика после загрузки из БД
}
}
Заключение
JPA предоставляет мощный и гибкий способ работать с БД на уровне объектов. Правильное использование этих элементов значительно упрощает разработку и делает код более поддерживаемым. Ключ — выбрать подходящую стратегию для конкретной задачи.