JPA。 FetchType.Lazy 引起了奇怪的行为@ManyToOne
JPA. FetchType.Lazy caused strange behaviour @ManyToOne
我正在尝试提高使用 JPA 的项目的性能。
我正在使用 JPA 2.1 和 Hibernate 5.0.1 实现。
我将 ManyToOne 关系的 FetchType 更改为 Lazy,所以事情搞砸了。
当我试图查找子对象的所有记录时:最后一条记录带有所有空字段和 handler=JavasistLazyInitializer。这种奇怪的行为会影响使用此对象的字段(如 h:OneSelectMenu)。
如果我删除 FetchType.Lazy 东西恢复正常。
一些印刷品:
第二次打印代码(FetchType.Lazy):
public class Usuario implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "Id_Usuario")
private Integer idUsuario;
// Fields ...
@JoinColumn(name = "Id_Tipo_Logradouro", referencedColumnName = "Id_Tipo_Logradouro", nullable = true)
@ManyToOne(optional = true, fetch = FetchType.LAZY)
private TipoLogradouro tipoLogradouro;
@JoinColumn(name = "Id_Tipo_Usuario", referencedColumnName = "Id_Tipo_Usuario")
@ManyToOne(optional = false, fetch = FetchType.LAZY)
private TipoUsuario tipoUsuario;
@JoinColumn(name = "Id_Supervisor", referencedColumnName = "Id_Usuario")
@ManyToOne(optional = true, fetch = FetchType.LAZY)
private Usuario supervisor;
// Contructor, Getters Setters etc ...
}
public class TipoUsuario implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Basic(optional = false)
@NotNull
@Size(min = 1, max = 1)
@Column(name = "Id_Tipo_Usuario")
private String idTipoUsuario;
@Basic(optional = false)
@NotNull
@Size(min = 1, max = 20)
@Column(name = "Descricao")
private String descricao;
@Basic(optional = false)
@NotNull
@Size(min = 1, max = 1)
@Column(name = "Possui_Supervisor")
private String possuiSupervisor;
@Size(max = 1)
@Column(name = "Possui_Meta")
private String possuiMeta;
@Size(max = 1)
@Column(name = "Recebe_Alerta")
private String recebeAlerta;
@Transient
private List<Usuario> usuarioList = new ArrayList<>();
//Contructor, Getters Setters etc ...
为什么
使用延迟加载,您是在指示 EntityManager
除非有人要求,否则不要获取这些详细信息。因此,如果在您的交易中,您不要求获取 property
,您将只会获得它的代理。但是,如果您向该代理询问任何与 属性、e.x、EntityManager
相关的信息,on-demand.
看起来您正在为您的视图使用 JSF,现在在这种情况下,在您的模型要求这些细节之前,实体管理器 已经完成了它的工作 因此不知道它必须再次为您从数据库中获取这些详细信息。请记住,代理是序列化的,因此在您看来,您的 collection 看起来像是 null/empty.
如何解决这个问题
正确答案取决于您的使用情况。
如果您当前延迟加载的信息总是需要在前端显示,那么将其延迟加载对您没有任何好处。
否则,如果您需要它仅在有人单击下拉菜单或其他内容时显示,那么您可以使用 Fetch Joins
基于 JPA 查询填充这些值。
否则,如果您有 EJB,您可以考虑扩展 EntityManager
。
每个选项都有很多详细信息,但您可以查看来自 Adam Bien 的 blog post,了解有关上述所有选项的更多详细信息!
更新 1:看看这个 answer 了解如何在服务器端加载延迟加载的属性。
我正在尝试提高使用 JPA 的项目的性能。
我正在使用 JPA 2.1 和 Hibernate 5.0.1 实现。
我将 ManyToOne 关系的 FetchType 更改为 Lazy,所以事情搞砸了。
当我试图查找子对象的所有记录时:最后一条记录带有所有空字段和 handler=JavasistLazyInitializer。这种奇怪的行为会影响使用此对象的字段(如 h:OneSelectMenu)。
如果我删除 FetchType.Lazy 东西恢复正常。
一些印刷品:
第二次打印代码(FetchType.Lazy):
public class Usuario implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "Id_Usuario")
private Integer idUsuario;
// Fields ...
@JoinColumn(name = "Id_Tipo_Logradouro", referencedColumnName = "Id_Tipo_Logradouro", nullable = true)
@ManyToOne(optional = true, fetch = FetchType.LAZY)
private TipoLogradouro tipoLogradouro;
@JoinColumn(name = "Id_Tipo_Usuario", referencedColumnName = "Id_Tipo_Usuario")
@ManyToOne(optional = false, fetch = FetchType.LAZY)
private TipoUsuario tipoUsuario;
@JoinColumn(name = "Id_Supervisor", referencedColumnName = "Id_Usuario")
@ManyToOne(optional = true, fetch = FetchType.LAZY)
private Usuario supervisor;
// Contructor, Getters Setters etc ...
}
public class TipoUsuario implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Basic(optional = false)
@NotNull
@Size(min = 1, max = 1)
@Column(name = "Id_Tipo_Usuario")
private String idTipoUsuario;
@Basic(optional = false)
@NotNull
@Size(min = 1, max = 20)
@Column(name = "Descricao")
private String descricao;
@Basic(optional = false)
@NotNull
@Size(min = 1, max = 1)
@Column(name = "Possui_Supervisor")
private String possuiSupervisor;
@Size(max = 1)
@Column(name = "Possui_Meta")
private String possuiMeta;
@Size(max = 1)
@Column(name = "Recebe_Alerta")
private String recebeAlerta;
@Transient
private List<Usuario> usuarioList = new ArrayList<>();
//Contructor, Getters Setters etc ...
为什么
使用延迟加载,您是在指示 EntityManager
除非有人要求,否则不要获取这些详细信息。因此,如果在您的交易中,您不要求获取 property
,您将只会获得它的代理。但是,如果您向该代理询问任何与 属性、e.x、EntityManager
相关的信息,on-demand.
看起来您正在为您的视图使用 JSF,现在在这种情况下,在您的模型要求这些细节之前,实体管理器 已经完成了它的工作 因此不知道它必须再次为您从数据库中获取这些详细信息。请记住,代理是序列化的,因此在您看来,您的 collection 看起来像是 null/empty.
如何解决这个问题
正确答案取决于您的使用情况。
如果您当前延迟加载的信息总是需要在前端显示,那么将其延迟加载对您没有任何好处。
否则,如果您需要它仅在有人单击下拉菜单或其他内容时显示,那么您可以使用 Fetch Joins
基于 JPA 查询填充这些值。
否则,如果您有 EJB,您可以考虑扩展 EntityManager
。
每个选项都有很多详细信息,但您可以查看来自 Adam Bien 的 blog post,了解有关上述所有选项的更多详细信息!
更新 1:看看这个 answer 了解如何在服务器端加载延迟加载的属性。