вторичная таблица гибернации для того же отношения сущности - PullRequest
0 голосов
/ 15 февраля 2020

У меня есть класс Profile, который содержит информацию о пользователе. Одной из особенностей этого приложения является «отслеживание» других профилей на ваш выбор. У меня возникают проблемы при проектировании БД и создании связи, при написании кода модели и репозитория (это просто вопрос сохранения?).

Мой класс Profile выглядит следующим образом: (нерелевантные поля на вопрос, и получатели / установщики опущены для простоты)

import javax.persistence.*;
import javax.validation.constraints.Email;
import javax.validation.constraints.Size;
import java.io.Serializable;
import java.lang.reflect.Array;
import java.util.*;

@Entity
@Table(name = "USERS")
public class Profile implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Size(max = 32)
    @Column(nullable = false)
    private String name;

    @Size(max = 16)
    @Column(unique=true, nullable = false)
    private String username;

    @Email
    @Column(unique=true)
    private String email;

    @ManyToOne
    @JoinColumn(name="profile_id")
    private Profile profile;

    @OneToMany(mappedBy = "profile")
    private List<Profile> friends = new ArrayList<>();


    public Profile() {
    }

    // other getters/setters

    public List<Profile> getFriends() {
        return friends;
    }

    public void setFriends(List<Profile> friends) {
        this.friends = friends;
    }

    public void addFriend(Profile friend) {
        this.friends.add(friend);
    }
}


Это создает поле null с именем profile_id в таблице пользователей. Я провел некоторые исследования, и кажется, что создание другой таблицы с использованием аннотации @SecondaryTable может помочь. Учебники, которые я изучал, не решили моих сомнений. Мне бы хотелось немного разобраться в этом вопросе, и, если возможно, избегать создания другой сущности.

В идеале, я бы хотел иметь таблицу с собственным идентификатором, идентификатором владельца (человека, который следует за ним) и ID цели (человека, за которым следят).

Заранее спасибо!

Ответы [ 2 ]

2 голосов
/ 16 февраля 2020

Вам нужна отдельная таблица для хранения следующих отношений (многие ко многим). Самый простой способ - использовать @ManyToMany:

@Entity
@Table(name = "USERS")
public class Profile implements Serializable {


        @ManyToMany(cascade = CascadeType.ALL)
        @JoinTable(name="following", 
                joinColumns={@JoinColumn(name="user_id")}, 
                inverseJoinColumns={@JoinColumn(name="follower_id")})
        private Set<Profile> followers = new HashSet<Profile>();

        @ManyToMany(mappedBy = "followers", cascade = CascadeType.ALL)
        private Set<Profile> followBy = new HashSet<Profile>();
}

. Он будет отображен в таблицу отношений с именем following, которая имеет следующую схему:

---------------------------------
| column      | FK              |
=================================
| user_id     | FK to users.id  |
---------------------------------
| follower_id | FK to users.id  |
---------------------------------

. пользователь A, поле followers - это все пользователи, которым следует A. И поле followBy - это все пользователи, которым следует A.

Кроме того, обратите внимание, что параметр mappedBy. Это означает, что вы должны использовать поле followers для поддержания следующих отношений, но не поле followBy, что в основном означает, что вы должны вставить / удалить экземпляры в followers Set, чтобы изменить следующие отношения для данного профиля.

Также см. this , если хотите добавить дополнительные столбцы в таблицу отношений (например, following таблица)

1 голос
/ 16 февраля 2020

Что ж, реализация отношения @ManyToMany имеет два подхода. Во-первых, создать отдельную таблицу только с соответствующими идентификаторами каждого объекта. И это может быть легко, но не охватывает все случаи. Например, в вашем случае вы реализуете @ManyToMany для пользователя и подписчиков. Вам также может понадобиться дата для этого, чтобы показать, в какую дату они создали эти отношения. И это тот случай, когда все немного усложняется (не сильно), но в результате получается кусок кода красоты. В любом случае давайте go для обоих подходов:

`

  @ManyToMany(cascade=CascadeType.ALL)
    @JoinTable(
    name = "profile_follower", 
    joinColumns = @JoinColumn(name = "profile_id", referencedColumnName="id"), 
    inverseJoinColumns = @JoinColumn(name = "following_id", referencedColumnName="id")
    private Set<Profile> profiles;
    @ManyToMany(mappedBy = "profiles")
    private Set<Profile> following= new HashSet<>();

`

Другой подход заключается в создании отдельного класса для отношения. `

@Entity
public class ProfilesFollowedByUser{
@EmbeddedId
UserFollower id;//this is a separate class

@ManyToOne
@MapsId("id")
@JoinColumn(name="profile_id", referencedColumnName="id")
private Profile profile;

@ManyToOne
@MapsId("id")
@JoinColumn(name="following_id", referencedColumnName="id")
private Profile profile;

private Date createdAt;}

` А вот встраиваемый класс:

`

@Embeddable
public class UserFollower implements Serializable{

    private static final long serialVersionUID = 819015237657421374L;

    @Column(name="profile_id")
    private Long profileId;
    @Column(name="following_id")
    private Long followingId;
}

` Второй, вероятно, немного сложнее, но в подавляющем большинстве Scenar ios, по крайней мере, в реальных приложениях, когда вам приходится иметь дело с отношениями, созданными, по крайней мере, всегда необходима дата. Надеюсь, что это поможет с вашей проблемой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...