没有惰性字段的休眠克隆实体

时间:2019-06-10 13:58:37

标签: java hibernate spring-data-jpa entitymanager

我有两个实体:

@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;

此人为LAZY。我加载了一个用户并将其分离。

    @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 :(得分:0)

据我了解,您是在克隆上调用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

答案 1 :(得分:0)

似乎在detach时实际上已经加载了Person

根据FetchType文档,这是可能的:

  

LAZY策略是对持久性提供程序运行时的提示,   首次访问时应延迟获取数据。的   允许实现急于获取LAZY的数据   策略提示已指定。

因此,请查看Hibernate调试日志,最有可能在某处加入一个Person以及其字段选择。