Однонаправленное соответствие OneToOne в сущности с стороной первичного ключа

Вопрос или проблема

У меня есть две таблицы.

Человек: 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 и обеспечения целостности данных.

Оцените материал
Добавить комментарий

Капча загружается...