我正在尝试弄清JPA / Hibernate在做什么。
我有一个包含两个表的数据库:banner和bannerlinks。
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行的'where 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=?
有什么想法我在做什么错吗?
答案 0 :(得分:2)
您的查询错误。正确的查询是>
"select distinct banner FROM Banner banner fetch join banner.links where banner.studyId = :studyId"
我理解您的问题的方式是,您希望获取studyId的所有横幅及其对应的链接。如果我错了,请纠正我。上面的查询正在完成这项工作。
答案 1 :(得分:0)
您为什么需要Join,这是某种隐式过滤器吗?如我所见,studyId位于Banner中,因此只需删除查询并将函数名称更改为findOneByStudyId。同时删除参数注释。然后,如果您需要链接信息,则只需调用getter即可,因为它会延迟获取。 但是,如果您需要该连接,我会这样写(未经测试): 从Banner b,BannerLink bl中选择DISTINCT b。b.studyId =:studyId
答案 2 :(得分:0)
同意@kSp-如果您使用的是Spring Data JPA,则没有理由自己编写此查询,也无需使用它的功能来基于方法名称生成查询。否则,如果您需要自己编写,请尝试使用适当的JPQL连接(例如,
)编写查询 SELECT b from Banner b JOIN b.links WHERE b.studyId = :studyId
答案 3 :(得分:0)
是的!花了我很长时间才弄清楚!
有两种加入方式。如果要按原样加入,则必须在实体之间指定要加入的属性。 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);