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: Это должно быть исключение при отложенной загрузке
Результат отладки: Во время отладки у меня есть доступ к электроинструментуно он должен выдавать исключение отложенной загрузки
Когда я включаю отображение SQL и изменяю метод в контроллере, чтобы напрямую получать electricTool из userInformation, он возвращает объект, но должен выдавать исключение, и 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