2015-03-14 2 views
0

Я пытаюсь спроектировать запрос с использованием API критериев гибернации. Цель состоит в том, чтобы получить отфильтрованный список элементов, хранящихся на 3-м уровне, в виде java.util.Set, которые соответствуют определенному значению. Далее список должен быть отфильтрован на внешнем самом уровне для другого конкретного значения. Ниже приведены модельные классы, которые формируют отношения с многоуровневой:Как создать критерии спящего режима для нескольких уровней

Seller.java

@Entity 
@Table(name="seller") 
public class Seller { 
    private Integer id; 
    private Set<Store> stores; 

    @Id 
    @GeneratedValue(strategy=GenerationType.IDENTITY) 
    @Column(name="id", unique=true, nullable=false) 
    public Integer getId(){ 
     return id; 
    } 
    public void setId(Integer id){ 
     this.id = id; 
    } 

    @ManyToMany(fetch=FetchType.EAGER, cascade=CascadeType.ALL) 
    @JoinTable(name="seller_store", 
     joinColumns={@JoinColumn(name="sellertid")}, 
     inverseJoinColumns={@JoinColumn(name="storeid", referencedColumnName="id")}) 
    @ForeignKey(name="fk_sellerid_seller_store", inverseName="fk_storeid_seller_store") 
    public Set<Store> getStores() { 
     return stores; 
    } 
    public void setStores(Set<Store> stores) { 
     this.stores = stores; 
    } 
} 

Store.java

@Entity 
@Table(name="store") 
public class Store { 
    private Integer id; 
    private Stock stock; 

    @Id 
    @GeneratedValue(strategy=GenerationType.IDENTITY) 
    @Column(name="id", unique=true, nullable=false) 
    public Integer getId(){ 
     return id; 
    } 
    public void setId(Integer id){ 
     this.id = id; 
    } 

    @OneToOne(cascade=CascadeType.ALL, fetch=FetchType.EAGER, orphanRemoval=true) 
    @JoinColumn(name="stockid", referencedColumnName="id") 
    @ForeignKey(name="fk_stockid_store") 
    public Stock getStock() { 
     return stock; 
    } 
    public void setStock(Stock stock) { 
     this.stock = stock; 
    } 
} 

Stock.java

@Entity 
@Table(name="stock") 
public class Stock { 
    private Integer id; 
    private Set<Item> stockItems; 

    @Id 
    @GeneratedValue(strategy=GenerationType.IDENTITY) 
    @Column(name="id", unique=true, nullable=false) 
    public Integer getId(){ 
     return id; 
    } 
    public void setId(Integer id){ 
     this.id = id; 
    } 

    @ManyToMany(fetch=FetchType.EAGER, cascade=CascadeType.ALL) 
    @JoinTable(name="stock_stockitem", 
      joinColumns={@JoinColumn(name="stockid")}, 
      inverseJoinColumns={@JoinColumn(name="stockitemid")}) 
    @ForeignKey(name="fk_stockid_stock", inverseName="fk_stockitemid_stock") 
    public Set<Item> getStockItems() { 
     return stockItems; 
    } 
    public void setStockItems(Set<Item> stockItems) { 
     this.stockItems = stockItems; 
    } 

}

Элемент .java

@Entity 
@Table(name="item") 
public class Item { 
    private Integer id; 
    private String name; 

    @Id 
    @GeneratedValue(strategy=GenerationType.IDENTITY) 
    @Column(name="id", unique=true, nullable=false) 
    public Integer getId(){ 
     return id; 
    } 
    public void setId(Integer id){ 
     this.id = id; 
    } 

    @Column(name="name", unique=true) 
    public String getName(){ 
     return name; 
    } 
    public void setName(String name){ 
     this.name = name; 
    } 
} 

