jpa自定义sql_JPA遇到多主键表怎么进行查询

数据表是原始就存在的,里面存在两个主键:

a5430de0b15463e32dab298d4ab005db.png
在这里插入图片描述

当建好实体类,然后用JPA去关联操作查询,(根据StudyId)去进行查询的时候,发现原本可以有八条不一样的记录,只是StudyId相同,其他的不同,这个时候,出来确实是八条,但是居然每一条都一样,是根据StudyId一样的数据记录里的都一条。

19eb2696b26c67e3ec5456cec06564b3.png
在这里插入图片描述

即当根据 StudyId='194205'去查的时候,JPA都会返回八条一样的记录

JPA代码:

@Query(value = "select * from tbl_ic_film_info where StudyId = ?1",nativeQuery = true)
List findByStudyIdSQL(String studyId);

service代码:

List icFilmInfoList= icFilmInfoRepository.findByStudyIdSQL(studyId);

然后循环打印icFilmInfoList

b6c3332e8f018bcd42400ead072cb6ad.png
在这里插入图片描述
FileName查出来都是1
后来才发现是联合主键惹得锅,数据库表中有两个主键,一个是StudyId,还有一个是FileName。
我的实体类是这么定义的(因为我只需要StudyId和FileName的信息就行了):
cbbea4edc039bb7b8b6531662957fb0c.png
在这里插入图片描述

当JPA在根据StudyId去查询的时候,只会将StudyId当做主键,当StudyId一样的时候,JPA会当做所有的都是同一条记录,不会管FileName是否相同了,一股脑的返回八条一样的数据。

对此其实有很多种解决办法,说下我使用的几种:

1、使用List>的方式去接收

由于这边数据库的记录值都字符串类型,我就直接使用List>了~

JPA代码:

@Query(value = "select StudyId,FileName from tbl_ic_film_info where StudyId = ?1",nativeQuery = true)
List> findByStudyIdMap(String studyId);

循环答应查询结果:

30e3b499e4968cdf908bc51ec1bd6983.png

这种方式有点就是代码简单,但是如果要对查询的结果再进行一步处理的话,就会变的更复杂,不好处理。
2、自定义接收类

新建一个IcFilmInfoVO类:

@AllArgsConstructor
@Data
public class IcFilmInfoVO {

    private String studyId;

    /**
     * 文件名
     */
    private String fileName;
}
  • 注意添加的全参构造方法注解@AllArgsConstructor

JAP代码

@Query(value = "select new cloud.image.vo.IcFilmInfoVO(t.studyId,t.fileName) from IcFilmInfo t where t.studyId = ?1")
List findByStudyId(String studyId);

注意,这个时候这里的@Query注解里面是没有加nativeQuery = true
然后循环打印查询结果:

ffcfc4b65aadfe8508ba3d363607d775.png


这样即使以后要操作查询的结果也很方便,同时这种自定义接收类的用法还可以用于统计等业务场景,可以接收sumcount等SQL内置函数查询出来的结果。

3、配置联合主键

由于表中是两个主键的存在,接下来改造一下我们的实体类:

@Entity
@Data
@IdClass(IcFilmInfoPk.class)
@Table(name = "tbl_ic_film_info")

public class IcFilmInfo implements Serializable {

    private static final long serialVersionUID = 9121531612760132363L;

    @Id
    @Column(name = "StudyId")
    private String studyId;

    /**
     * 文件名
     */
    @Id
    @Column(name = "FileName")
    private String fileName;
}

在两个主键映射的字段上都标注@Id注解
同时新建一个IcFilmInfoPk类:

@Data
public class IcFilmInfoPk implements Serializable {

    private static final long serialVersionUID = -1570834456846579284L;

    private String studyId;
    private String fileName;
}

在实体类上加上@IdClass(IcFilmInfoPk.class)注解,这个时候就可以用一下JPA代码直接去查询了

@Query(value = "select * from tbl_ic_film_info where StudyId = ?1",nativeQuery = true)
List findByStudyIdSQL(String studyId);

总结:

针对上面三种方法,貌似都可以解决我们的问题,但是个人只推荐第三种,因为第三种是最贴合数据库的,使用了联合主键的注解,数据库中也是多主键,但是第二种方式可以很好的解决我们在使用JPA去查询的时候接口其他非数据库字段的信息,例如统计等方面。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值