【问题标题】:JPQL Join on one to many databaseJPQL加入一对多数据库
【发布时间】:2014-02-24 21:32:53
【问题描述】:

我知道它之前已经在这里提到过几次,但我真的无法让它为我工作,

我有两个实体:配方,成分:

@Entity
@Table(name = "Recipe")
public class Recipe {

    @Id
    @GeneratedValue
    @Column(name = "Recipe_id")
    private Long id;

    private String name;

    private String description;
    @Lob
    @Basic(fetch = FetchType.LAZY)
    @Column(length = 100000)
    private byte[] image;

    @OneToMany(mappedBy = "recipe", fetch = FetchType.EAGER)
    @Cascade({CascadeType.ALL})
    private List<Ingredient> ingredientsList;
....
}

和成分:

@Entity
@Table
public class Ingredient {

    @Id
    @GeneratedValue
    private Long id;

    private String name;

    private int cpt;

    private String cptyType;

    @ManyToOne
    @JoinColumn(name = "Recipe_id")
    private Recipe recipe;

....
}

我还设置了 JPA 存储库,我想创建自定义查询,相当于:

SELECT *
FROM `Recipe`
INNER JOIN `Ingredient` ON Recipe.Recipe_id = Ingredient.Recipe_id
WHERE Ingredient.name = "fancyName"
LIMIT 0 , 30

到目前为止,我已经尝试过这个:

@Query("Select r from Recipe r join r.id i  where i.name = :ingredient")
List<Recipe> findRecipeByIngredient(@Param("ingredient") String ingredient);

以期望结束:

Caused by: java.lang.NullPointerException
        at org.hibernate.hql.internal.ast.HqlSqlWalker.createFromJoinElement(HqlSqlWalker.java:395)
        at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.joinElement(HqlSqlBaseWalker.java:3477)
        at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.fromElement(HqlSqlBaseWalker.java:3263)
        at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.fromElementList(HqlSqlBaseWalker.java:3141)
        at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.fromClause(HqlSqlBaseWalker.java:694)
        at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.query(HqlSqlBaseWalker.java:550)
        at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.selectStatement(HqlSqlBaseWalker.java:287)
        at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.statement(HqlSqlBaseWalker.java:235)
        at org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:248)
        at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:183)
        at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:136)
        at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:101)
        at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:80)
        at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:119)
        at org.hibernate.internal.AbstractSessionImpl.getHQLQueryPlan(AbstractSessionImpl.java:214)
        at org.hibernate.internal.AbstractSessionImpl.createQuery(AbstractSessionImpl.java:192)

我尝试过这样的事情:

@Query("Select r from Recipe r join fetch r.ingredientsList where r.name = :ingredient")
    List<Recipe> findRecipeByIngredient(@Param("ingredient") String ingredient);

这不会导致任何错误,但会返回空结果。

这是一个琐碎的问题,但我之前对 jpql 没有任何经验 = /

编辑:

仍然得到空结果:

DEBUG (SqlStatementLogger.java:104) - select recipe0_.Recipe_id as Recipe1_1_0_, ingredient1_.id as id0_1_, recipe0_.description as descript2_1_0_, recipe0_.image as image1_0_, recipe0_.name as name1_0_, ingredient1_.cpt as cpt0_1_, ingredient1_.cptyType as cptyType0_1_, ingredient1_.name as name0_1_, ingredient1_.Recipe_id as Recipe5_0_1_, ingredient1_.Recipe_id as Recipe5_1_0__, ingredient1_.id as id0__ from Recipe recipe0_ inner join Ingredient ingredient1_ on recipe0_.Recipe_id=ingredient1_.Recipe_id where ingredient1_.name=?
DEBUG (CollectionLoadContext.java:224) - No collections were found in result set for role: com.bla.model.Recipe.ingredientsList

编辑 2:

从语句中删除 fetch 后:

DEBUG (SqlStatementLogger.java:104) - select recipe0_.Recipe_id as Recipe1_1_, recipe0_.description as descript2_1_, recipe0_.image as image1_, recipe0_.name as name1_ from Recipe recipe0_ inner join Ingredient ingredient1_ on recipe0_.Recipe_id=ingredient1_.Recipe_id where ingredient1_.name=?
DEBUG (StatefulPersistenceContext.java:899) - Initializing non-lazy collections

【问题讨论】:

    标签: java hibernate jpa jpql


    【解决方案1】:

    您的最后一个查询搜索名称为作为参数传递的成分名称的所有食谱。那不是你想要的。您想要的是所有配方的名称都是作为参数传递的成分名称:

    select r from Recipe r
    join r.ingredientList i
    where i.name = :ingredient
    

    旁注:为什么我不能有两个使用相同成分的食谱?相当有限。关联应该是ManyToMany。

    【讨论】:

    • 好吧,我真的找不到我没有做的原因!感谢这个简单但非常有用的提示。今天将检查查询 = )。感谢您的快速答复。
    • 我已经更新了描述。我想我们快到了 = )
    • 从查询中删除fetch。并粘贴您正在使用的新 JPQL 查询
    • 您可能没有任何具有所提供名称的成分的配方。粘贴执行 JPQL 查询的代码,告诉您作为参数传递的名称,并显示表包含的内容。
    • 奇怪的事情,当我从 netbeans 级别 [sql 客户端] 运行此查询时,它返回一些值 [预期]。我认为这与我传递论点的方式有关。
    【解决方案2】:

    您的 JPQl 查询应如下所示:- (因为 JPA 已经在连接元数据中烘焙,但对于 @OnetoMany,我们可以将其用于 JPQl)

    @Query("Select r from Recipe r join Ingredient i on r.id = i.recipe.id where i.name=:ingredient)
    
    List<Recipe> findRecipeByIngredient(@Param("ingredient") String ingredient);
    

    【讨论】:

      猜你喜欢
      • 2013-06-17
      • 2017-06-20
      • 2021-08-18
      • 2013-06-11
      • 2017-07-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多