java Spring boot JPA延迟加载不适用于一对一映射
请注意,我已经研究了类似的问题,并解释了为什么这些问题对我不起作用
我有一个简单的Spring boot JPA Hibernate应用程序,在用户和地址之间有一对一的映射。(请注意,我没有一对多映射的问题)
用户实体
@Entity
@Table(name = "users")
public class User implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Integer id;
@Column
private String name;
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "user")
private Address address;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "user")
private Set<Note> notes;
}
地址实体
@Entity
@Table(name = "addresses")
public class Address implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Integer id;
@Column
private String street;
@Column
private String city;
@JsonIgnore
@OneToOne
@JoinColumn(name = "user_id")
private User user;
}
票据实体
@Entity
@Table(name = "notes")
public class Note implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Integer id;
@Column
private String date;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id", nullable = false)
private User user;
}
我的问题是,每当我调用控制器mapped来获取所有用户时,我都会获取地址以及与之相关的所有注释。但我希望FetchType.LAZY
能解决这个问题
我在StackOverflow上读到很多问题,提到杰克逊可能是罪魁祸首:
那年春天我也读了。jpa。在视图中打开解除值可能是罪魁祸首:
因此,我尝试了以下选项:
我通过将spring.jpa.open-in-view=false
添加到我的application.properties
中禁用了默认的“在视图中打开”属性,该属性开始为我提供
Could not write JSON: failed to lazily initialize a collection of role error
我假设这是因为Jackson正在调用我的延迟加载对象的getter,所以我按照另一篇文章中的说明添加了以下内容,以便Jackson不使用延迟加载的集合:
波姆。xml
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-hibernate5</artifactId>
<version>2.9.9</version>
</dependency>
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
for (HttpMessageConverter converter : converters) {
if (converter instanceof org.springframework.http.converter.json.MappingJackson2HttpMessageConverter) {
ObjectMapper mapper = ((MappingJackson2HttpMessageConverter) converter).getObjectMapper();
mapper.registerModule(new Hibernate5Module());
}
}
}
}
上面的这个解决方案修复了一对多映射的问题,但是仍然有响应中关联的地址
我不知道我能在这里做什么。默认登录页上的用户实体不需要任何地址详细信息,因此我不想将其加载到登录页上。单击记录后,它将导航到另一个页面,我希望在响应中返回所有延迟加载的对象
我已经尝试了所有我能在网上找到的东西,但到目前为止仍然没有任何效果。我真的很感激你能帮我
如其中一位用户所述,这可能是另一个问题的重复,因此: Suggested Possible duplicate 我想提到的是,我通过禁用spring实现了延迟加载。jpa。在视图中打开属性,但添加
mapper.registerModule(new Hibernate5Module());
返回响应中与用户关联的地址
# 1 楼答案
你可以看看Jackson Serialization Views
我已经了解了您尝试的Hibernate5模块,它有一些有趣的特性。。。但是没有人应该为您解决这个问题
顺便说一句,我通常通过不返回实体作为响应,而是返回DTO来解决这个问题
# 2 楼答案
问题是jackson在写入JSON时触发初始化,所以不要写入当前字段(地址)。但是您不应该使用
@jsonIgnore
,因此在其他地方可以返回Eager
obj您可以使用
@jsonView
注释,该注释可以在不同的请求下为同一obj提供不同的JSON。您可以查看以下示例:创建视图类:
注释您的实体
在控制器中指定
FetchType
类:这是我的想法来源的答案https://stackoverflow.com/a/49207551/10162200
# 3 楼答案
它的工作原理与JPA规范相同:-
请参阅下面的URL https://javaee.github.io/javaee-spec/javadocs/javax/persistence/FetchType.html
延迟抓取策略只是一个提示(正如javadoc所说,数据可以延迟抓取)。。这不是强制性的行动
Eager是必需的(正如javadoc所说的,必须急切地获取数据)