Java: сопоставление Hibernate @OneToOne

Я пытаюсь заставить работать аннотации Hibernate @OneToOne и не добился здесь большого успеха...

Допустим, у меня есть таблица с именем status, которая выглядит так:

+------------------------------------------------+
|                     status                     |
+------------------------------------------------+
| id | frn_user_id | frn_content_id |   status   |
+----+-------------+----------------+------------+
|  1 |     111     |        0       |  "active"  |
+----+-------------+----------------+------------+
|  2 |      0      |       222      | "inactive" |
+----+-------------+----------------+------------+

И у меня есть сущность для User, которая выглядит так:

@Entity
@Table(name = "user")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id", nullable = false)
    private Integer id;

    @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "userId")
    private Status status;

    // getters and setters
}

И аналогичный объект для Content, и еще один объект для Status, который выглядит так:

@Entity
@Table(name = "status")
public class Status {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id", nullable = false)
    private Integer id;

    @Column(name = "frn_user_id")
    private Integer userId;

    @Column(name = "frn_content_id")
    private Integer contentId;

    @Column(name = "status")
    private String status;

    // getters and setters
}

Когда я выполняю чтение User, я ожидаю, что User.getStatus() вернет объект Status с id=1. Вместо этого я получаю AnnotationException: «Свойство, указанное в ссылке, не является (One | Many) ToOne: Status.userId в mappedBy User.status»

Я просмотрел документы, учебные пособия и примеры здесь, на SO, но все, что я пробовал до сих пор, не удалось.

Также стоит отметить: это должно поддерживать отношение один к нулю или один, так как некоторые записи user и content не будут иметь ссылки в таблице status.

Любая помощь будет принята с благодарностью!


person Shaun Scovil    schedule 13.02.2014    source источник
comment
userId должен быть типа User с @OneToOne/@JoinColumn на нем. Также обратите внимание, что у вас есть опечатка (contentId/userId)   -  person    schedule 13.02.2014
comment
см. также stackoverflow .com/questions/18303522/   -  person    schedule 13.02.2014
comment
Просто идея дизайна базы данных: может быть, вы могли бы пересмотреть свой дизайн как отношения «многие ко многим» между пользователями и содержимым, а описание статуса было бы в этом дизайне атрибутом пользователя?   -  person Jorge_B    schedule 13.02.2014
comment
Спасибо @RC. Я не понимал, что это должен быть объект.   -  person Shaun Scovil    schedule 13.02.2014
comment
@Jorge_B Да, дизайн БД не идеален, но пока я его использую.   -  person Shaun Scovil    schedule 13.02.2014


Ответы (2)


Ваш объект Status не должен иметь свойства userId и contentId типа Integer, сопоставленные с @Column. Он должен иметь свойства user и content типа User и Content, сопоставленные с @OneToOne:

public class User {
    @OneToOne(mappedBy = "user")
    private Status status;
    // ...
}

public class Status {
    @OneToOne
    @JoinColumn(name = "frn_user_id")
    private User user;
    // ...
}

Пользователь имеет один статус. Статус имеет один пользователь.

person JB Nizet    schedule 13.02.2014
comment
Спасибо, что поделились этим. Я застрял на mappedBy за последние 3 дня. Я погуглил и просмотрел так много сообщений Stackoverflow для этого, но мне не повезло. Когда я просматриваю ваше решение, я вспоминаю я создал сопоставление java.util.Set в OneToOne на обратной стороне отношения. Как только я удалил свойство Set и просто создал свойство типа сущности, мой код начал работать. Большое спасибо. Проголосовать. - person OO7; 10.04.2015
comment
Я немного смущен после того, как прошел @Vlad Mihalcea Ответить на этот пост. В своем ответе Child имеет many toys, тогда почему он аннотировал List<Toy> toys OneToOne(mappedBy = "child")? Почему не с OneToMany ? Также вы указали JoinColumn на User в Status, а Влад Михалча не указал на Child в Toy. Какова цель mappedBy с/без JoinColumn ? Не могли бы вы развеять мои сомнения? - person OO7; 10.04.2015
comment
Это не правильно. Это должно быть OneToMany. JoinColumn используется для указания имени столбца соединения. Если вы не укажете его, Hibernate будет использовать имя по умолчанию (как создается это имя по умолчанию, имя указано в спецификации JPA) - person JB Nizet; 10.04.2015
comment
Я использовал тот же код, который вы упомянули здесь. Но все же я получаю frn_user_id как null - person viper; 24.08.2016

используйте этот способ. Добавьте поле ниже в сущность «Клиент».

@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "customer")
private Status status;

и не добавляйте геттер и сеттер для поля статуса в объекте «Клиент». И добавьте приведенный ниже код в объект статуса.

@OneToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "customer_id", nullable = false)
private Customer customer;

Здесь добавьте геттер и сеттер для поля клиента в классе Status Entity. Вы можете увидеть один рабочий пример здесь.

person Abhishek    schedule 02.11.2019