Spring Data Jpa findById,getOne找不到记录

目录
  1. 问题
  2. 描述
  3. 解决

问题

Spring Data JPA 使用findById(id),getOne(id),虽然数据库中存在记录,但查询不出来。

描述

最近升级项目框架,将Spring Boot版本升级至2.0.2。Spring Data JPA有不少变化,根据id查询 findOne(id)方法没有了,换成了findById(id),同时还有getOne(id)可以使用。

但使用新的根据id的查询方法找不到数据,虽然数据库中记录存在。

解决

查看sql日志发现新方法会将查询Entity中的关联Entity inner join进查询语句。示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// App.class
@Entity
@Table(name = "app")
@EqualsAndHashCode(callSuper = true)
@Data
@NoArgsConstructor
@SequenceGenerator(name = "app_id_seq", sequenceName = "app_id_seq", allocationSize = 1)
public class App extends SequenceIdentityEntity {
private static final long serialVersionUID = -259135240342702789L;
@Id
@Column(name = "id")
@GeneratedValue(generator = "app_id_seq", strategy = GenerationType.SEQUENCE)
private Integer id;
@Column(name = "name")
private String name;
@ManyToOne(optional = false)
@JoinColumn(name = "template_id", nullable = false)
private Template template;
@Column(name = "template_id", updatable = false, insertable = false)
private Integer templateId;
}
// Template.class 略
1
2
3
// 使用findById(id),getOne(id)时打印的sql
select app0.id as id1_0_0, app0.name as name_2_0_0, template1.app_id as app_id5_4_1, template1.name as name6_4_1
from app app0_ inner join template template1_ on app0.template_id=template1.id where app0_.id=?

因此若关联值templateId为空或值映射不上时,就会找不到app记录。

在@ManyToOne添加fetch = FetchType.LAZY即可解决问题,同理使用@OneToOne,@OneToMany等若不能保证 关联字段不为空且一定能找到关联数据 时,均需配置懒加载。

1
2
3
@ManyToOne(optional = false, fetch = FetchType.LAZY)
@JoinColumn(name = "template_id", nullable = false)
private Template template;