2015-11-05 2 views
1

У меня есть модель с тремя слоями в моем J2EE с использованием приложения EJB: Cart, у которой много LineItems, каждый из которых имеет много книг (Книга не обязательно относится к позиции, она не является двунаправленной).Глубокая загрузка в объектах J2EE

Cart(1) <--> (M) LineItem (1) --> (M) Book 

Я хочу, чтобы его все хотят грузятся, то есть, когда я достаю телегу он также должен загрузить все свои строки Items, и все эти книги с минимальным количеством запросов SQL (я использую реляционную БД, например MySQL). Это можно сделать с 3-мя запросами, по одному для каждого типа объектов. Установка «FetchType.EAGER» вызывает загрузку всех объектов, однако у нее есть вызовы «2 + n»: 1 запрос для тележки (очевидно), другой запрос для строк, но затем нужно было выполнять n запросов для книг, где n - количество позиций.

Раньше я работал с Ruby on Rails, где использование активной загрузки (с использованием включает) будет делать то, что мне нужно. Могу ли я это сделать и с J2EE?

(примечание: объединение может быть опцией, но я хочу, чтобы объекты были заполнены автоматически из запроса, хотя я думаю, что соединение менее удобно).

Пример моего кода:

@Entity 
public class Cart implements Serializable { 
    @OneToMany(cascade=ALL, mappedBy="cart", fetch = FetchType.EAGER) 
    private List<LineItem> lineItems; 
} 

@Entity 
public class LineItem implements Serializable { 
    @ManyToOne(fetch = FetchType.LAZY) 
    @JoinColumn(name="cart_id", referencedColumnName = "id") 
    private Cart cart; 

    @ManyToOne(fetch = FetchType.EAGER) 
    @JoinColumn(name="book_id", referencedColumnName = "id") 
    private Book book; 
} 

@Entity 
public class Book implements Serializable { 
    ... 
} 

Вот пример из запросов SQL, где телега 3 Позиции:

SELECT id, name FROM carts WHERE (id = 19) 
SELECT id, quantity, book_id, cart_id FROM line_items WHERE (cart_id = 19) 
SELECT id, description, name, price FROM books WHERE (id = 4) 
SELECT id, description, name, price FROM books WHERE (id = 3) 
SELECT id, description, name, price FROM books WHERE (id = 1) 
+0

Нам нужно знать, какую версию EE (или на самом деле JPA) вы нацеливаете, и если вы хотите получить чистое решение EE/JPA - или это нормально с использованием функций, предназначенных для конкретной реализации JPA (если это так, какой) , – esej

ответ

1

Standard JPA обеспечивает join fetch, который знаменует собой отношение быть с нетерпением ожидая, как если бы он был отмечен нетерпеливым путем аннотации. В вашем случае необходимо только join fetchlineItems, так как book будет загружен с каждым LineItem в одном запросе.

С JPA 2.1 вы можете использовать Entity graph - вам не нужно изменять ваш запрос, вы просто присоедините дескриптор к своему запросу, который определяет, какие отношения следует с нетерпением ожидать.

Если вы хотите оптимизировать минимальное количество запросов, вы можете использовать batch fetching, который доступен в некоторых провайдерах JPa. Но будьте осторожны, нет стандартизованного способа включить это - я просто связался с тем, как это сделать с EclipseLink.

+0

В спящем режиме такое же может быть достигнуто с помощью '@Fetch (JOIN)' - это всегда будет загружать отношения, используя join, чтобы он всегда был нетерпелив. Но в целом «join fetch» ​​- это способ, который указал @OndrejM. – yntelectual

+0

Используя первый метод «join fetch», он приводит к нескольким строкам на объект верхнего уровня (т. Е. Когда соединение обнаружило несколько результатов для Cart, оно дублирует строки и не переводится в одну корзину с несколькими строками). – user2339344

+0

Я не понимаю, на каком уровне вы получаете дублированные строки? Если вы хотите получить один запрос для получения сущности и всех сущностей в своей коллекции, записи в результате SQL должны иметь повторяющиеся значения, если существует несколько связанных объектов. Результатом SQL является таблица, а не дерево, столбцы, которые атрибут корневой сущности всегда имеют одни и те же данные. – OndrejM

Смежные вопросы