Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/332.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用QueryDSL和JPASQLQuery连接多对多关系_Java_Jpa_Querydsl - Fatal编程技术网

Java 使用QueryDSL和JPASQLQuery连接多对多关系

Java 使用QueryDSL和JPASQLQuery连接多对多关系,java,jpa,querydsl,Java,Jpa,Querydsl,我拥有以下实体: @AllArgsConstructor @EqualsAndHashCode(of = {"name"}) @Data @NoArgsConstructor @Entity @Table(schema = "eat") public class Pizza { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator="pizza_id_se

我拥有以下实体:

@AllArgsConstructor
@EqualsAndHashCode(of = {"name"})
@Data
@NoArgsConstructor
@Entity
@Table(schema = "eat")
public class Pizza {

   @Id
   @GeneratedValue(strategy = GenerationType.SEQUENCE, generator="pizza_id_seq")
   private Integer id;

   @NotNull       
   private String name;

   @NotNull
   @Positive
   private Double cost;

   @ManyToMany
   @JoinTable(schema = "eat",
              name = "pizza_ingredient",
              inverseJoinColumns = { @JoinColumn(name = "ingredient_id") })
   private Set<Ingredient> ingredients;

}


@AllArgsConstructor
@EqualsAndHashCode(of = {"name"})
@Data
@NoArgsConstructor
@Entity
@Table(schema = "eat")
public class Ingredient {

   @Id
   @GeneratedValue(strategy = GenerationType.SEQUENCE, generator="ingredient_id_seq")
   private Integer id;

   @NotNull
   @Size(min=1, max=64)
   private String name;

}
问题出现在尝试使用
join
函数时,例如:

QIngredient ingredient = QIngredient.ingredient;
QPizza pizza = QPizza.pizza;

StringPath ingredientPath = Expressions.stringPath("ingredient");
StringPath pizzaPath = Expressions.stringPath("pizza");
NumberPath<Double> costPath = Expressions.numberPath(Double.class, "cost");
Expression rowNumber = SQLExpressions.rowNumber().over().partitionBy(ingredientPath).orderBy(costPath.desc()).as("rnk");

JPASQLQuery subQuery = getJPASQLQuery()
   .select(ingredient.name.as(ingredientPath), pizza.name.as(pizzaPath), pizza.cost.as(costPath), rowNumber)
   .from(pizza)
   // The error is in next innerJoin
   .innerJoin((SubQueryExpression<?>) pizza.ingredients, ingredient)
   .where(ingredient.name.in(ingredientNames));
@Table(schema = "eat")
public class Pizza ...
我无法删除当前的
(SubQueryExpression)
,因为
innerJoin
不接受
SetPath
作为参数

另一方面,以下方面:

.from(pizza)               
.innerJoin(ingredient)
由于生成的查询中未包含
pizza\u配料
,因此不起作用


如何将
JPASQLQuery
中的
innerJoin
与上述多对多关系一起使用?

基本上,有两种主要的解决方法:


包括必需的本机函数 正如一位QueryDSL开发人员所建议的,用JPA替代品取代
JPASQLQuery


为多对多表创建所需的路径 首先,将
name
属性添加到每个
@表
注释中非常重要,因为内部是QueryDSL
NativeSQLSerializer
类用于从和
联接
子句生成

例如:

QIngredient ingredient = QIngredient.ingredient;
QPizza pizza = QPizza.pizza;

StringPath ingredientPath = Expressions.stringPath("ingredient");
StringPath pizzaPath = Expressions.stringPath("pizza");
NumberPath<Double> costPath = Expressions.numberPath(Double.class, "cost");
Expression rowNumber = SQLExpressions.rowNumber().over().partitionBy(ingredientPath).orderBy(costPath.desc()).as("rnk");

JPASQLQuery subQuery = getJPASQLQuery()
   .select(ingredient.name.as(ingredientPath), pizza.name.as(pizzaPath), pizza.cost.as(costPath), rowNumber)
   .from(pizza)
   // The error is in next innerJoin
   .innerJoin((SubQueryExpression<?>) pizza.ingredients, ingredient)
   .where(ingredient.name.in(ingredientNames));
@Table(schema = "eat")
public class Pizza ...
应替换为:

@Table(name = "pizza", schema = "eat")
public class Pizza ...
接下来,为多对多表的自定义路径创建:

RelationalPathBase<Object> pizzaIngredient = new RelationalPathBase<>(Object.class, "pi", "eat", "pizza_ingredient");
NumberPath<Integer> pizzaIngredient_PizzaId = Expressions.numberPath(Integer.class, pizzaIngredient, "pizza_id");
NumberPath<Integer> pizzaIngredient_IngredientId = Expressions.numberPath(Integer.class, pizzaIngredient, "ingredient_id");
RelationalPathBase PizzaComponent=新的RelationalPathBase(Object.class,“pi”,“eat”,“pizza_配料”);
NumberPath PizzaComponent_PizzaId=Expressions.NumberPath(Integer.class,pizzaComponent,“pizza_id”);
NumberPath PizzaComponent\u IngredenId=Expressions.NumberPath(Integer.class,PizzaComponent,“Component\u id”);
因此,完整的代码是:

QIngredient ingredient = QIngredient.ingredient;
QPizza pizza = QPizza.pizza;

RelationalPathBase<Object> pizzaIngredient = new RelationalPathBase<>(Object.class, "pi", "eat", "pizza_ingredient");
NumberPath<Integer> pizzaIngredient_PizzaId = Expressions.numberPath(Integer.class, pizzaIngredient, "pizza_id");
NumberPath<Integer> pizzaIngredient_IngredientId = Expressions.numberPath(Integer.class, pizzaIngredient, "ingredient_id");

StringPath ingredientPath = Expressions.stringPath("ingredient");
StringPath pizzaPath = Expressions.stringPath( "pizza");
NumberPath<Double> costPath = Expressions.numberPath(Double.class, "cost");

Expression rowNumber = SQLExpressions.rowNumber().over().partitionBy(ingredientPath).orderBy(costPath.desc()).as("rnk");
NumberPath<Long> rnk = Expressions.numberPath(Long.class, "rnk");

SubQueryExpression subQuery = getJPASQLQuery()
   .select(ingredient.name.as(ingredientPath), pizza.name.as(pizzaPath), pizza.cost.as(costPath), rowNumber)
   .from(pizza)
   .innerJoin(pizzaIngredient).on(pizzaIngredient_PizzaId.eq(pizza.id))
   .innerJoin(ingredient).on(ingredient.id.eq(pizzaIngredient_IngredientId))
   .where(ingredient.name.in(ingredientNames));

return getJPASQLQuery()
          .select(ingredientPath, pizzaPath, costPath)
          .from(
              subQuery,
              Expressions.stringPath("temp")
          )
          .where(rnk.eq(1l))
          .fetch();
QIngredient-component=QIngredient.component;
QPizza比萨饼=QPizza.pizza;
RelationalPathBase PizzaComponent=新的RelationalPathBase(Object.class,“pi”,“eat”,“pizza_配料”);
NumberPath PizzaComponent_PizzaId=Expressions.NumberPath(Integer.class,pizzaComponent,“pizza_id”);
NumberPath PizzaComponent\u IngredenId=Expressions.NumberPath(Integer.class,PizzaComponent,“Component\u id”);
StringPath ingredientPath=Expressions.StringPath(“成分”);
StringPath pizzaPath=Expressions.StringPath(“pizzaPath”);
NumberPath costPath=Expressions.NumberPath(Double.class,“cost”);
表达式rowNumber=SQLExpressions.rowNumber().over().partitionBy(IngreditEntPath).orderBy(costPath.desc()).as(“rnk”);
NumberPath rnk=Expressions.NumberPath(Long.class,“rnk”);
SubQueryExpression subQuery=getJPASQLQuery()
.选择(配料.name.as(IngreditPath)、pizza.name.as(pizzaPath)、pizza.cost.as(costPath)、rowNumber)
.来自(比萨饼)
.innerJoin(PizzaComponent).on(PizzaComponent_PizzaId.eq(pizza.id))
.innerJoin(配料).on(配料.id.eq(比萨配料)
.其中(成分名称)在(IngreditNames)中;
返回getJPASQLQuery()
.选择(IngreditPath、pizzaPath、costPath)
.来自(
子查询,
表达式.stringPath(“temp”)
)
.式中(rnk等式(1l))
.fetch();