Почему весенние данные jpa сопоставляют ассоциацию «один к одному» с «один ко многим»

у меня есть 2 объекта, студент и пользователь. Я использую JPA для создания отношений один к одному между ними следующим образом:



@Entity
@Table(name = "Student")
public class Student {
    @Id
    private Long id;
    private String specialty;
    private String level;
    private String type;
    private String institution;

    @OneToOne
    @MapsId
    @JoinColumn(name = "id")
    private User user;
}

@Entity
@Table(name = "User")
public class User {
    @Id
    private Long id;
    private String firstName;
    private String lastName;
    private String gender;
    private String birthDate;
    private String adress;
    private int phone;
    private String username;
    private String email;
    private String password;
    private String type;

    @OneToOne(mappedBy = "user")
    @PrimaryKeyJoinColumn
    private Student student;


}

это действительно создает отношения, однако, когда я иду в Mysql, чтобы увидеть таблицы, отношения один ко многим, а не один к одному.

Как вы определяете, что здесь точно есть отношение OneToMany? PrimaryJoinColumn в User просто неверен, так как у вас нет внешнего ключа для связи с первичным ключом (отношения отмечены как сопоставленные пользователем). Удаление этого сообщит JPA, что обе таблицы имеют только идентификатор, который должен быть уникальным, при этом Student.ID является внешним ключом для User.Id - один к одному.

Chris 12.04.2023 18:59

я могу сказать, потому что вы можете посмотреть схему в Mysql. и @PrimaryKeyKeyColumn, насколько я понимаю, необходим для создания ассоциации на основе первичного ключа

Azzedine Bk 12.04.2023 19:45

Ваше понимание неверно. Он чаще использовался в JPA 1.0 до того, как появились производные идентификаторы, где он был в основном нацелен на то, чтобы указать, как отображать несколько таблиц в одном и том же объекте (наследование и т. д.), и повторно использовался при сопоставлении ссылок. Возможно, вы использовали его в сопоставлении Student.user вместо MapsId, чтобы JPA знал, что внешний ключ в сопоставлении привязан к свойству id, но JPA НЕ установило бы для вас свойство id. Это будет вести себя так, как если бы вы установили joinColumn и указали тот же столбец ID и пометили его как updateable=false, insertable=false.

Chris 12.04.2023 20:12

@PrimaryKeyJoinColumn не следует использовать на стороне пользователя, поскольку вы уже сообщили JPA, что сопоставление управляется через сопоставление Student.user. Его добавление просто сбивает с толку, фактически заявляя, что оба идентификатора являются fks для другого идентификатора. Что касается того, что вы видите на схеме... что вы видите на схеме по сравнению с тем, что вы ожидаете увидеть? Нет большой разницы с ManyToOne и OneToOne без добавления ограничения уникальности на FK, а с другой стороны вы вообще не увидите fk.

Chris 12.04.2023 20:20

ах понял. Что касается того, что я ожидаю увидеть, я ожидаю увидеть отношение один к одному, так как это то, что я определяю, поэтому что вызвало сопоставление ассоциации с одним ко многим

Azzedine Bk 12.04.2023 20:33

Вы не определяете то, что видите, и нет никакой разницы в структуре таблицы между двунаправленным отношением OneToOne и отношением ManyToOne/OneToMany. Одна таблица будет иметь внешний ключ к другой. Единственное функциональное отличие, которое препятствует тому, чтобы двунаправленный ключ «один к одному» «был» OneToMany, заключается в том, что у вас может быть ограничение уникальности, наложенное на внешний ключ, гарантирующее, что только один дочерний элемент может ссылаться на родителя вместо многих. Вам это не нужно и вы не увидите здесь, потому что ваш внешний ключ является идентификатором дочернего элемента, поэтому он должен быть уникальным.

Chris 12.04.2023 22:00
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
6
140
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я попробовал именно ваш код в Hibernate 6.2, и это был сгенерированный DDL:

    create table Student (
        id bigint not null,
        institution varchar(255),
        level varchar(255),
        specialty varchar(255),
        type varchar(255),
        primary key (id)
    ) engine=InnoDB

    create table User (
        id bigint not null,
        adress varchar(255),
        birthDate varchar(255),
        email varchar(255),
        firstName varchar(255),
        gender varchar(255),
        lastName varchar(255),
        password varchar(255),
        phone integer not null,
        type varchar(255),
        username varchar(255),
        primary key (id)
    ) engine=InnoDB

    alter table Student 
       add constraint FKkfqq4nickg8wu56axc7jktv1 
       foreign key (id) 
       references User (id)

Мне кажется, это довольно хорошая ассоциация один к одному.

ОБНОВЛЯТЬ

Обратите внимание, что я бы отобразил вашу ассоциацию следующим образом, предполагая, что у каждого Student есть User:

    @Entity
    @Table(name = "Student")
    public static class Student {
        @Id
        private Long id;

        @OneToOne(optional=false)
        @MapsId 
        @JoinColumn(name = "id")
        private User user;
        ...
    }

    @Entity
    @Table(name = "User")
    public static class User {
        @Id
        private Long id;

        @OneToOne(mappedBy = "user")
        private Student student;
        ...
    }

Код работает. Это когда вы проверяете схему базы данных. В mysql отношение один ко многим, а не один к одному. Кроме того, почему вы не добавили @primarykeyjoincolumn?

Azzedine Bk 12.04.2023 15:55

Я все это понимаю. Я говорю, что получаю отношения, основанные на первичном ключе. Посмотрите на DDL, который я разместил! Спящий режим сгенерировал это. Это ассоциация один к одному.

Gavin King 12.04.2023 16:09

(И я не добавлял @PrimaryKeyJoinColumn, потому что это не нужно.)

Gavin King 12.04.2023 16:10

да, я вижу консоль, я получил те же результаты, что и вы, просто странно, как это происходит от одного ко многим в Mysql, и почему @PrimaryKeyColumn не нужен?

Azzedine Bk 12.04.2023 17:52

Другие вопросы по теме