2011-12-19 33 views
5

Digamos que tenemos clase de entidad de usuario. El usuario puede ser amigo de otros usuarios. ¿Cómo puedo mapear este campo de colección de autorreferencia sin crear una nueva entidad llamada Conexión o crear múltiples entradas en la base de datos?asignación de campo de autorreferencia en JPA

@Entity 
public class User { 
... 
@ManyToMany 
private Collection<User> friends; 
... 
} 

USER_ID-FRIEND_ID 
1 - 2 
2 - 1 (duplicate... I don't need it) 
+0

Una relación muchos a muchos autorreferencial es válida y puede correlacionarse utilizando anotaciones JPA. Como todas las relaciones de muchos a muchos, debe definir una tabla puente para almacenar ambos lados de la relación. La entidad definirá un campo para el lado propietario y otro campo para el lado asignado de la relación. – scottb

Respuesta

1

No puede, necesita ambos registros en la base de datos.

En realidad, para las relaciones de amistad, yo diría que una base de datos de gráficos como neo4j es lo apropiado para usar. Ahí tienes los dos usuarios y simplemente agregas un borde "amigos".

+0

interesante ... pensé que podría haber un engaño o algo así –

+2

Esta respuesta no es correcta. Una relación autorreferencial de muchos a muchos es válida y se puede mapear en JPA sin definir ninguna entidad nueva.La relación requiere una tabla puente, como todas las relaciones de muchos a muchos. – scottb

6

A continuación se presenta la instantánea de mi código para ElementEntity:

@OneToMany(mappedBy = "parent", fetch = FetchType.LAZY) 
private List<ElementEntity> children; 

@JoinColumn(name = "ParentId", referencedColumnName = "ElementId") 
@ManyToOne(fetch = FetchType.LAZY) 
private ElementEntity parent; 

Cuando en la base de datos hay campos:

  • ElementId - clave primaria;
  • ParentId relación con los padres
+0

gracias amigo por su tiempo. No estoy buscando una relación padre-hijo. –

+3

@HayatiGuvence qué pasa - simplemente cambie el nombre de ParentId a USER_ID y elementId a friend_Id – Dewfy

1

Por lo menos se necesita un relational table.

lo que tiene una mesa de USER y una FRIENDS:

user_id friend_id 
    1  2 

Pero @Bozho respuesta es mucho mejor que la mía (neo4j).

+0

:) no puede tener dos mismos nombres de columna en una tabla –

+0

¡gracias! solo un typ0 – ssedano

0

Bueno, de hecho se puede.

Puede usar anotaciones como @PreUpdate, @PrePersists, @PostUpdate y así convertir manualmente los elementos de una colección. De esta forma su entidad puede renderizarlos a su gusto, mientras que en la base de datos solo almacena un texto sin formato.

Una alternativa más pausible será usar la anotación @Convert, disponible desde jpa 2.1 (@UserType in hibernate). Le dice a jpa que convierta el campo en otro tipo cada vez que lea/guarde en la base de datos. Para ello, debe usar la anotación @Convert, especificar y el objeto AttributeConverter.

Por ejemplo

public class Parent { 
     @Id 
     private Integer id; 

     @Convert(converter = FriendConverter.class) 
     private Set<Parent>friends; 
    } 

y Clase convertidor como el siguiente:

@Component 
    public class FriendConverter implements AttributeConverter<List, String>{ 
     @Autowired 
     private SomeRepository someRepository; 

     @Override 
     public String convertToDatabaseColumn(List attribute) { 
     StringBuilder sb = new StringBuilder(); 
     for (Object object : attribute) { 
      Parent parent = (parent) object; 
      sb.append(parent.getId()).append("."); 
     } 
     return sb.toString(); 
     } 

     @Override 
     public List convertToEntityAttribute(String dbData) { 
     String[] split = dbData.split("."); 
     List<Parent>friends = new ArrayList<>(); 
     for (String string : split) { 
      Parent parent = someRepository.findById(Integer.valueOf(string)); 
      friends.add(accion); 
     } 
     return friends; 
     } 
    } 

Es una aplicación ficticia pero te da la idea.

Como comentario personal, recomiendo mapear la relación como debería. En el futuro te evitará problemas. AttributeConverter es útil cuando se trabaja con enums

Cuestiones relacionadas