Hibernate 在从相关实体中删除时加载 LOBS(不应该是懒惰的)?
Hibernate loads LOBS on deleting from related entity (Shouldn't it be Lazy)?
我有一个使用 JPA 和 Hibernate 进行数据库交互的 Web 应用程序。
有一个通用的 JPA 存储库,一个实体,我现在遇到了问题。
现在调用 delete 方法时,我得到一个 java.lang.OutOfMemoryError: Java heap space 异常。
(它是 deleteByCreatedDateLessThan)。
当表中只有一些条目时(用 20 个进行测试)这工作正常,但对于高达 20.000 的实际负载。
分析转储后发现应用程序正在从数据库加载整个 IbGeneratedData.IbPdf & IbGeneratedData.IbXml(填满了堆的 80%space)。
我怎样才能阻止这个?要删除它,只需检查 ID 即可将其删除 ...
我也在 LOB 上试过 @Basic(fetch=FetchType.LAZY)
。
public interface ResponseRepository extends JpaRepository<IbResponse, String>, JpaSpecificationExecutor<IbResponse> {
@Modifying
void deleteByCreatedDateLessThan(Date maxAgedDate);
Collection<IbResponse> findByOwningUserIdEquals(String id, Sort sort);
}
@Entity(name = "IbResponse")
@Table(name = "IB_RESPONSE")
public class IbResponse implements Serializable {
@Id
@GeneratedValue(generator = "system-uuid")
@GenericGenerator(name = "system-uuid", strategy = "uuid")
@Column(name = "ID")
private String id;
@ManyToOne(fetch = FetchType.LAZY, optional = false, targetEntity = IbUser.class)
@JoinColumn(name = "USER_ID", updatable = false)
private IbUser owningUser;
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "GENERATED_DATA_ID")
private IbGeneratedData generatedData;
...
}
@Entity(name = "IbGeneratedData")
@Table(name = "IB_GENERATED_DATA")
public class IbGeneratedData implements Serializable {
@Id
@GeneratedValue(generator = "system-uuid")
@GenericGenerator(name = "system-uuid", strategy = "uuid")
@Column(name = "ID")
private String id;
@Lob
@Column(name = "PDF")
private byte[] IbPdf;
@Lob
@Column(name = "XML")
private byte[] IbXml;
...
}
Spring-data-jpa: 1.7.0
休眠:4.3.7
运行 在 Oracle 数据库上
1) LAZY
只是对持久性提供者的提示,不是必须的。
2) deleteBy
在 Spring Data Jpa 中的工作方式,根据 JPA 标准是正确的,它首先加载所有实体进入持久性上下文,然后为每个结果调用 delete(entity)
。
解决方案
创建一个更新查询并运行它在一个新事务中 (propagation.REQUIRES_NEW):
@Modifying
@Query("delete from IbResponse i where i.createdDate < :date", )
void deleteByCreatedDateLessThan(@Param("date") Date date);
这将忽略将实体加载到持久性上下文中并执行直接批量删除。
我有一个使用 JPA 和 Hibernate 进行数据库交互的 Web 应用程序。
有一个通用的 JPA 存储库,一个实体,我现在遇到了问题。 现在调用 delete 方法时,我得到一个 java.lang.OutOfMemoryError: Java heap space 异常。 (它是 deleteByCreatedDateLessThan)。
当表中只有一些条目时(用 20 个进行测试)这工作正常,但对于高达 20.000 的实际负载。
分析转储后发现应用程序正在从数据库加载整个 IbGeneratedData.IbPdf & IbGeneratedData.IbXml(填满了堆的 80%space)。
我怎样才能阻止这个?要删除它,只需检查 ID 即可将其删除 ...
我也在 LOB 上试过 @Basic(fetch=FetchType.LAZY)
。
public interface ResponseRepository extends JpaRepository<IbResponse, String>, JpaSpecificationExecutor<IbResponse> {
@Modifying
void deleteByCreatedDateLessThan(Date maxAgedDate);
Collection<IbResponse> findByOwningUserIdEquals(String id, Sort sort);
}
@Entity(name = "IbResponse")
@Table(name = "IB_RESPONSE")
public class IbResponse implements Serializable {
@Id
@GeneratedValue(generator = "system-uuid")
@GenericGenerator(name = "system-uuid", strategy = "uuid")
@Column(name = "ID")
private String id;
@ManyToOne(fetch = FetchType.LAZY, optional = false, targetEntity = IbUser.class)
@JoinColumn(name = "USER_ID", updatable = false)
private IbUser owningUser;
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "GENERATED_DATA_ID")
private IbGeneratedData generatedData;
...
}
@Entity(name = "IbGeneratedData")
@Table(name = "IB_GENERATED_DATA")
public class IbGeneratedData implements Serializable {
@Id
@GeneratedValue(generator = "system-uuid")
@GenericGenerator(name = "system-uuid", strategy = "uuid")
@Column(name = "ID")
private String id;
@Lob
@Column(name = "PDF")
private byte[] IbPdf;
@Lob
@Column(name = "XML")
private byte[] IbXml;
...
}
Spring-data-jpa: 1.7.0
休眠:4.3.7
运行 在 Oracle 数据库上
1) LAZY
只是对持久性提供者的提示,不是必须的。
2) deleteBy
在 Spring Data Jpa 中的工作方式,根据 JPA 标准是正确的,它首先加载所有实体进入持久性上下文,然后为每个结果调用 delete(entity)
。
解决方案
创建一个更新查询并运行它在一个新事务中 (propagation.REQUIRES_NEW):
@Modifying
@Query("delete from IbResponse i where i.createdDate < :date", )
void deleteByCreatedDateLessThan(@Param("date") Date date);
这将忽略将实体加载到持久性上下文中并执行直接批量删除。