@OneToMany延迟加载尽管配置好也无法正常工作

时间:2018-11-21 09:11:08

标签: hibernate spring-boot jpa

Java 8 Spring Boot 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的结果: This should be lazy loading exception

调试结果: While debugging i have access to electric tool but it should throw lazy loading exception

当我打开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()

Result

我得到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

2 个答案:

答案 0 :(得分:0)

它将仅打印该类的地址/引用。如果要打印值,请重写如下的toString方法。

@Override
public String toString() 
{
    return new ToStringBuilder(this)
      .append("name", name)
      .append("etc", etc)
      .toString(); 
}

还在onetomany映射中添加级联类型和访存类型。

@OneToMany(mappedBy = "userInformation",cascade=CascadeType.ALL,fetch=FetchType.EAGER)

答案 1 :(得分:0)

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