Java 您可以使用JPA和Hibernate在一个事务中进行批量删除吗?
所以,我一直在努力加快数据库的删除过程。我对Hibernate比较陌生,我想知道是否可以在一个事务中执行多个操作 我不太担心事务无法删除,所以回滚所有删除的想法并不困扰我 如果有助于提供表格描述,我也可以这样做。不过,我的想法是,我必须先删除每个for循环内的内容,然后再删除循环外的内容 我的代码Java 您可以使用JPA和Hibernate在一个事务中进行批量删除吗?,java,hibernate,jpa,session,transactions,Java,Hibernate,Jpa,Session,Transactions,所以,我一直在努力加快数据库的删除过程。我对Hibernate比较陌生,我想知道是否可以在一个事务中执行多个操作 我不太担心事务无法删除,所以回滚所有删除的想法并不困扰我 如果有助于提供表格描述,我也可以这样做。不过,我的想法是,我必须先删除每个for循环内的内容,然后再删除循环外的内容 我的代码 private void deleteTrackItems() { Session session = m_databaseConnection.getSession();
private void deleteTrackItems() {
Session session = m_databaseConnection.getSession();
Transaction tx = null;
try {
final List<TrackItem> trackItems = loadAllTrackItemByTrackID(
track.getId(), session);
// Deletes all Track Items for the given track
List<Long> trackItemIds = new ArrayList();
for (TrackItem trackItem : trackItems) {
trackItemIds.add(trackItem.getId());
// this is test code 189 through 214
Set<TrackPoint> trackPoints = trackItem.getTrackPoints();
for (TrackPoint trackPoint : trackPoints) {
// load track
final List<TrackPointDetail> trackPointDetails = loadAllTrackPointDetailByTrackID(
trackPoint.getId(), session);
for (TrackPointDetail trackPointDetail : trackPointDetails) {
// delete track point details
deleteObject(trackPointDetail, session);
}
// delete track point
deleteObject(trackPoint, session);
}
// get the track informations
final Set<TrackInformation> trackInformations = trackItem
.getTrackInformations();
// for each track information
for (TrackInformation trackInformation : trackInformations) {
deleteTrackInformation(trackInformation, session);
}
deleteObject(trackItem, session);
}
}
catch (Exception ex) {
System.out.println(ex);
tx.rollback();
}
finally {
if (session != null) {
session.close();
}
}
}
/**
* @param p_objectToDelete The object to delete
* @param p_session the hibernate session
* @return Returns the {@link Runnable}
*/
protected void deleteObject(Object p_objectToDelete, final Session p_session) {
// get the transaction
final Transaction transaction = p_session.getTransaction();
try {
LOGGER.info("Deleting object: " + p_objectToDelete.getClass());
transaction.begin();
p_session.delete(p_objectToDelete);
transaction.commit();
LOGGER.info("Deleted object: " + p_objectToDelete.getClass());
}
catch (Exception exception) {
transaction.rollback();
LOGGER.error(exception);
}
}
我的另一个批量删除解决方案是使用HibernateSqlQuery,在这里我只获取每个对象的id,将它们存储在一个列表中,然后在一个查询中以这种方式进行批量删除。然而,我觉得当我在(?,,,,,?)列表中查询我的where id时,由于序列扫描,需要花费更多的时间
我觉得应该有一种使用hibernates session.delete()进行批量删除的简单方法。非常感谢您的任何想法。使用Hibernate和JPA执行批量删除的常用方法正是您在上一个解决方案中提出的方法—HQL/JPQL中的批量删除查询
从MyEntity e中删除,其中e.id位于(:id)
这应该是迄今为止最有效的方法,因为Hibernate不需要加载和实例化实体
考虑将批量删除放在它自己的事务方法中,并在其他方法中尽快调用该方法-持久性上下文不会用查询结果更新,因此,您希望防止持久性上下文包含过时的数据。在使用JPA时,有许多方法可以执行批量删除语句 使用JPQL进行批量删除 如果要删除其记录的表映射为一个实体,则可以使用JPQL[
bulk delete
][1]语句,如下所示:
int deleteCount = entityManager.createQuery("""
delete from Post
where
status = :status and
updatedOn <= :validityThreshold
""")
.setParameter("status", PostStatus.SPAM)
.setParameter(
"validityThreshold",
Timestamp.valueOf(
LocalDateTime.now().minusDays(7)
)
)
.executeUpdate();
使用SQL进行批量删除
另一种选择是使用本机SQL执行批量删除语句:
int deleteCount = entityManager.createNativeQuery("""
delete from post
where
status = :status and
updated_on <= :validityThreshold
""")
.setParameter("status", PostStatus.SPAM.ordinal())
.setParameter(
"validityThreshold",
Timestamp.valueOf(
LocalDateTime.now().minusDays(7)
)
)
.executeUpdate();
int deleteCount=entityManager.createNativeQuery(“”)
删
哪里
状态=:状态和
更新了方法的次数吗?我严重怀疑查询方法可能比上面的N+1查询策略花费更长的时间。Hibernate仍然会将实体加载到内存中并处理它们的生命周期事件(级联等)。处理级联将违反服务器端删除上的JPA规范:删除操作仅适用于指定类及其子类的实体。它不会级联到相关实体。
,删除操作还应绕过已加载的实体,但这可能取决于版本或可由H中的设置控制伊比利亚。
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaDelete<T> delete = builder.createCriteriaDelete(postModerateClass);
Root<T> root = delete.from(postModerateClass);
int daysValidityThreshold = (Post.class.isAssignableFrom(postModerateClass)) ? 7 : 3;
delete.where(
builder.and(
builder.equal(
root.get("status"),
PostStatus.SPAM
),
builder.lessThanOrEqualTo(
root.get("updatedOn"),
Timestamp.valueOf(
LocalDateTime
.now()
.minusDays(daysValidityThreshold)
)
)
)
);
int deleteCount = entityManager.createQuery(delete).executeUpdate();
int deleteCount = entityManager.createNativeQuery("""
delete from post
where
status = :status and
updated_on <= :validityThreshold
""")
.setParameter("status", PostStatus.SPAM.ordinal())
.setParameter(
"validityThreshold",
Timestamp.valueOf(
LocalDateTime.now().minusDays(7)
)
)
.executeUpdate();