Ленивая загрузка @OneToMany не работает, несмотря на хорошую конфигурацию - PullRequest
0 голосов
/ 21 ноября 2018

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

Ответы [ 2 ]

0 голосов
/ 22 ноября 2018

Проблема решена, как сказал @Abdullah Khan, логи sql правильно показывают, что все эти примеры работают, но отладчик Intellij выбирает необходимые отношения для объектов, тему для закрытия.Спасибо ребята за помощь:)

0 голосов
/ 21 ноября 2018

Будет напечатан только адрес / ссылка на класс.если вы хотите напечатать значения, переопределите метод toString, как показано ниже.

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

Также добавьте каскадный тип и тип выборки в однообразное отображение.

@OneToMany(mappedBy = "userInformation",cascade=CascadeType.ALL,fetch=FetchType.EAGER)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...