2015-03-12 15 views
17

Nel nostro progetto, abbiamo un'entità "Ristorante" con quasi 30 campi (alcuni hanno relazioni con altre entità). Quindi, ogni volta che abbiamo bisogno di un oggetto "Ristorante" anche per pochi campi, tutti gli altri vengono recuperati. Ciò influisce sulle prestazioni. Quindi, nel file HBM, abbiamo scritto due classi che puntavano alla stessa classe fisica e alla stessa tabella di database, come mostrato di seguito.Come mappare due entità JPA o Hibernate sulla stessa tabella di database

=== restaurant.hbm.xml === 
<!-- Light Weight Version --> 
<class name="com.raj.model.Restaurant" table="RESTAURANTS" entity-name="RestaurantLite" 
       dynamic-update="false" dynamic-insert="false"> 
<cache usage="read-only"/> 
    <!-- few basic properties and relationships --> 
</class> 

<!-- Restaurant --> 
<class name="com.raj.model.Restaurant" table="RESTAURANTS" entity-name="Restaurant"> 
    <!-- all properties and relationships --> 
</class> 

In una delle implementazioni DAO, stiamo usando criteri che prende 'RestaurantLite' e la lista ritorno di ristoranti come illustrato di seguito.

Criteria criteria = session.createCriteria("RestaurantLite"); 

    // criteria related stuff 

return new LinkedHashSet<Restaurant>(criteria.list()); 

Ora vogliamo rimuovere tutti i file hbm e utilizzare le annotazioni. Quindi, come si può fare lo stesso usando le annotazioni per le entrate? Abbiamo bisogno di creare una classe extra "RestaurantLite"? Se poi, come i criteri sopra riportati restituiscono gli oggetti "Restaurant" ??

+1

Questo influisce sulle prestazioni. Fino a che punto? Hai misurato? Come notano i documenti di Hibernate: l'ottimizzazione delle letture delle righe è molto più importante dell'ottimizzazione delle letture delle colonne. Tuttavia, il caricamento di alcune proprietà di una classe può essere utile solo nei casi ** estremi **. Ad esempio, quando le tabelle legacy hanno ** centinaia ** di colonne e il modello di dati non può essere migliorato. https://docs.jboss.org/hibernate/orm/3.3/reference/en/html/performance.html#performance-fetching-lazy –

+0

@Alan Hay Abbiamo un database con migliaia di record per ogni tabella. La classe sopra menzionata è necessaria per la maggior parte delle operazioni. Quindi, recuperare tutte le proprietà per ogni ristorante ogni volta ha un impatto negativo sulle prestazioni. Quindi, abbiamo trovato questa soluzione nei file hbm. – Raj44

+0

Tutti i database hanno migliaia,/decine di migliaia/milioni di righe. Come sottolineano i documenti di Hibernate, le ottimizzazioni delle colonne raramente valgono la pena. http://en.wikipedia.org/wiki/Program_optimization#When_to_optimize –

risposta

32

questo argomento e come lo si può utilizzare per gli attributi fetching pigri, è descritto in grande dettaglio in this article.

In sintesi, le seguenti mappature stanno per dimostrare come è possibile mappare più entità alla stessa tabella del database:

@Entity(name = "Post") 
public class Post { 

    @Id 
    @GeneratedValue(strategy=GenerationType.AUTO) 
    private Long id; 

    private String name; 

    private String description; 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

    public String getDescription() { 
     return description; 
    } 

    public void setDescription(String description) { 
     this.description = description; 
    } 
} 

@Entity(name = "PostSummary") 
@Table(name = "Post") 
@Immutable 
public class PostSummary { 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private Long id; 

    private String name; 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 
} 

@Entity(name = "UpdatablePostSummary") 
@Table(name = "Post") 
@DynamicUpdate 
public class UpdatablePostSummary { 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private Long id; 

    private String name; 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 
} 

E Hibernate funzionano bene:

@Test 
public void testOneTableMultipleEntities() { 
    doInTransaction(session -> { 
     Post post = (Post) session.get(Post.class, 1L); 
     PostSummary postSummary = (PostSummary) session.get(PostSummary.class, 1L); 
     UpdatablePostSummary updatablePostSummary = (UpdatablePostSummary) session.get(UpdatablePostSummary.class, 1L); 
     assertEquals(post.getName(), postSummary.getName()); 
     assertEquals(post.getName(), updatablePostSummary.getName()); 
     updatablePostSummary.setName("Hibernate Master Class Tutorial."); 
    }); 
} 
  1. Il PostSummary è solo una vista di sola lettura sull'entità originale, quindi l'ho annotato con @Immutable.

  2. Il UpdatablePostSummary è contrassegnato con @DynamicUpdate e quindi è possibile propagare le modifiche anche da questa entità di visualizzazione.

Questo test è disponibile sul GitHub anche.

+0

Cosa succede se aggiorni un 'UpdatablePostSummary'?L'entità 'Post' sarà aggiornata? (All'interno di Hibernate intendo, ovviamente nel database questa è la stessa tabella). –

+3

In Hibernate, l'entità 'Post' dovrà essere aggiornata manualmente, altrimenti Hibernate non lo farà automaticamente. –

Problemi correlati