Как добавить продукт в списке, не загружая всю базу данных?

В моей модели предметной области у меня есть bi-directionnel ассоциация между объектом ProductList, и объект продукта со следующим в спящем режиме, отображаясь:

@Entity @Indexed
@Table(name="product_list")
public class ProductList {

@ManyToMany(fetch=FetchType.LAZY)
@JoinTable(name = "list_items",
        inverseJoinColumns = { @JoinColumn(name = "product_id")},
        joinColumns = { @JoinColumn(name = "list_id")})
@IndexColumn(name = "item_index", base = 1, nullable = false )
@LazyCollection(LazyCollectionOption.EXTRA)
@BatchSize(size=50)
private List<Product> products = new LinkedList<Product>();
....

}

@Entity
@Table(name="logical_item")
@Cache(usage=CacheConcurrencyStrategy.READ_WRITE)
public class Product {

@ManyToMany(fetch=FetchType.LAZY, mappedBy="products")
private Set<ProductList> productLists = new LinkedHashSet<ProductList>();

...
}

Но когда я пытался добавить, что продукт к персистентному productList В спящем режиме попытка загрузить весь продукт в списке прежде! У меня есть больше чем 14 000 продуктов в списке!

Product item = (Product) session.get(Product.class, 123);
ProductList myFavoriteItems = (ProductList) session.get(ProductList.class, 321);

// Evil lazy loading (need more 512Mo of memory )
myFavoriteItems.addItem(Product item);

public void addItem(Product item){
    this.getProducts().add(item);
    item.getProductLists().add(this);
}

Как добавить продукт в списке, не загружая всю базу данных?

5
задан Julien Brulin 21 June 2010 в 14:43
поделиться

2 ответа

Я предполагаю, что это один из недостатков использования отношения ManyToMany, когда вам нужно обновить таблицу соединений.

Я бы посоветовал создать объект из таблицы соединения, и тогда вам нужно было бы только создать объект соединения и сохранить его:

public class ProductListItem {
    @ManyToOne(...)
    private Product product;

    @ManyToOne(...)
    private ProductList productList;

    ...
}

И у вас все еще может быть временный получатель, который будет возвращать список продуктов из продукта :

public class Product {

    @OneToMany(...)
    private Set<ProductListItem> items;

    @Transient
    public Set<ProductList> getProductLists() {
        Set<ProductList> list = new LinkedHashSet<ProductList>();
        for(ProductListItem item : items) {
            list.add(item.getProductList());
        }
        return Collections.unmodifiableSet(list);
    }
    ...
}

То же самое и с другой стороной отношения многие-многие.

Тогда ваша операция сохранения сводится к созданию и сохранению ProductListItem, который ничего не загружает и требует только одной вставки.

Будьте осторожны с вашими уже существующими hql-запросами: если они использовали ссылку Product <-> ProductList, они больше не будут работать.

если вы хотите сохранить отношение ManyToMany, вам следует посмотреть на: http://josephmarques.wordpress.com/2010/02/22/many-to-many-revisited/ (i ' я никогда не пробовал это решение)

3
ответ дан 15 December 2019 в 06:15
поделиться
public class Controller {

private static SessionFactory sf = HibernateUtil.getSessionFactory();

/**
* @param args
*/
public static void main(String[] args) {
// construct data
sf.getCurrentSession().beginTransaction();
Item i1 = new Item("i1");
Item i2 = new Item("i2");
Item i3 = new Item("i3");
Category c1 = new Category("c1");
sf.getCurrentSession().save(i1);
sf.getCurrentSession().save(i2);
sf.getCurrentSession().save(i3);
sf.getCurrentSession().save(c1);
c1.getItems().add(i1);
i1.getCategories().add(c1);
c1.getItems().add(i2);
i2.getCategories().add(c1);
sf.getCurrentSession().getTransaction().commit();

// get Category & i (i3)
sf.getCurrentSession().beginTransaction();
Category c = (Category) sf.getCurrentSession().get(Category.class, c1.getId());
Item i = (Item) sf.getCurrentSession().get(Item.class, i3.getId());

// proxys i & c have null Set
System.out.println("i : " + i.getName());
System.out.println("c : " + c.getName());

// here we have the IDs
long category_id = c.getId();
long item_id = i.getId();

sf.getCurrentSession().getTransaction().commit();

// add many to many data
sf.getCurrentSession().beginTransaction();

// here we can use pure SQL to add a line in CATEGORY_ITEM.
// with the known IDs
String ins = "insert into category_items (item_id,category_id,item_index) SELECT 4639, 100, MAX(item_index)+1 from category_items where category_id = 100 ;";

sf.getCurrentSession().getTransaction().commit();

}

}
0
ответ дан 15 December 2019 в 06:15
поделиться
Другие вопросы по тегам:

Похожие вопросы: