Java 不带惰性字段的休眠克隆实体

Java 不带惰性字段的休眠克隆实体,java,hibernate,spring-data-jpa,entitymanager,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;

我有两个实体:

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

这个人很懒。我加载一个用户并将其分离

    @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字段,但它仍然有效

我想创建一个不带person的用户克隆,并另存为一个新实体

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);
但这个人很懒,看起来像个黑客。那么,分离方法的意义是什么呢

编辑:

非常有趣的事情-如果我在调试断点时启动示例应用程序-所有都可以正常工作,但如果我取消选择所有断点,我会在控制台中遇到异常:

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

如果我理解的话,你是在克隆上调用分离?这个克隆不是普通的用户对象,而是扩展用户对象的代理

您需要首先使用
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

如果我理解的话,你是在克隆上调用分离?这个克隆不是普通的用户对象,而是扩展用户对象的代理

您需要首先使用
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

detach
点上,似乎实际加载了
Person

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

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


因此,查看Hibernate调试日志,很可能会在某个地方加入Person及其字段的选择。

似乎在
分离时,
Person
实际上已经加载

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

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


因此,请查看Hibernate调试日志,最有可能的情况是,在某个地方会有一个连接到Person及其字段的选择。

当您调用detach时,该对象会从会话(如事务)中分离,并且不会保存到数据库,除非您在某个点再次附加它。。。但是它的所有属性都与您的用例相同,您需要在分离“用户”后刷新会话。一旦您准备好“克隆”对象,您将需要一个打开的会话当您调用detach时,该对象将从会话(如事务)中分离,并且不会保存到数据库,除非您在某个点再次附加它。。。但是它的所有属性都与您的用例相同,您需要在分离“用户”后刷新会话。一旦您准备好“克隆”对象,您将需要一个打开的会话是的,我看到了hibernate日志。首先-加载唯一的用户而不加载人员。之后,我调用detach方法。然后,我调用
user.getPerson()
。hibernate进行一个新的查询(标准的延迟加载)。但是我不明白如果用户已经分离,它怎么能做到。是的,我看到了hibernate日志。首先-加载唯一的用户而不加载人员。之后,我调用detach方法。然后,我调用
user.getPerson()
。hibernate进行一个新的查询(标准的延迟加载)。但我不明白,如果用户已经分离,它怎么能做到这一点。