Я пытаюсь лениво загрузить ингредиенты продукта в собственные отношения. Продукт может иметь ноль или более ингредиентов. Отношение сохраняется в сущности 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;
В методе 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=?
Однако, все попытки не могут загрузить ингредиенты. Они просто возвращают пустой список.
Что я делаю не так в этих методах?
Я бы предпочел, чтобы отношения были ленивыми. Кроме того, потому что в противном случае Hibernate вернет cannot simultaneously fetch multiple bags
, ссылаясь на Product.orders и Product.ingredients