Вопрос или проблема
У меня есть две таблицы.
Человек: id, имя
Электронная почта: id, адрес электронной почты, person_id
Здесь “person_id” является внешним ключом, который ссылается на id в таблице человека. Учтите, что у каждого человека будет только одна электронная почта, и каждая электронная почта связана только с одним человеком.
Я хочу получить доступ к данным электронной почты в сущности человека, но не наоборот.
@Entity
@Table(name = "EMAIL")
public class Email {
@Id
private int id;
@Column(name = "EMAIL_ADDRESS")
private int emailAddress;
@Column(name = "STUDENT_ID", unique = true)
private String studentId;
}
@Entity
@Table(name = "STUDENT")
public class Student {
@Id
@Column(name = "ID")
private String id;
@Column(name = "NAME")
private String name;
@Column(name = "AGE")
private int age;
// однопортальное соответствие один к одному
private Email email;
}
Поскольку каждая Email
связана только с одним Student
, мы будем использовать однопортальное
@OneToOne
соответствие в сущности Student
.
Вот шаги для реализации логики
1 ) Обновленная Email
сущность
import jakarta.persistence.*;
@Entity
@Table(name = "EMAIL")
public class Email {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID")
private int id;
@Column(name = "EMAIL_ADDRESS", nullable = false, unique = true)
private String emailAddress;
// Удалите столбец "STUDENT_ID", так как связь будет управляться из сущности `Student`
// Геттеры и сеттеры
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getEmailAddress() {
return emailAddress;
}
public void setEmailAddress(String emailAddress) {
this.emailAddress = emailAddress;
}
}
2 ) Обновленная Student
сущность
Добавьте однопортальное @OneToOne
соответствие с Email. Используйте аннотацию @JoinColumn
, чтобы указать столбец внешнего ключа (person_id
)
import jakarta.persistence.*;
@Entity
@Table(name = "STUDENT")
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID")
private int id;
@Column(name = "NAME", nullable = false)
private String name;
@Column(name = "AGE")
private int age;
// Однопортальное соответствие один к одному с Email
@OneToOne
@JoinColumn(name = "PERSON_ID", referencedColumnName = "ID", unique = true)
private Email email;
// Геттеры и сеттеры
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Email getEmail() {
return email;
}
public void setEmail(Email email) {
this.email = email;
}
}
3 ) Определите StudentRepository
public interface StudentRepository extends JpaRepository<Student, Integer> {
}
4 ) Определите Student
сервис
@Service
public class StudentService {
@Autowired
private StudentRepository studentRepository;
public void displayStudentEmail(int studentId) {
studentRepository.findById(studentId).ifPresent(student -> {
System.out.println("Имя студента: " + student.getName());
System.out.println("Электронная почта студента: " + student.getEmail().getEmailAddress());
});
}
}
Ответ или решение
Одностороннее сопоставление «Один к одному» с использованием первичного ключа: Подход к реализации в Java с использованием JPA
В данном ответе мы подробно рассмотрим, как реализовать одностороннее сопоставление «Один к одному» между сущностями Student
и Email
в контексте использования Java Persistence API (JPA). Мы создадим модель, в которой каждый студент имеет только один адрес электронной почты, и наоборот.
1. Определение сущностей
Мы начинаем с создания двух сущностей: Email
и Student
. Каждая из этих сущностей будет отображать таблицы с соответствующими атрибутами.
Обновленная сущность Email
import jakarta.persistence.*;
@Entity
@Table(name = "EMAIL")
public class Email {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID")
private int id;
@Column(name = "EMAIL_ADDRESS", nullable = false, unique = true)
private String emailAddress;
// Геттеры и сеттеры
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getEmailAddress() {
return emailAddress;
}
public void setEmailAddress(String emailAddress) {
this.emailAddress = emailAddress;
}
}
В этой реализации мы устанавливаем уникальность для адреса электронной почты и убираем поле person_id
, поскольку оно будет управляться из сущности Student
.
Обновленная сущность Student
import jakarta.persistence.*;
@Entity
@Table(name = "STUDENT")
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID")
private int id;
@Column(name = "NAME", nullable = false)
private String name;
@Column(name = "AGE")
private int age;
// Одностороннее сопоставление «Один к одному» с Email
@OneToOne
@JoinColumn(name = "PERSON_ID", referencedColumnName = "ID", unique = true)
private Email email;
// Геттеры и сеттеры
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Email getEmail() {
return email;
}
public void setEmail(Email email) {
this.email = email;
}
}
В этой сущности мы устанавливаем одностороннее сопоставление с использованием аннотации @OneToOne
. Мы указываем, что столбец PERSON_ID
будет использоваться для связи с сущностью Email
.
2. Определение репозитория
Создадим интерфейс StudentRepository
, который будет обеспечивать взаимодействие с БД:
public interface StudentRepository extends JpaRepository<Student, Integer> {
}
Этот интерфейс на основе JpaRepository
предоставляет базовые методы для работы с сущностью Student
.
3. Создание сервиса
Создадим сервис StudentService
, который будет использовать наш репозиторий для извлечения данных о студентах и их адресах электронной почты:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class StudentService {
@Autowired
private StudentRepository studentRepository;
public void displayStudentEmail(int studentId) {
studentRepository.findById(studentId).ifPresent(student -> {
System.out.println("Имя студента: " + student.getName());
System.out.println("Email студента: " + student.getEmail().getEmailAddress());
});
}
}
В этом сервисе мы используем метод findById
для получения студента по его идентификатору и выводим на консоль имя студента и его электронную почту.
Заключение
Использование одностороннего сопоставления «Один к одному» в JPA позволяет создать четкую и простую структуру связи между сущностями Student
и Email
. Это решение подходит для случаев, когда вам нужно управлять объектами без необходимости обратного доступа, что улучшает инкапсуляцию данных и упрощает бизнес-логику.
Таким образом, данная реализация предоставляет вам все необходимые инструменты для эффективного использования одностороннего сопоставления в вашем проекте, соблюдая при этом принципы применения JPA и обеспечения целостности данных.