2

我试图弄清楚我在使用 JPA/Hibernate 时做错了什么。

我有一个包含两个表的数据库:横幅和横幅链接。

 banner
 +-------------------------------------------+
 | id | logo | studyId | textColor | bgColor |
 +-------------------------------------------+
 |  1 | xx   |  17     |  green    | red     |
 +-------------------------------------------+

 bannerlink
 +----------------------------------------+
 | id | bannerId| label | text | image    |
 +----------------------------------------+
 |  1 | 1       |  About| Abt..| xxx      |
 +----------------------------------------+
 |  2 | 1       |  Beta | Bet..| xxx      |
 +----------------------------------------+
 |  2 | 1       |  Cont | Ctc..| xxx      |
 +----------------------------------------+

以及每个实体类

@Entity
@Table(name="bannerlink")
public class BannerLink{
    @Id
    @GeneratedValue
    private int id;
    private String label;

    @ManyToOne
    @JoinColumn(name = "bannerId")
    private Banner banner;
    ...
}


@Entity
@Table(name = "banner")
public class Banner {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    private String logo;
    private String textColor;
    private String backgroundColor;
    private int studyId;

    @OneToMany(
        mappedBy = "banner",
        cascade = CascadeType.ALL,
        fetch=FetchType.LAZY,
        targetEntity = BannerLink.class
    )
    private List<BannerLink> links;

    public Banner() {
    }
    ...
 } 

我还定义了一个 DAO。

public interface BannerDAO extends JpaRepository<Banner, Integer> {

    @Query("select distinct banner FROM Banner banner join BannerLink bl where banner.studyId = :studyId")
    Banner getBannerByStudyId(@Param("studyId") int studyId);
}

但是,当我运行 DAO 方法 getBannerByStudyId 时,我得到一个异常“com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException:您的 SQL 语法有错误;请查看与您的 MariaDB 服务器版本对应的手册以获取正确的语法在第 1 行的“其中banner0_.studyId=17”附近使用”

打印出 Hibernate 生成的 RAW SQL 显示 INNER JOIN ON 子句中缺少参数。

 Hibernate: 
     select
         distinct banner0_.id as id1_0_,
         banner0_.backgroundColor as backgrou2_0_,
         banner0_.logo as logo3_0_,
         banner0_.studyId as studyId4_0_,
         banner0_.textColor as textColo5_0_ 
     from
         banner banner0_ 
     inner join
         bannerlink bannerlink1_ 
             on 
     where
         banner0_.studyId=?

任何想法我做错了什么?

4

4 回答 4

1

是的!我花了很长时间才弄清楚!

有两种加入方式。如果您按原样加入,则在实体之间,您必须指定要加入的属性。JPA 不会猜测。

所以你必须这样做:

@Query("select distinct b FROM Banner b join BannerLink bl ON b.id = bl.bannerId WHERE b.studyId = :studyId") Banner getBannerByStudyId(@Param("studyId") int studyId);

但是,您几乎应该总是指定父级的属性来进行连接,即作为子级集合的属性。这样你就告诉 JPA 如何加入表,你只需要给它 Where 子句:

@Query("select distinct b FROM Banner b join b.links bl WHERE b.studyId = :studyId") Banner getBannerByStudyId(@Param("studyId") int studyId);

参考:https ://www.objectdb.com/java/jpa/query/jpql/from

于 2020-03-05T17:22:01.187 回答
1

你的查询是错误的。正确的查询是 >

"select distinct banner FROM Banner banner fetch join banner.links where banner.studyId = :studyId"

我理解你的问题的方式是你想获取一个 studyId 的所有横幅及其相应的链接。如果我错了,请纠正我。上面的查询正在完成这项工作。

于 2018-08-15T20:28:39.613 回答
0

同意@kSp - 如果您使用的是 Spring Data JPA,则没有理由自己编写此查询并且不使用它的功能来生成基于方法名称的查询。否则,如果您确实需要自己编写,请尝试使用正确的 JPQL 连接编写查询,例如

SELECT b from Banner b JOIN b.links WHERE b.studyId = :studyId

于 2018-08-15T20:28:40.500 回答
0

为什么需要加入,这是某种隐式过滤器吗?正如我所见,studyId 在横幅中,所以只需删除查询并将函数名称更改为 findOneByStudyId。同时删除 Param 注释。然后,如果您需要链接信息,只需调用 getter,而不是懒惰地获取它。但是,如果您需要该加入,我会这样写(未经测试): SELECT DISTINCT b FROM Banner b, BannerLink bl WHERE b.studyId = :studyId

于 2018-08-15T20:20:48.560 回答