我正在尝试使用 hibernate criteria API 设计一个查询。目标是获取以 java.util.Set 形式存储在第三级的经过过滤的项目列表,这些项目与特定值匹配。此外,应该在最外层过滤列表以获取另一个特定值。下面是形成多级关系的模型类:
卖家.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;
}
}
商店.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 对象,其中包含具有特定 id 的 Item 以及具有特定 id 的 Seller 。我可以通过 id 获取顶级 Seller 对象来轻松地做到这一点,但这会给我的代码带来负担,需要使用多个 for 循环手动过滤生成 Stock 列表,这绝对是这不是一个好主意。任何有关映射和/或标准逻辑的建议和指南将不胜感激。 提前致谢!
最佳答案
第一步应该是更改 Store 实体以支持 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));
我还没有测试过这个查询,所以我不确定它是否会起作用。不过,这就是想法。
更新
对于 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 标准查询是标准。这意味着其他供应商也在使用它。例如,如果您使用 JPA 标准而不是 Hibernate Criteria,则可以在 Hibernate 和 EclipseLink 之间切换而不会出现很多问题,因为两个供应商都应该遵循该标准(不是 100%,而是高度)。
关于java - 如何为多个级别创建 Hibernate Criteria,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29048663/