Спящий клон сущности без ленивых полей - PullRequest
1 голос
/ 10 июня 2019

У меня есть две сущности:

@Entity
@Table(name = "users")
public class User {

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

    @Column(name = "name")
    private String name;

    @Column(name = "age")
    private int age;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "person_id")
    private Person person;

и

@Entity
@Table(name = "persons")
public class Person {

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

    @Column(name = "name")
    private String name;

    @Column(name = "number")
    private String number;

Человек ленивый.Я загружаю одного пользователя и отсоединяю его.

    @Transactional
    @Override
    public void run(String... args) {
        User user = userService.getOne(1L);

        userService.detach(user);

        System.out.println(user.getName());
        System.out.println(user.getAge());
        Person person = user.getPerson();
        System.out.println(person.getName());
        System.out.println(person.getNumber());
    }

Но когда я звоню user.getPerson() - он не выдает исключений.Я ожидаю исключения, потому что я отсоединяю сущность и пытаюсь вызвать поле LAZY, но оно все еще работает.

Я хочу создать клон пользователя без лица и сохранить его как новую сущность.

User user = userService.getOne(1L);
userService.detach(user);
user.setId(null)//autogenerate id

но когда я сохраняю пользователя, человек тоже клонируется.Я могу установить ноль:

User user = userService.getOne(1L);
userService.detach(user);
user.setId(null);
user.setPerson(null);

Но человек ленив, и это выглядит как взломать.И какой смысл тогда detach метод ...

РЕДАКТИРОВАТЬ:

Очень интересная вещь - если я запускаю пример приложения в отладке с точками останова - все работает нормально, но если я отменяю выбор всех точек остановаЯ получаю исключение в консоли:

Caused by: org.hibernate.LazyInitializationException: could not initialize proxy [com.example.detachexample.User#1] - no Session

Ответы [ 2 ]

0 голосов
/ 10 июня 2019

Кажется, что в точке detach Person действительно загружено.

Это возможно согласно FetchType документации:

Стратегия LAZY - это подсказка для среды выполнения персистентного провайдера, которая данные должны извлекаться лениво при первом обращении к ним. Реализация разрешено охотно получать данные, для которых ленивый был указан совет по стратегии.

Итак, взгляните на журналы отладки Hibernate и, скорее всего, где-нибудь будет объединение с Person и выбор его полей.

0 голосов
/ 10 июня 2019

Если я понимаю, вы называете detach на клона? Хорошо, что клон не из простого объекта User, а из прокси, который расширяет объект User.

Сначала необходимо получить необработанный загруженный объект, используя unproxy.

User olduser = userService.getOne(1L);
User user = org.hibernate.Hibernate.unproxy(olduser);
if (olduser == user) userService.detach(user);
user.setId(null)//autogenerate id
user.getPerson().setId(null); // so you will generate this as well
user.getPerson().setUser(user); // so that it will point to the correct new entity
...