2010-04-15 5 views
5

Sto provando a configurare un semplice pattern EAV nella mia app Web utilizzando Java/Spring MVC e Hibernate. Non riesco a capire la magia dietro la configurazione XML di ibernazione per questo scenario.Implementazione di pattern EAV con Hibernate per utente -> Relazione impostazioni

mio database tabella "SETUP" ha tre colonne:

  • id_utente (FK)
  • setup_item
  • setup_value

La chiave composta banca dati è costituito da user_id | setup_item

Ecco la classe Setup.java:

public class Setup implements CommonFormElements, Serializable { 
    private Map data = new HashMap(); 
    private String saveAction; 
    private Integer speciesNamingList; 
    private User user; 

    Logger log = LoggerFactory.getLogger(Setup.class); 

    public String getSaveAction() { 
    return saveAction; 
    } 

    public void setSaveAction(String action) { 
    this.saveAction = action; 
    } 

    public User getUser() { 
    return user; 
    } 

    public void setUser(User user) { 
    this.user = user; 
    } 

    public Integer getSpeciesNamingList() { 
    return speciesNamingList; 
    } 

    public void setSpeciesNamingList(Integer speciesNamingList) { 
    this.speciesNamingList = speciesNamingList; 
    } 

    public Map getData() { 
    return data; 
    } 

    public void setData(Map data) { 
    this.data = data; 
    } 
}

Il mio problema con l'installazione Hibernate, è che io non riesco a capire come tracciare il fatto che una chiave esterna e la chiave di una mappa costruirà la chiave composita della tabella ... ciò è dovuto alla mancanza di esperienza nell'utilizzo di Hibernate. Ecco il mio primo tentativo di ottenere questo al lavoro:

<composite-id> 
    <key-many-to-one foreign-key="id" name="user" column="user_id" class="Business.User"> 
    <meta attribute="use-in-equals">true</meta> 
    </key-many-to-one> 
</composite-id> 

<map lazy="false" name="data" table="setup"> 
    <key column="user_id" property-ref="user"/> 
    <composite-map-key class="Command.Setup"> 
    <key-property name="data" column="setup_item" type="string"/> 
    </composite-map-key> 

    <element column="setup_value" not-null="true" type="string"/> 
</map> 

Tutta la comprensione di come mappare correttamente questo scenario comune sarebbe apprezzato!

+0

@Trevor Benvenuto, ma se vedi una risposta utile, in suvota, grazie! –

risposta

2

Come mostrato da soli, si dispone di una mappatura incoerente

Hai detto di classe di installazione definisce una chiave primaria composta (da notare che ho creato una classe chiave primaria composta (SetupId - vedi sotto), che deve implementa Serializable e uguale e il metodo codice hash)

package ar.domain; 

import java.io.Serializable; 
import java.util.HashMap; 
import java.util.Map; 

public class Setup implements Serializable { 

    private SetupId setupId; 

    private User user; 
    private Map data= new HashMap(); 

    public SetupId getSetupId() { 
     return setupId; 
    } 

    public void setSetupId(SetupId setupId) { 
     this.setupId = setupId; 
    } 

    public User getUser() { 
     return user; 
    } 

    public void setUser(User user) { 
     this.user = user; 
    } 

    public Map getData() { 
     return data; 
    } 

    public void setData(Map data) { 
     this.data = data; 
    } 


    public static class SetupId implements Serializable { 

     private Integer userId; 
     private String setupItem; 

     public String getSetupItem() { 
      return setupItem; 
     } 

     public void setSetupItem(String setupItem) { 
      this.setupItem = setupItem; 
     } 

     public Integer getUserId() { 
      return userId; 
     } 

     public void setUserId(Integer userId) { 
      this.userId = userId; 
     } 

     @Override 
     public boolean equals(Object o) { 
      if (o == null) 
       return false; 

      if (!(o instanceof SetupId)) 
       return false; 

      final SetupId other = (SetupId) o; 
      if (!(getUserId().equals(other.getUserId()))) 
       return false; 
      if (!(getSetupItem().equals(other.getSetupItem()))) 
       return false; 

      return true; 
     } 

     @Override 
     public int hashCode() { 
      int hash = 7; 
      hash = 11 * hash + (getUserId() != null ? getUserId().hashCode() : 0); 
      hash = 11 * hash + (getSetupItem() != null ? getSetupItem().hashCode() : 0); 
      return hash; 
     } 

    } 

} 

a causa della vostra classe di installazione ha una mappa di tipo valore, è dovrebbe definire il suo composito estera chiave al momento di definire il suo rapporto (vedi elemento chiave)

<class name="ar.domain.Setup"> 
    <composite-id name="setupId" class="ar.domain.Setup$SetupId"> 
     <key-property name="setupItem" type="string" column="SETUP_ITEM"/> 
     <key-property name="userId" type="integer" column="USER_ID"/> 
    </composite-id> 
    <many-to-one name="user" class="ar.domain.User" column="USER_ID" insert="false" update="false"/> 
    <map name="data" table="DATA_TABLE"> 
     <key> 
      <column name="SETUP_ITEM"/> 
      <column name="USER_ID"/> 
     </key> 
     <map-key column="USER_ID"/> 
     <element column="SETUP_VALUE" not-null="true" type="string"/> 
    </map> 
</class> 

E, allo stesso tempo, utilizzare una colonna di chiave esterna composita come map-key (USER_ID, right?) Che non ha senso. Perché ?

  • Hibernate non consente si aggiorna un (composito) colonna di chiave primaria

Oltre a ciò, Hibernate non supporta la generazione automatica di composito primario chiave

Supponiamo qui va la tua SETUP Table

SETUP_ITEM USER_ID 
0   1 
0   2 

E il tuo DATA_TABLE

SETUP_ITEM USER_ID 
0   1 

Cosa succede se si tenta la seguente

Integer userId = 3; 
String setupValue = "someValue"; 

setup.getData().put(userId, setupValue); 

A causa della tabella di installazione non definisce un USER_ID cui valore è 3, si vedrà una violazione vincolo.

Tenerlo a mente

Quando si dispone di una chiave (composito) primario, che non può essere aggiornabile, evitare di usarlo, in qualche modo, per modificare una proprietà mutabile, che dipende da esso. Altrimenti, Hibernate si lamenterà.