Теперь мне нужно получить определенный Stock объект, содержащий Пункт S с определенным идентификатором и, что тоже для Продавец с определенным идентификатором. Я мог бы легко сделать это, получив верхний уровень Продавец объект по id, но это повлечет за собой нагрузку на мой код, чтобы вручную отфильтровать список генераторов Stock с несколькими для циклов, что определенно не очень хорошая идея. Любые предложения и рекомендации для картографирования и/или критериев будут наиболее оценены. Спасибо заранее!

+0

Может ли кто-нибудь помочь в этом, пожалуйста? – Sachin

ответ

1

Первого шаг должен быть изменить объект хранилища для SUPORT toMany продавцов, то я бы начать писать jpql запрос,

SELECT * FROM stock s 
JOIN stock.items si 
JOIN stock.store.sellers sss 
WHERE si.id IN(:itemIds) 
AND sss.id IN(:sellerIds) 

второго шаг будет переписать этот запрос на основе критериев запроса

CriteriaQuery<Stock> cq = cb.createQuery(Stock.class); 
Metamodel m = em.getMetamodel(); 
EntityType<Stock> Stock_ = m.entity(Stock.class); 
Root<Stock> stock = cq.from(Stock.class); 
Join<Stock, Item> items = stock.join(Stock_.items); 
Join<Stock, Store> store = stock.join(Stock_.store); 
Join<Store, Seller> sellers = store.join(Store_.sellers); 
cq.where(cb.in(items.get(Item_.id), Arrays.asList(1, 2, 3, 4)) 
    .and(cb.in(sellers.get(Seller_.id), Arrays.asList(1, 2, 3, 4)); 

Я не тестировал этот запрос, поэтому не уверен, что он сработает. Однако это идея.

UPDATE

Для Hibernate Criteria Query применяет аналогичную концепцию Присоединяется, но в данном случае создает критерий суб:

List stocks = sess.createCriteria(Stock.class) 
    .createCriteria("items") 
    .add(Restrictions.in("id", {1, 2, 3, 4, 5})) 
    .createCriteria("store") 
    .createCriteria("sellers") 
     .add(Restrictions.like("id", {1, 2, 3, 4, 5})) 
    .list(); 

или используя псевдоним:

List stocks = sess.createCriteria(Cat.class) 
    .createAlias("items", "si") 
    .createAlias("store.sellers", "sss") 
    .add(Restrictions.in("si.id", {1, 2, 3, 4, 5})) 
    .add(Restrictions.in("sss.id", {1, 2, 3, 4, 5})) 
    .list(); 

Опять Я не уверен, что любой из этих запросов будет работать.

А также в качестве окончательного совета следует избегать использования специальных инструментов для поставщиков. Требования к критериям JPA являются стандартными. Это означает, что другие продавцы также используют его. Например, вы можете переключаться между Hibernate и EclipseLink без особых проблем, если вы используете критерии JPA вместо Hibernate Criteria, так как оба поставщика должны следовать стандарту (не 100%, но высоко).

+0

Спасибо за ваш ответ и ответ @bigluis; Я понимаю, что благодаря объединениям я смогу получить накопленный набор акций; Но я не понимаю идею Store потенциально иметь много (OneToMany или ManyToMany?) Отношение к Продавцу. Как вы можете видеть, я настроил Продавца иметь ManyToMany с отдельной таблицей на основании того факта, что Продавец _may_ имеет более 1 «Магазин». Более того, запрос критериев «формулировки», который я написал в названии моего вопроса, вероятно, создал путаницу. Я хочу сделать это с API-интерфейсом Hibernate, а не с API JPA Crtieria. – Sachin

+0

посмотрите на это: http://en.wikibooks.org/wiki/Java_Persistence/ManyToMany. Там вы можете видеть, что оба объекта привязаны к ManyToMany. Я хочу сказать, что вы также должны аннотировать Store.sellers с @ManyToMany. –

+0

вы должны отметить Store.sellers с @ManyToMany (mappedBy = "продавцы"). Это говорит о спящем режиме, что Store.sellers собирается получить из таблицы продавца. Вы не должны аннотировать Store.sellers с @JoinTable, так как вы уже аннотировали Sales.stores. –

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