2010-02-24 4 views
25

À l'aide d'annotations, comment mappez-vous un champ dans une entité qui est une «carte» (table de hachage) de chaîne à un objet donné? L'objet est annoté et les instances de celui-ci sont déjà stockées dans la base de données Hibernate.Comment mapper une "Carte" en hibernation en utilisant des annotations?

que j'ai trouvé la syntaxe pour definging une carte avec une simple clé et de la valeur en tant que telle:

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

Et curieusement avec une entité comme la clé et un type simple que la valeur comme ceci:

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

Mais je ne vois pas comment faire cela pour une simple clé de mappage d'éléments, et je ne vois pas comment faire cela en utilisant des annotations.

+1

Il est correctement expliqué ici http://stackoverflow.com/questions/3393649/storing-a-mapstring-string-using-jpa – jalogar

Répondre

33

Vous pouvez simplement utiliser l'annotation JPA@MapKey (notez que l'annotation JPA est différente de la mise en veille prolongée un, la mise en veille prolongée @MapKey Mappe une colonne de base de données contenant la clé de la carte, tandis que l'annotation de l'Assemblée parlementaire paritaire mappe la propriété de être utilisé comme clé de la carte).

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

Merci, je vais essayer ça. Quel type de schéma de base de données reflète-t-il? J'utilise l'unité DB et je veux pouvoir remplir l'ensemble de données en utilisant XML. Est-ce que cela utilise une table de jointure? Si oui pouvez-vous spécifier ce que la table est appelée et quelles sont les colonnes de la table de jointure? –

+2

@Omar Crée une table de jointure (FOO_PERSON par défaut). Vous pouvez contrôler le nom en utilisant '@ javax.persistence.JoinTable'. Pas sûr sur les colonnes. –

1

Vous devriez probablement utiliser un UserType ou un UserCollectionType. Ou, vous pouvez utiliser un tupleizer personnalisé. Voir hibernate core documentation pour les concepts et hibernate annotations documentation pour l'approche d'annotation équivalente. Faites-moi savoir si ce n'est pas ce que vous demandez.

+0

Je déteste avoir l'air d'un idiot, mais j'ai regardé ces mêmes deux pages tout au long de la journée et je ne semble pas l'avoir. J'ai regardé ce style: <élément column = " age "type =" string "/> Ce qui semble être le genre de chose dont j'ai besoin, je ne comprends pas comment le faire comme annotation. Je ne sais pas non plus comment je ferais si l'élément n'était pas une chaîne. Est-ce que j'ai la mauvaise extrémité du manche? –

+0

Oui, je pense que vous voulez vraiment un UserType, car toutes les autres choses discutées ici (je crois) créent une autre table pour stocker la carte. Regardez l'interface UserType et vous verrez qu'il n'y a que quelques méthodes implémenter. Fondamentalement, vous dites à Hibernate, à l'aide d'un ResultSet, comment le mettre dans le type Java et vice-versa. –

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

C'est le genre de chose que je cherche mais comment le ferais-je si la clé était une chaîne comme dans l'exemple et la valeur était un autre objet? –

+0

Cela ressemble à l'annotation pour mapper un Enum. –

+0

@Omar: Doit être aussi simple que de remplacer "String" par le type d'entité de votre choix. Vous devrez peut-être supprimer @Column (name = "age") et ajouter quelque chose comme reverseJoinColumns = @ JoinColumn (name = "fk_ik") à l'annotation @ JoinTable. Pas sûr cependant. – whiskeysierra

2

Je sais que cette question est très ancienne mais peut-être que cela pourrait aider quelqu'un.

Autre acceuillent quelque chose comme ça:

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

qui ne produit que deux tables préférences utilisateur et, notez que PreferenceKey est unique pour un utilisateur dans un domaine

Questions connexes