2010-02-24 11 views
25

Utilizzo di annotazioni Come si mappa un campo in un'entità che è una "Mappa" (Hashtable) di String su un dato oggetto? L'oggetto è annotato e le relative istanze sono già memorizzate nel databse di ibernazione.Come si esegue il mapping di una "mappa" in ibernazione utilizzando le annotazioni?

ho trovato la sintassi per definging una mappa con una chiave semplice e valore come ad esempio:

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

e stranamente con un'entità come la chiave e un tipo semplice come il valore in questo 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> 

Ma non vedo come farlo per una semplice chiave per la mappatura degli elementi, e non vedo come farlo usando le annotazioni.

+1

Si è correttamente spiegata qui http://stackoverflow.com/questions/3393649/storing-a-mapstring-string-using-jpa – jalogar

risposta

33

Si potrebbe semplicemente usare l'annotazione JPA@MapKey (si noti che l'annotazione APP è diverso da Hibernate uno, il Hibernate @MapKey mappe una colonna del database tenendo premuto il tasto mappa, mentre l'annotazione dell'APP mappa la proprietà essere usato come chiave della mappa).

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

Grazie, ci proverò. Che tipo di schema databse riflette questo? Sto usando l'unità DB e voglio essere in grado di popolare il set di dati usando XML. Questo usa un tavolo join? in tal caso, puoi specificare come viene chiamata la tabella e quali sono le colonne della tabella di join? –

+2

@Omar Crea una tabella di join (FOO_PERSON per impostazione predefinita). Puoi controllare il nome usando '@ javax.persistence.JoinTable'. Non sono sicuro delle colonne. –

1

Probabilmente dovresti usare un UserType o UserCollectionType. Oppure puoi usare un tupleizer personalizzato.

vedere hibernate core documentation per i concetti e hibernate annotations documentation per l'approccio di annotazione equivalente.

Fammi sapere se questo non è quello che stai chiedendo.

+0

Odio sembrare un idiota ma ho guardato quelle stesse due pagine avanti e indietro tutto il giorno e io non sembra averlo capito Ho osservato questo stile: Quale sembra essere il tipo di cosa di cui ho bisogno, proprio non capisco come farlo come annotazione. Inoltre, non so come farei se l'elemento non fosse una stringa. Ho la parte sbagliata del bastone. –

+0

Sì, penso che tu voglia veramente un UserType, perché tutte le altre cose discusse qui (credo) creano un'altra tabella per memorizzare la mappa. Guarda l'interfaccia UserType e vedrai che ci sono solo alcuni metodi implementare. Fondamentalmente dici hibernate, dato un ResultSet, come inserirlo nel tipo java e 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

Questo è il tipo di cosa che sto cercando, tuttavia, come lo farei se la chiave fosse una stringa come nell'esempio e il valore fosse un altro oggetto? –

+0

Sembra simile all'annotazione per mappare un Enum. –

+0

@ Omar: dovrebbe essere semplice come sostituire "String" con il tipo di entità di propria scelta. Potrebbe essere necessario rimuovere @Column (name = "age") e aggiungere qualcosa come inverseJoinColumns = @ JoinColumn (name = "fk_ik") all'annotazione @ JoinTable. Non sono sicuro però. – whiskeysierra

2

So che questa domanda è molto vecchia ma forse questo potrebbe aiutare qualcuno.

Altra possibilita 'è qualcosa di simile:

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

che produce solo due tabelle utente e preferenze, si noti che PreferenceKey è unico per un utente in un dominio

Problemi correlati