Отношения JPA OneToMany и ManyToOne

У меня есть три класса, одно из которых - это Пользователь, и у этого пользователя есть экземпляры других классов. Вот так:

public class User{
    @OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL)
    public List<APost> aPosts;

    @OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL)
    public List<BPost> bPosts;
}




   public class BPost extends Post {

    @ManyToOne(fetch=FetchType.LAZY)    
    public User user;
 }

    public class APost extends Post {

     @ManyToOne(fetch=FetchType.LAZY) 
     public User user;
 }

он работает так, но генерирует таблицы emty в db. Которые должны содержать внешние ключи. Когда я попытался использовать аннотации mappedBy и JoinColumn, я потерпел неудачу. Как я могу это решить?

Дополнительная информация:

Когда я изменил с помощью

 @ManyToOne(fetch=FetchType.LAZY)
 @JoinColumn(name="id")
 public User user;

и

 @OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL, mappedBy="id")
 public List<APost> aPosts;

Я получаю

Произошла ошибка JPA (невозможно построить EntityManagerFactory): повторный столбец при сопоставлении для объекта: models.post.APost column: id (должен быть сопоставлен с insert = "false" update = "false" )

Заключительное редактирование: Наконец, я ошибся в аннотации ipa.:( Когда я меняю

@OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL, mappedBy="id")

к

@OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL, mappedBy="user")

и

@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="user_id")

все работает нормально.:)

Ответ 1

Как я объяснил в этой статье, и в моей книге " Высокопроизводительное сохранение Java" вы никогда не должны использовать однонаправленную аннотацию @OneToMany потому что:

  1. Он генерирует неэффективные операторы SQL
  2. Он создает дополнительную таблицу, которая увеличивает объем памяти ваших индексов DB

Теперь, в вашем первом примере, обе стороны владеют ассоциацией, и это плохо.

Хотя @JoinColumn позволит стороне @OneToMany отвечать за ассоциацию, это определенно не лучший выбор. Поэтому, всегда используйте mappedBy атрибут на @OneToMany стороне.

public class User{
    @OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL, mappedBy="user")
    public List<APost> aPosts;

    @OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL, mappedBy="user")
    public List<BPost> bPosts;
}

public class BPost extends Post {

    @ManyToOne(fetch=FetchType.LAZY)    
    public User user;
}

public class APost extends Post {

     @ManyToOne(fetch=FetchType.LAZY) 
     public User user;
}

Ответ 2

Я не уверен в вашем вопросе (значение "пустой стол" и т.д., или как mappedBy и JoinColumn не работают).

Я думаю, вы пытались сделать двунаправленные отношения.

Во-первых, вам нужно решить, какая сторона "владеет" отношениями. Hibernate собирается настроить базу отношений с этой стороны. Например, предположим, что я делаю стороной Post собственную связь (я упрощаю ваш пример, просто чтобы все было в порядке), сопоставление будет выглядеть следующим образом:

(Желаю синтаксиса правильно, я пишу их только по памяти. Однако идея должна быть прекрасной)

public class User{
    @OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL, mappedBy="user")
    private List<Post> posts;
}


public class Post {
    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="user_id")
    private User user;
}

Таким образом, таблица для Post будет иметь столбец user_id, который сохранит это отношение. Hibernate получает отношение user в Post (вместо posts в user. Вы заметите разницу, если у вас есть Post user, но отсутствует user posts).

Вы упомянули mappedBy и JoinColumn не работает. Однако я считаю, что это на самом деле правильный путь. Скажите, не работает ли этот подход для вас и дайте нам немного больше информации о проблеме. Я считаю, что проблема связана с чем-то еще.


Edit:

Немного дополнительная информация об использовании mappedBy, поскольку это обычно путается вначале. В mappedBy мы помещаем "имя свойства" в противоположную сторону двунаправленного отношения, а не в имя столбца таблицы.

Ответ 3

Используете ли вы правильную конфигурацию в вашем приложении application.conf?

db=mysql://user:[email protected]/database

Я тоже столкнулся с аналогичной проблемой, решаемой, предоставив права администратора на имя пользователя db, которое вы используете в своем файле conf.

Ответ 4

Поскольку вы будете автоматически сохранять APost и BPost, это означает, что APost и BPost будут владельцем отношений. Поскольку пользователь не имеет отношения, в анноте @OneToMany будет отображаться атрибут, связанный с ним.

public class User{
    @OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL,mappedBy="user", targetEntity = APost.class)
    public List<APost> aPosts;

    @OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL,mappedBy="user", targetEntity = BPost.class)
    public List<BPost> bPosts;
}

public class BPost extends Post {
    @ManyToOne(fetch=FetchType.LAZY)  
    @JoinColumn(name="user_id",referencedColumnName="id")  
    public User user;
}

public class APost extends Post {
    @ManyToOne(fetch=FetchType.LAZY) 
    @JoinColumn(name="user_id",referencedColumnName="id")
    public User user;
}

аннотация @JoinColumn будет отвечать за добавление внешнего ключа в Apost и BPost.