web-dev-qa-db-fra.com

Comment mapper une "carte" en veille prolongée à l'aide d'annotations?

À l'aide d'annotations, comment mappez-vous un champ dans une entité qui est une "mappe" (table de hachage) de chaîne à un objet donné? L'objet est annoté et ses instances sont déjà stockées dans la base de données de mise en veille prolongée.

J'ai trouvé la syntaxe pour défier une carte avec une clé simple et une 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 bizarrement avec une entité comme clé et un type simple comme 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ément, et je ne vois pas comment faire cela en utilisant des annotations.

30
Omar Kooheji

Vous pouvez simplement utiliser l'annotation JPA @MapKey (notez que l'annotation JPA est différente de celle d'Hibernate, l'Hibernate @MapKey mappe une colonne de base de données contenant la clé de la carte, tandis que l'annotation JPA mappe la propriété à utiliser 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>();
40
Pascal Thivent
@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>();
9
whiskeysierra

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

L'autre posibilité est 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;
}

Cela ne produit que deux tableaux Utilisateur et Préférences, notez que PreferenceKey est unique pour un utilisateur dans un domaine

2
Juan

Vous devez probablement utiliser un UserType ou UserCollectionType. Ou, vous pouvez utiliser un tupleizer personnalisé.

voir documentation de base d'hibernation pour les concepts et documentation d'hibernation des annotations pour l'approche d'annotation équivalente.

Faites-moi savoir si ce n'est pas ce que vous demandez.

1
Jeff Walker