2010-02-24 16 views
25

Usando anotaciones, ¿cómo mapea un campo en una entidad que es un "Mapa" (Hashtable) de Cadena para un objeto dado? El objeto está anotado y las instancias de él ya están almacenadas en el databse de hibernación.¿Cómo se mapea un "Mapa" en hibernación usando anotaciones?

he encontrado la sintaxis para definging un mapa con una simple clave y valor como tales:

<class name="Foo" table="foo"> 
    ... 
    <map role="ages"> 
     <key column="id"/> 
     <index column="name" type="string"/> 
     <element column="age" type="string"/> 
    </map> 
</class> 

Y curiosamente con una entidad como la clave y un tipo simple como el valor de este modo:

<class name="Foo" table="foo"> 
    ... 
    <map role="ages"> 
    <key column="id"/> 
    <index-many-to-many column="person_id" 
     class="Person"/> 
    <element column="age" type="string"/> 
    </map> 
</class> 
<class name="Person" table="person"> 
    ... 
    <property name="name" column="name" 
     type="string"/> 
</class> 

Pero no veo cómo hacer esto para obtener una clave simple para el mapeo de elementos, y no veo cómo hacerlo usando anotaciones.

+1

Se explica correctamente aquí http://stackoverflow.com/questions/3393649/storing-a-mapstring-string-using-jpa – jalogar

Respuesta

33

Usted puede simplemente utilizar la anotación APP@MapKey (tenga en cuenta que la anotación JPA es diferente de la hibernación uno, el Hibernate @MapKey asigna una columna de base de la celebración de la clave del mapa, mientras que la anotación de la APP asigna la propiedad de ser utilizado como la clave del mapa).

@javax.persistence.OneToMany(cascade = CascadeType.ALL) 
@javax.persistence.MapKey(name = "name") 
private Map<String, Person> nameToPerson = new HashMap<String, Person>(); 
+0

Gracias, intentaré esto. ¿Qué tipo de esquema de databse refleja esto? Estoy usando la unidad DB y quiero poder completar el conjunto de datos usando XML. ¿Esto usa una tabla de unión? de ser así, ¿puede especificar a qué se llama la tabla y cuáles son las columnas de la tabla de unión? –

+2

@Omar Crea una tabla de unión (FOO_PERSON por defecto). Puedes controlar el nombre usando '@ javax.persistence.JoinTable'. No estoy seguro de las columnas –

1

Probablemente debería usar un UserType o UserCollectionType. O bien, puede usar un tupleizador personalizado.

ver hibernate core documentation para los conceptos y hibernate annotations documentation para el enfoque de anotación equivalente.

Avísame si no es eso lo que estás pidiendo.

+0

Odio sonar como un idiota pero he estado viendo esas mismas dos páginas de forma intermitente durante todo el día y parece que no lo entiendo He estado buscando en este estilo: Lo que parece ser el tipo de cosa que necesito, simplemente no entiendo cómo hacerlo como anotación. Tampoco sé cómo lo haría si el elemento no fuera una cadena. Tengo el extremo equivocado de la palanca. –

+0

Sí, creo que realmente quieres un UserType, porque todas las otras cosas que se analizan aquí (creo) crean otra tabla para almacenar el mapa. Mira la interfaz UserType y verás que solo hay unos pocos métodos para implementar. Básicamente le dices hibernate, dado un ResultSet, cómo ponerlo en el tipo java y viceversa. –

8
@CollectionOfElements(fetch = FetchType.LAZY) 
@JoinTable(name = "JOINTABLE_NAME", 
    joinColumns = @JoinColumn(name = "id")) 
@MapKey(columns = @Column(name = "name")) 
@Column(name = "age") 
private Map<String, String> ages = new HashMap<String, String>(); 
+0

Ese es el tipo de cosa que estoy buscando, sin embargo, ¿cómo lo haría si la clave fuera una cadena como en el ejemplo y el valor fuera otro objeto? –

+0

que se parece a la anotación para mapear un Enum. –

+0

@Omar: Debería ser tan simple como reemplazar "Cadena" con el tipo de entidad de su elección. Es posible que deba eliminar @Column (name = "age") y agregar algo como inverseJoinColumns = @ JoinColumn (name = "fk_ik") a la anotación @ JoinTable. Aunque no estoy seguro – whiskeysierra

2

Sé que esta pregunta es muy antigua, pero tal vez esto podría ayudar a alguien.

Otra posibilidad es algo así:

@Entity 
@Table(name = "PREFERENCE", uniqueConstraints = { @UniqueConstraint(columnNames = { "ID_DOMAIN", "ID_USER", "KEY" })}) 
public class Preferences { 
    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    @Column(name = "ID", unique = true, nullable = false) 
    private Long id; 

    @Column(name = "ID_DOMAIN", unique = false, nullable = false") 
    private Long domainId; 

    @Column (name = "PREFERENCE_KEY") 
    @Enumerated(EnumType.STRING) 
    private PreferenceKey key; 

    @ManyToOne(fetch = FetchType.LAZY) 
    @JoinColumn(name = "ID_USER", referencedColumnName = "ID") 
    private User user; 
} 

and 

@Entity 
@Table(name = "USER", uniqueConstraints = { @UniqueConstraint(columnNames = { "ID_DOMAIN", "LOGIN" })}) 
public class User { 
    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    @Column(name = "ID", unique = true, nullable = false) 
    private Long id; 

    @Column(name = "ID_DOMAIN", unique = false, nullable = false") 
    private Long domainId; 

    // more fields 

    @ElementCollection(fetch = FetchType.LAZY) 
    @JoinColumns({@JoinColumn(name = "ID_USER", referencedColumnName = "ID"), @JoinColumn(name = "ID_DOMAIN", referencedColumnName = "ID_DOMAIN")}) 
    @OneToMany(targetEntity = Preferences.class, fetch = FetchType.LAZY) 
    @MapKey(name = "key") 
    private Map<PreferenceKey, Preferences> preferencesMap; 
} 

Eso sólo produce dos mesas preferencias del usuario y, tenga en cuenta que PreferenceKey es único para un usuario en un dominio

Cuestiones relacionadas