2009-02-02 14 views
5

Ho due tabelle correlate tra loro utilizzando la relazione uno-a-molti: dipendente -> reparto: e relazione attraverso reparto_id nella tabella dei dipendenti.Sospende la modalità di recupero in runtime

io uso Hibernate: e il mio file di mapping Hibernate sono:

<?xml version="1.0" encoding="utf-8"?> 
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 
            "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 
<!-- 
    Mapping file autogenerated by MyEclipse Persistence Tools 
--> 
<hibernate-mapping default-lazy="false"> 
<class catalog="moi" 
    name="com.ebla.moi.correspondence.model.entity.user.User" table="user"> 
    <id name="id" type="java.lang.Long"> 
    <column name="id"/> 
    <generator class="identity"/> 
    </id> 
    <many-to-one 
    class="com.ebla.moi.correspondence.model.entity.department.Department" 
    fetch="select" name="department"> 
    <column name="department_id"/> 
    </many-to-one> 
    <property generated="never" lazy="false" name="name" type="java.lang.String"> 
    <column length="128" name="name" not-null="true"/> 
    </property> 
    <property generated="never" lazy="false" name="email" type="java.lang.String"> 
    <column length="128" name="email" not-null="true" unique="true"/> 
    </property> 
    <property generated="never" lazy="false" name="maritalStatus" type="java.lang.Short"> 
    <column name="marital_status" not-null="true"/> 
    </property> 
    <property generated="never" lazy="false" name="hireDate" type="java.lang.String"> 
    <column length="64" name="hire_date"/> 
    </property> 
</class> 
</hibernate-mapping> 

e il secondo file di mapping è:

<?xml version="1.0" encoding="utf-8"?> 
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 
            "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 
<!-- 
    Mapping file autogenerated by MyEclipse Persistence Tools 
--> 
<hibernate-mapping default-lazy="false"> 
<class catalog="moi" 
    name="com.ebla.moi.correspondence.model.entity.department.Department" table="department"> 
    <id name="id" type="java.lang.Long"> 
    <column name="id"/> 
    <generator class="identity"/> 
    </id> 
    <property generated="never" lazy="false" name="name" type="java.lang.String"> 
    <column length="256" name="name" unique="true"/> 
    </property> 
    <set inverse="true" name="users" sort="unsorted"> 
    <key> 
    <column name="department_id"/> 
    </key> 
    <one-to-many class="com.ebla.moi.correspondence.model.entity.user.User"/> 
    </set> 
</class> 
</hibernate-mapping> 

Il mio problema è: a volte ho bisogno di ottenere il dipendente con il suo reparto e altre volte ho bisogno solo delle informazioni del dipendente con le informazioni del dipartimento fuori ..... e la stessa cosa con il reparto con il dipendente .... utilizzando il file di mappatura sopra l'ibernato porta il dipartimento e gli utenti se ho bisogno del dipendente o non ... come definire i miei bisogni di ibernare a f Etch proprio quello che mi serve ...

grazie

risposta

10

Si potrebbe mappare il rapporto come "pigro" e scrivere due query per ottenere i vostri dati:

  • La solita semplice query per ottenere la vostra dati ("pigro"). Per esempio. msgstr "seleziona e dal Dipendente e dove ..."

  • La stessa query che utilizza "fetch join" per forzare Hibernate a recuperare "childs". Per esempio. "Selezionare e da Employee LEFT JOIN prendere e.department dove ..."

LLP, Andrea

8

È possibile utilizzare ICriteria per andare a prendere il vostro dipendente.

È possibile utilizzare il metodo setFetchMode del ICriteria per determinare se il Dipartimento dovrebbe essere presa, o no:

Questo farà in modo che il Dipartimento non è inverosimile:

ICriteria crit = theSession.CreateCriteria (typeof(Employee)); 
crit.SetFetchMode ("Department", FetchMode.Lazy) 

Con questo codice , il dipartimento verrà recuperato.

ICriteria crit = theSession.CreateCriteria (typeof(Employee)); 
crit.SetFetchMode ("Department", FetchMode.Join) 

Alcuni dicono che si tratta di best practice per utilizzare il fetchmode predefinito nelle mappature (che sarebbe pigro, credo), e specificare la fetchmode in ogni scenario specifico. (Cioè, nei tuoi repository).

+0

Non funziona per me. Recupera comunque le entità associate ma non utilizza una clausola join. Invece, chiama un'altra istruzione select. – supertonsky

2

Un modo per farlo è quello di avere due classi che rappresentano un dipendente:

  • Employee che ha informazioni reparto mappato tramite;
  • EmployeeSummary che contiene solo i dati del dipendente.

Entrambe le classi allora binding indipendenti sul tavolo employee, ma solo Employee ha anche il rapporto sul department definito.

Quindi quando hai bisogno di tutte le informazioni che carichi istanze Employee, e quando hai solo bisogno di informazioni dipendente carichi istanze EmployeeSummary.

È possibile rimuovere qualsiasi duplicazione di binding ORM e logica aziendale introducendo una superclasse comune come AbstractEmployee in entrambe le classi di dipendenti.

+1

Non penso che questa sia una buona idea in questa situazione. Cosa succede se le tue lezioni contengono BL complessi? Dovrai duplicarlo? –

+0

Non necessariamente se si introduce la superclasse comune, ma buon punto - Ho aggiornato la risposta per riflettere questo. –

+0

Cosa succede se in una singola sessione sia un Employee che un EmployeeSummary caricato dallo stesso record del database, quindi uno o entrambi sono stati modificati? –