java - Spring boot JPA - 延迟加载不适用于一对一映射

标签 java hibernate spring-boot jpa jackson

请注意,我已经看过类似的问题,并且我已经解释了为什么它们对我不起作用

我有一个简单的 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;

    }

我的问题是,每当我调用映射的 Controller 来获取所有用户时,我都会获取地址以及与之相关的所有注释。但我希望 FetchType.LAZY 能够解决这个问题。

我在 StackOverflow 上读到了很多问题,提到 jackson 可能是这里的罪魁祸首:

Post 1

我还读到 spring.jpa.open-in-view 默认值可能是罪魁祸首:

Post 2

Post 3

所以我尝试了以下选项:

我通过将 spring.jpa.open-in-view=false 添加到我的 application.properties 来禁用默认在 View 中打开属性,这开始给我

Could not write JSON: failed to lazily initialize a collection of role error

我假设这是因为 jackson 正在调用我的延迟加载对象上的 setter/getter ,所以我按照另一篇文章中的说明添加了以下内容,以便 jackson 单独保留延迟加载的集合:

pom.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());
            }
        }
    }

}

上面的解决方案修复了一对多映射的问题,但响应中仍然具有关联的地址。

我不知道我能在这里做什么。默认登陆页面上的用户实体不需要任何地址详细信息,因此我不想将其加载到登陆页面上。单击记录时,它会导航到另一个页面,这就是我希望在响应中返回所有延迟加载对象的地方。

我已经尝试了网上能找到的所有方法,但到目前为止仍然没有效果。我真的很感激一些帮助。

正如一位用户提到的,它可能与 SO 上的另一个问题重复: Suggested Possible duplicate 我想提一下,我通过禁用 spring.jpa.open-in-view 属性但添加

来实现延迟加载
mapper.registerModule(new Hibernate5Module());

在响应中返回与用户关联的地址。

最佳答案

它的工作方式与 JPA 规范相同:-

引用以下网址 https://javaee.github.io/javaee-spec/javadocs/javax/persistence/FetchType.html

LAZY 获取策略只是一个提示(正如 javadoc 所说,可以延迟获取数据).. 不是强制操作。

Eager 是强制性的(正如 javadoc 所说,必须急切地获取数据)。

关于java - Spring boot JPA - 延迟加载不适用于一对一映射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57169361/

相关文章:

mysql - 如何将sql查询转换为hibernate查询以从数据库获取上周记录

java - Spring boot 和 GCP - 使用 spring-cloud-gcp-starter-sql-postgresql 连接 Cloud SQL 实例尝试 SSL,但启动延迟

java - 通过 -cp 而不是 -jar 运行 spring boot 应用程序 jar

java - 如何统计数组中每个单词的出现频率?

java - 将 ArrayList 保存到文本文件时出现 NotSerializedException

java - 多核与单处理器中的 volatile 关键字?

java - 我是否需要使用 @Access=FIELD 注释来进行多对一关系?

java - 使用输入列表获取实体对象列表 : Spring Data JPA - Hibernate

java - 无法在单元测试中使用自定义 Spring 转换器

java - 如何为用 java 编写的文本编辑器实现自动完成?