java - 在复制构造函数中使用直接字段访问而不是 getter 会导致空指针异常

标签 java hibernate copy-constructor lombok intellij-lombok-plugin

它一定是 Java 101,但我不明白为什么我不能使用直接字段访问以及为什么我被迫在复制构造函数中使用 getter。

我有很多实体。它们像树一样组织起来。急切地获取链接的实体。

我使用 Hibernate、Lombok 和 IntelliJ 作为调试器。

当我拉动一个实体树的根时,我得到了一棵对象树。我们姑且称之为“原创”吧。由于与业务需求相关的某种原因,我需要复制它(我们称之为“副本”)。我使用复制构造函数来完成它。 我首先使用直接字段访问编写了复制构造函数的一个版本。

 this.someField= original.someField

没成功。当我检查调试器时,我看到original.someField(以及其他字段)始终为空。

enter image description here

尽管如此,它仍然可以使用 setter/getter 来工作。

 this.setSomeField(original.getSomeField())

在调试器中,我可以看到原始.handler.target 中的字段已“设置”。 (我不知道 handler.target 是什么)。

enter image description here

有人可以向我解释为什么直接字段访问不起作用吗?
(我问的是技术原因,而不是哲学原因,例如“你应该始终使用 setter/getter ”等)。

我也很高兴知道什么是“handler.target”。

提前致谢。

最佳答案

您遇到的根本不是Java 101问题。 Hibernate 有一个称为延迟加载的功能,它允许框架将(可能很重的)对象的加载推迟到稍后的时间点,仅在需要时。例如,当您加载 account 时,这会很方便。对象只是为了检查 active标志,但绝对不需要使用此帐户获取所有登录历史记录。

现在是“仅在需要时”部分: setter/getter 。

当您在对象图中的父对象上调用 getter 时,Hibernate 知道您确实需要该可延迟加载的对象。在您这样做之前,延迟引用的对象将保持为空。直接变量访问绕过了执行此“技巧”的代理逻辑,这就是获得意外空值的方法。当通过其 getter 访问该字段时,代理代码就会启动,发生加载,然后您就可以取回对象。

handler/target/etc只是由于代理而需要的额外引用。 (您的 account 将不再有直接的 accounthistory 变量,而是一个 accounthistory_proxy ,而后者又将有一个 accounthistory_real )

关于java - 在复制构造函数中使用直接字段访问而不是 getter 会导致空指针异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54194071/

相关文章:

c++ - 包含其他对象的类的复制构造函数中的取消引用语法

java - 如何从 JSP 文件中删除实体(使用 Google App Engine 的 Java)

java - java中CompareTo(Object o)用于比较字符串

java.sql.BatchUpdateException : Cannot add or update a child row: a foreign key constraint fails ERROR

java - JPA 选择查询返回带有 @ManyToOne 映射的实体

c++ - 错误 : definition of implicitly declared copy constructor

java - 启用 Java/Groovy URL 连接以忽略没有设置 setDefaultSSLSocketFactory 的 SSL 证书错误

java - 在 Java 电子表格应用程序中存储数据的最佳方法

java se 与 hibernate 和 JavaDB。我如何部署应用程序?

c++ - 临时对象是如何创建的,实际发生的操作是什么?