у меня есть 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, чтобы увидеть таблицы, отношения один ко многим, а не один к одному.
я могу сказать, потому что вы можете посмотреть схему в Mysql. и @PrimaryKeyKeyColumn, насколько я понимаю, необходим для создания ассоциации на основе первичного ключа
Ваше понимание неверно. Он чаще использовался в JPA 1.0 до того, как появились производные идентификаторы, где он был в основном нацелен на то, чтобы указать, как отображать несколько таблиц в одном и том же объекте (наследование и т. д.), и повторно использовался при сопоставлении ссылок. Возможно, вы использовали его в сопоставлении Student.user вместо MapsId, чтобы JPA знал, что внешний ключ в сопоставлении привязан к свойству id, но JPA НЕ установило бы для вас свойство id. Это будет вести себя так, как если бы вы установили joinColumn и указали тот же столбец ID и пометили его как updateable=false, insertable=false.
@PrimaryKeyJoinColumn не следует использовать на стороне пользователя, поскольку вы уже сообщили JPA, что сопоставление управляется через сопоставление Student.user. Его добавление просто сбивает с толку, фактически заявляя, что оба идентификатора являются fks для другого идентификатора. Что касается того, что вы видите на схеме... что вы видите на схеме по сравнению с тем, что вы ожидаете увидеть? Нет большой разницы с ManyToOne и OneToOne без добавления ограничения уникальности на FK, а с другой стороны вы вообще не увидите fk.
ах понял. Что касается того, что я ожидаю увидеть, я ожидаю увидеть отношение один к одному, так как это то, что я определяю, поэтому что вызвало сопоставление ассоциации с одним ко многим
Вы не определяете то, что видите, и нет никакой разницы в структуре таблицы между двунаправленным отношением OneToOne и отношением ManyToOne/OneToMany. Одна таблица будет иметь внешний ключ к другой. Единственное функциональное отличие, которое препятствует тому, чтобы двунаправленный ключ «один к одному» «был» OneToMany, заключается в том, что у вас может быть ограничение уникальности, наложенное на внешний ключ, гарантирующее, что только один дочерний элемент может ссылаться на родителя вместо многих. Вам это не нужно и вы не увидите здесь, потому что ваш внешний ключ является идентификатором дочернего элемента, поэтому он должен быть уникальным.
Я попробовал именно ваш код в 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?
Я все это понимаю. Я говорю, что получаю отношения, основанные на первичном ключе. Посмотрите на DDL, который я разместил! Спящий режим сгенерировал это. Это ассоциация один к одному.
(И я не добавлял @PrimaryKeyJoinColumn
, потому что это не нужно.)
да, я вижу консоль, я получил те же результаты, что и вы, просто странно, как это происходит от одного ко многим в Mysql, и почему @PrimaryKeyColumn не нужен?
Как вы определяете, что здесь точно есть отношение OneToMany? PrimaryJoinColumn в User просто неверен, так как у вас нет внешнего ключа для связи с первичным ключом (отношения отмечены как сопоставленные пользователем). Удаление этого сообщит JPA, что обе таблицы имеют только идентификатор, который должен быть уникальным, при этом Student.ID является внешним ключом для User.Id - один к одному.