Pergunta

Estou tentando criar algum tipo de relação de usuário para usuário, como "o usuário A segue o usuário B" e "O usuário A quer ser amigo do usuário B."

Tenho uma classe de usuário e a forma como ela foi projetada é assim:

@Entity
public class User{
    @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
    List<User> followers;
    @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
    List<User> following;
    @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
    List<User> friendRequests;
    @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
    List<User> requesting;
    @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
    List<User> friends;

}

Estou tendo dois problemas:

  • O Hibernate está causando o problema de não consigo buscar vários sacos simultaneamente
  • Eu pesquisei online, pessoas disseram para remover FetchType.EAGER ou alterá-lo para Set em vez de List, mas isso me resultou O campo não tem um valor padrão

Tenho a sensação de que a relação não está definida corretamente e também devo ver mais tabelas, porque agora, vejo apenas a tabela User e a tabela User_User.


Atualizar

O seguinte cria 3 tabelas, amigos, seguidores e solicitantes. Isso é um pouco otimizado em comparação com 5 tabelas? E há alguma vantagem nisso em comparação com o que o Sr. J4mes sugeriu?

@ManyToMany
@JoinTable(name = "followers", joinColumns = @JoinColumn(name = "followerId"), inverseJoinColumns = @JoinColumn(name = "userId"))
private List<User> followers;
@ManyToMany
@JoinTable(name = "followers", joinColumns = @JoinColumn(name = "userId"), inverseJoinColumns = @JoinColumn(name = "followerId"))
private List<User> following;
@ManyToMany
@JoinTable(name = "friends", joinColumns = @JoinColumn(name = "userId"), inverseJoinColumns = @JoinColumn(name = "friendId"))
private List<User> friends;
@ManyToMany
@JoinTable(name = "requesters", joinColumns = @JoinColumn(name = "requesterId"), inverseJoinColumns = @JoinColumn(name = "userId"))
private List<User> friendRequests;
@ManyToMany
@JoinTable(name = "requesters", joinColumns = @JoinColumn(name = "userId"), inverseJoinColumns = @JoinColumn(name = "requesterId"))
private List<User> requesting;
Foi útil?

Solução

Em primeiro lugar, para implementar seu recurso, você deve usar @ManyToMany em vez de @OneToMany.Deve ser assim:

@Entity
public class User implements Serializable {
   @ManyToMany(mappedBy="followers")
   @JoinTable(name="followingTable")
   private Set<User> following;
   @ManyToMany
   @JoinTable(name="followerTable")
   private Set<User> followers;
   @ManyToMany(mappedBy="friendRequests")
   @JoinTable(name="requestingTable")
   private Set<User> requesting;
   @ManyToMany
   @JoinTable(name="friendRequestTable")
   private Set<User> friendRequests;
   @ManyToMany
   private Set<User> friends;
}

Seus relacionamentos parecem bidirecionais para mim.Se você usar @OneToMany, significa que C has 2 followers A and B= A and B only follows C.No entanto, o fato é que uma pessoa pode seguir muitas pessoas e uma pessoa pode ser seguida por muitas pessoas.Em outras palavras, A and B can also follow D.

Além disso, você não deve usar cascadeType.ALL de forma alguma.Essa política em cascata significa que se um usuário excluir sua conta e você excluir a entrada correspondente no banco de dados, todos os seus amigos, etc. também serão excluídos.

Outras dicas

O Hibernate irá gerar apenas uma tabela para a entidade User, e estou assumindo uma tabela de referência cruzada para o relacionamento User to User.A solução alternativa para ter tabelas diferentes pode ser ter diferentes configurações de entidades para os diferentes relacionamentos, ou seja,

Entidade do usuário

@OneToMany
List<Follower> followers;

Entidade Seguidora

@Entity
class Follower
...
@ManyToOne
User user;

@Id
@Generated
int id;

Quanto à busca EAGER, você pode querer que todos eles sejam LAZY, devido ao fato de que dependendo de como seu banco de dados está configurado, todas essas cargas ansiosas podem ser bastante caras.Somente quando o usuário deseja carregar os seguidores do usuário, eu gostaria de buscá-los.

Separe o User do Friends, tente fazer uma tabela com pelo menos 2 colunas que mapeie o User_ID para todo o seu Friends_IDs, que é basicamente uma referência ao User_ID

Além disso, EAGER carregará TODOS os dados assim que você chamá-lo pela primeira vez.Significa que carregará todos os usuários e seus amigos.O carregamento de amigos deve ser LAZY, ou seja, carregado apenas quando você precisa deles.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top