我试图以一种自恋的方式懒惰地装载产品的成分。产品可以包含零种或多种成分。该关系存储在ProductComposition
实体中。
这些是我的实体:
产品
@Entity(name = Product.TABLE_NAME)
//@NamedEntityGraph(name = "graph.Product.ingredients", attributeNodes = //@NamedAttributeNode("ingredients"))
public class Product {
public static final String TABLE_NAME = "Product";
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long idProduct;
private String name;
@OneToMany(fetch = FetchType.EAGER, cascade = {CascadeType.MERGE}, mappedBy = "product")
private List<OrderDetail> orders;
@OneToMany(fetch = FetchType.LAZY,cascade = CascadeType.ALL, mappedBy = "ingredient", orphanRemoval=true)
private List<ProductComposition> ingredients;
ProductComposition
@Entity(name = ProductComposition.TABLE_NAME)
@IdClass(ProductCompositionId.class)
public class ProductComposition {
public static final String TABLE_NAME = "ProductComposition";
@Id
@ManyToOne //(fetch = FetchType.LAZY)
@PrimaryKeyJoinColumn(name = "PrincipalProductID")
private Product principalProduct;
@Id
@ManyToOne //(fetch = FetchType.LAZY)
@PrimaryKeyJoinColumn(name = "IngredientID")
private Product ingredient;
private int quantity;
ProductCompositionId
class ProductCompositionId implements Serializable{
private long principalProduct;
private long ingredient;
在我的Dao的方法get
中,我尝试了不同的方法:
使用CriteriaQuery
获取成分,然后将其设置为产品
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<ProductComposition> q = cb.createQuery(ProductComposition.class);
Root<ProductComposition> product = q.from(ProductComposition.class);
product.fetch("principalProduct", JoinType.LEFT);
q.select(product).where(cb.equal(product.get("principalProduct"), id));
List<ProductComposition> ingredients = entityManager.createQuery(q).getResultList();
Product p = entityManager.find(Product.class, id);
p.setIngredients(ingredients);
使用Entity Graph
EntityGraph<Product> graph = (EntityGraph<Product>) entityManager.getEntityGraph("graph.Product.ingredients");
Map<String, Object> ingredients = new HashMap<>();
ingredients.put("javax.persistence.fetchgraph", graph);
Product p = entityManager.find(entityClass, id, ingredients);
调用方法initialize
p = productDao.get(p.getIdProduct()); //the get here just calls entityManager.find(Product.class, id)
Hibernate.initialize(p.getIngredients());
System.out.println("Ingredients size: "+p.getIngredients().size()); //gives 0
在调用了上述两行之后,我得到以下两个日志,但是p
之后仍然没有内容:
Hibernate: select product0_.idProduct as idProduc1_4_0_, product0_.name as name2_4_0_, orders1_.product_idProduct as product_3_3_1_, orders1_.foodOrder_idFoodOrder as foodOrde2_3_1_, orders1_.foodOrder_idFoodOrder as foodOrde2_3_2_, orders1_.product_idProduct as product_3_3_2_, orders1_.quantity as quantity1_3_2_, foodorder2_.idFoodOrder as idFoodOr1_2_3_, foodorder2_.CustomerID as Customer2_2_3_, foodorder2_.DeliverymanID as Delivery3_2_3_, foodorder2_.RestaurantID as Restaura4_2_3_ from Product product0_ left outer join OrderDetail orders1_ on product0_.idProduct=orders1_.product_idProduct left outer join FoodOrder foodorder2_ on orders1_.foodOrder_idFoodOrder=foodorder2_.idFoodOrder where product0_.idProduct=?
Hibernate: select ingredient0_.ingredient_idProduct as ingredie2_5_0_, ingredient0_.principalProduct_idProduct as principa3_5_0_, ingredient0_.ingredient_idProduct as ingredie2_5_1_, ingredient0_.principalProduct_idProduct as principa3_5_1_, ingredient0_.quantity as quantity1_5_1_, product1_.idProduct as idProduc1_4_2_, product1_.name as name2_4_2_ from ProductComposition ingredient0_ inner join Product product1_ on ingredient0_.principalProduct_idProduct=product1_.idProduct where ingredient0_.ingredient_idProduct=?
但是,所有尝试都无法加载成分。他们只是返回一个空列表。
我用这种方法做错了什么?
我宁愿保持这种懒惰的关系。同样因为休眠,否则将返回cannot simultaneously fetch multiple bags
,它引用了Product.orders和Product.ingredients