2015-03-12 12 views
17

W naszym projekcie mamy podmiot "Restauracja" z prawie 30 polami (niektóre mają relacje z innymi podmiotami). Tak więc za każdym razem, gdy potrzebujemy obiektu "Restauracja", nawet dla kilku pól, wszystkie pozostałe są pobierane. To wpływa na wydajność. Tak więc w pliku HBM napisaliśmy dwie klasy wskazujące na tę samą klasę fizyczną i tę samą tabelę bazy danych, co pokazano poniżej.Jak odwzorować dwie jednostki JPA lub hibernacji na tej samej tabeli bazy danych

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

W jednym z wdrożeń DAO, używamy kryteria, które bierze „” i powracający RestaurantLite listę restauracji, jak pokazano poniżej.

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

    // criteria related stuff 

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

Teraz chcemy usunąć wszystkie pliki hbm i używać adnotacji. Więc jak można to zrobić za pomocą adnotacji na cele? Czy musimy stworzyć dodatkową klasę "RestaurantLite"? Jeśli tak, to w jaki sposób powyższe kryteria zwracają obiekty "restauracyjne"?

+1

Wpływa to na wydajność. Do jakiego stopnia? Zmierzyłeś? Jak zauważa Hibernate docs: optymalizacja odczytów wierszy jest o wiele ważniejsza niż optymalizacja odczytów kolumn. Jednak ładowanie niektórych właściwości klasy może być przydatne w ** skrajnych ** przypadkach. Na przykład, gdy starsze tabele mają ** setki ** kolumn, a model danych nie może zostać ulepszony. https://docs.jboss.org/hibernate/orm/3.3/reference/en/html/performance.html#performance-fetching-lazy –

+0

@Alan Hay Mamy bazę danych z tysiącami rekordów dla każdej tabeli. Wymieniona klasa jest potrzebna do większości operacji. Dlatego pobieranie wszystkich właściwości dla każdej restauracji zdecydowanie za każdym razem wpływa na wydajność. Tak, znaleźliśmy to rozwiązanie w plikach hbm. – Raj44

+0

Wszystkie bazy danych mają tysiące,/dziesiątki tysięcy/miliony wierszy. Jak wskazują dokumenty Hibernatora, optymalizacje kolumn rzadko są opłacalne. http://en.wikipedia.org/wiki/Program_optimization#When_to_optimize –

Odpowiedz

32

ten temat, a także w jaki sposób można go używać dla leniwych atrybutów pobierania, to opisane bardzo szczegółowo in this article.

Aby podsumować następujące odwzorowania zamiar pokazać, jak można mapować wiele elementów do tej samej tabeli bazy danych:

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

i hibernacji będzie działać dobrze:

@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. Urządzenie PostSummary jest tylko widokiem tylko do odczytu nad oryginalną jednostką, dlatego dodałem do niego annotę pod numerem @Immutable.

  2. Numer UpdatablePostSummary jest oznaczony @DynamicUpdate, dzięki czemu można również propagować zmiany z tego obiektu widoku.

Ten test jest również dostępny pod numerem GitHub.

+0

Co stanie się, jeśli zaktualizujesz 'UpdatablePostSummary'?Czy jednostka "Post" zostanie zaktualizowana do? (Wewnątrz Hibernate mam na myśli, oczywiście w bazie danych jest to ta sama tabela). –

+3

W trybie hibernacji jednostka 'Post' będzie musiała zostać odświeżona ręcznie, ponieważ inaczej Hibernate nie zrobi tego automatycznie. –

Powiązane problemy