Pregunta

Estoy intentando diseñar algún tipo de relación de usuario a usuario, como "el usuario A sigue al usuario B" y "El usuario A quiere ser amigo del usuario B".

Tengo una clase de Usuario y la forma en que está diseñada se ve así:

@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;

}

Me encuentro con dos problemas:

  • Hibernar me está dando no se pueden recuperar varias bolsas simultáneamente problema
  • Busqué en línea, la gente dijo que eliminara FetchType.EAGER o lo cambiara a Establecer en lugar de Lista, pero eso resultó en mí. El campo no tiene un valor predeterminado

Tengo la sensación de que la relación no está definida correctamente y también debería ver más tablas, porque en este momento solo veo la tabla Usuario y la tabla Usuario_Usuario.


Actualizar

Lo siguiente crea 3 tablas, amigos, seguidores y solicitantes.¿Está esto algo optimizado en comparación con 5 tablas?¿Y esto tiene alguna ventaja en comparación con lo que sugirió el señor J4mes?

@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;
¿Fue útil?

Solución

En primer lugar, para implementar su función, debe utilizar @ManyToMany en lugar de @OneToMany.Debería verse así:

@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;
}

Tus relaciones me parecen bidireccionales.Si usa @OneToMany, significa que C has 2 followers A and B= A and B only follows C.Sin embargo, el hecho es que una persona puede seguir a muchas personas y una persona puede ser seguida por muchas personas.En otras palabras, A and B can also follow D.

Además, no debería utilizar cascadeType.ALL en absoluto.Esa política en cascada significa que si un usuario elimina su cuenta y usted elimina la entrada correspondiente en la base de datos, también se eliminarán todos sus amigos, etc.

Otros consejos

Hibernate solo generará una tabla para la entidad Usuario, y estoy asumiendo una tabla de referencia cruzada para la relación Usuario a Usuario.La solución alternativa para tener diferentes tablas podría ser tener diferentes entidades configuradas para las diferentes relaciones, es decir,

Entidad de usuario

@OneToMany
List<Follower> followers;

Entidad seguidora

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

@Id
@Generated
int id;

En cuanto a la búsqueda EAGER, es posible que desee que todos sean LAZY, debido al hecho de que, dependiendo de cómo esté configurada su base de datos, todas esas cargas ansiosas podrían ser bastante caras.Solo cuando el usuario quiera cargar los seguidores de los usuarios, querría recuperarlos.

Separar el User de Friends Intente hacer una tabla con al menos 2 columnas que mapee los User_ID a todos sus Friends_IDs que es básicamente una referencia a User_ID

También EAGER se cargará TODO los datos tan pronto como los llame por primera vez.Significa que cargará a todos los usuarios y sus amigos.La carga de amigos debería ser LAZY, es decir.Sólo se cargan cuando los necesitas.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top