首页 > 解决方案 > 尽管配置良好,@OneToMany 延迟加载仍不起作用

问题描述

Java 8 春季启动 2.0.5

我有以下配置,我确信这是正确的。在调试期间,我可以从 UserInformations 中延迟加载的工具集合中获取值。我读到调试正在执行额外的提取以使用户能够从数据库中获取值,但是System.out.print在我的端点中简单应该会失败。我想延迟加载集合,@OneToMany因为现在正在加载急切,如果我将有更多数据获取单个UserInformation将很长。@OneToMany默认情况下是懒惰的,但在我的示例中,它的工作很热切,我不知道为什么要修复它来获取懒惰。

这是我的课:

@Getter
@Setter
@NoArgsConstructor
public class ElectricTool {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotNull
    @NotBlank
    @NotEmpty
    @Size(max = 64)
    private String name;

    @ManyToOne
    private UserInformation userInformation;

    public ElectricTool(String name) {
        this.name = name;
    }
}



@Getter
@Setter
@Entity
public class UserInformation {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotNull
    @NotEmpty
    @NotBlank
    @Size(max = 32)
    private String firstName;

    @OneToMany(mappedBy = "userInformation")
    private Set<ElectricTool> electricTools;

    public UserInformation() {
        this.electricTools = new HashSet<>();
    }

    public UserInformation(String firstName) {
        this.firstName = firstName;
        this.electricTools = new HashSet<>();
    }
}

@Repository
public interface UserInformationRepository extends
JpaRepository<UserInformation, Long> {}

@Repository
public interface ElectricToolRepository extends
JpaRepository<ElectricTool, Long> {}


@RestController
@RequestMapping(value = "/lazy")
public class LazyController {

    private UserInformationRepository userInformationRepository;
    private ElectricToolRepository electricToolRepository;

    public LazyController(UserInformationRepository userInformationRepository, ElectricToolRepository electricToolRepository) {
    this.userInformationRepository = userInformationRepository;
    this.electricToolRepository = electricToolRepository;
}

@GetMapping
public void checkLazy() {
    userInformationRepository.findAll().get(0).getElectricTools().stream().findFirst().get();
   }
}

配置

spring.datasource:
    url: jdbc:postgresql://localhost:5432/lazy
    username: postgres
    password: admin
spring.jpa:
    show-sql: true
    hibernate.ddl-auto: create-drop
    database-platform: org.hibernate.dialect.PostgreSQLDialect
    properties.hibernate.jdbc.lob.non_contextual_creation: true

System.out.print 的结果: 这应该是延迟加载异常

调试结果: 调试时我可以使用电动工具,但它应该抛出延迟加载异常

当我打开 SQL 的显示并更改控制器中的方法以直接从 userInformation 获取electricTool 时,它返回对象但应该抛出异常并且 sql 看起来像这样

select userinform0_.id as id1_1_, userinform0_.first_name as first_na2_1_ from user_information userinform0_
select electricto0_.user_information_id as user_inf3_0_0_, electricto0_.id as id1_0_0_, electricto0_.id as id1_0_1_, electricto0_.name as name2_0_1_, electricto0_.user_information_id as user_inf3_0_1_ from electric_tool electricto0_ where electricto0_.user_information_id=?
select userinform0_.id as id1_1_, userinform0_.first_name as first_na2_1_ from user_information userinform0_

当您问我为什么我认为在询问@OneToMany 注释的集合中的元素时我应该得到延迟获取异常时,我只想向您展示与上面相同的配置,但在第二个项目中可以正常工作,但让我们看看代码

@Entity
@Getter
@Setter
public class UserInformation {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String firstName;
    @OneToMany(mappedBy = "userInformation")
    private Set<Address> addresses;

    public UserInformation() {
        this.addresses = new HashSet<>();
    }

    public UserInformation(String firstName) {
        this.firstName = firstName;
        this.addresses = new HashSet<>();
    }
}


@Entity
@Getter
@Setter
@NoArgsConstructor
public class Address {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String city;
    @ManyToOne
    private UserInformation userInformation;

    public Address(String city) {
        this.city = city;
    }
}


@Repository
public interface UserInformationRepository extends JpaRepository<UserInformation, Long> {
}

@Repository
public interface AddressRepository extends JpaRepository<Address, Long> {
}

配置

spring.datasource:
    url: jdbc:postgresql://localhost:5432/specification
    username: postgres
    password: admin
spring.jpa:
    show-sql: true
    hibernate.ddl-auto: create-drop
    database-platform: org.hibernate.dialect.PostgreSQLDialect
    properties.hibernate.jdbc.lob.non_contextual_creation: true

当我尝试执行那段代码时:

userInformationRepository.findAll()

结果

我得到 LazyInitializationException ,这是我想在第一个示例中获得的行为。那么第一个示例中的错误在哪里,因为 findAll 方法给了我调试器中的所有嵌套关系

另外,当我执行与第一个示例相同的执行时,我得到 LazyInitializationException

userInformationRepository.findAll().get(0).getAddresses().stream().findFirst().get();

failed to lazily initialize a collection of role: com.specification.specification.entity.borrow.UserInformation.addresses, could not initialize proxy - no Session

标签: hibernatespring-bootjpa

解决方案


正如@Abdullah Khan 所说,问题已解决,sql 日志正确显示所有这些示例都有效,但 Intellij 的调试器会获取对象的必要关系,关闭主题。谢谢大家的帮助:)


推荐阅读