更新
我想指出@sainr 的回答 Converting Hibernate proxy to real entity object确实解决了问题。但幕后的问题是我的 SiteEntity
有一个 final
修饰符是 setControllerEntity
和 getControllerEntity
,我没有'提出我的问题。我道歉。
删除 final
修饰符。然后 Hibernate 可以很好地初始化代理对象。
解释可以在另一个answer中找到在 Stack Overflow 上。
我有如下三个实体
@Entity
@Table(name = "controller")
public class ControllerEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(nullable = false, updatable = false)
private long id;
}
@Entity
@Table(name = "site")
public class SiteEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(nullable = false)
private long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "controller_id", nullable = false)
private ControllerEntity controllerEntity;
}
@Entity
@Table(name = "device")
public class DeviceEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(nullable = false)
private long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "site_id", nullable = true)
private SiteEntity siteEntity;
}
找到设备实体后,我尝试直接从中获取 controllerEntity
。
final DeviceEntity deviceEntity1 = deviceRepository.findOne(1L);
System.out.println(deviceEntity1.getSiteEntity().getControllerEntity().getId());
但它会导致 java.lang.NullPointerException
,这是由 siteEntity
中的 null
controllerEntity
引起的.
此外,即使我尝试使用 siteRepositoy
再次获取 siteEntity。它的 controllerEntity
仍然是 null
。
在我从 DeviceEntity 和 SiteEntity 中删除 fetch = FetchType.LAZY
后,NPE 不再发生。
但这看起来很奇怪而且没有意义。我可以使用 FetchType.LAZY
并期待 hibernate 获取正确的值吗?
谢谢。
最佳答案
为了让您能够访问使用 FetchType.LAZY
声明的字段,Hibernate 使用 CGLIB 构造了一个代理。因此,当您为此类字段调用 getter(在您的情况下为 getSiteEntity()
或 getControllerEntity()
)时,您不会直接访问字段值 - - 相反,调用被传递给 Hibernate 的代理对象。反过来,Hibernate 会尝试从数据存储中加载实际值,为此,它需要一个 Activity 的 Hibernate session 来访问数据库。在您的情况下,Hibernate session 很可能已经关闭并且此类延迟加载失败,从而为您提供了该字段的有效 null
值。
基本上有两种方法可以解决这个问题:
- 使用
FetchType.EAGER
加载所有字段值以及持有对象DeviceEntity
- 将代理对象转换为真实对象(检查Converting Hibernate proxy to real entity object)并以常规方式访问它
考虑一下,您的情况是否真的需要延迟加载。如果您没有在子字段中存储大量重对象以按需加载它们,那么切换到 FetchType.EAGER
可能是最简单的方法。
希望对您有所帮助。
关于java - NullPointerException 发生在 FetchType.LAZY withi hibernate 和 spring boot,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47987472/