1

在使用 Hibernate 插入数据的同时截断表是否可以?

我们将具有许多关系的大型 XML 文件解析为 Hibernate POJO 并持久保存到数据库中。

我们现在计划通过截断表在某些时间点清除现有数据。这个可以吗?

似乎工作正常。我们不使用 Hibernate 的二级缓存。我确实注意到的一件事很好,那就是在插入时,我们使用 Hibernate 生成主键@GeneratedValue,其中 Hibernate 只使用比表中的最大值大一的键值 - 即使我们截断表,Hibernate 也会记住先前的value 并使用先前的 value + 1 而不是从 1 重新开始。这很好,只是出乎意料。

请注意,我们截断而不是调用delete()Hibernate POJO 的原因是为了速度。我们有数以百万计的数据行,而 truncate 的速度要快得多。

4

2 回答 2

3

我们现在计划通过截断表在某些时间点清除现有数据。这个可以吗?

如果您没有使用二级缓存并且没有从表中加载实体,您将在 Session 中截断,则以下内容应该有效(假设它不会破坏完整性约束):

Session s = sf.openSession();
PreparedStatement ps = s.connection().prepareStatement("TRUNCATE TABLE XXX");
ps.executeUpdate();

之后,您应该能够在同一个事务或另一个事务中持久化实体。

当然,如果这很重要,这样的 TRUNCATE 不会生成任何 Hibernate事件或触发任何回调。

(...) 插入时我们使用 Hibernate 的@GeneratedValue(...)

如果您使用(ie ) 的默认strategy值,那么它应该默认为 Oracle 的序列,并且如果您截断表或删除记录,则不会重置序列。@GeneratedValueAUTO


我们截断像 jdbcTemplate.execute("TRUNCATE TABLE abc") 这样的表

这应该是等效的(您最终将使用与 Hibernate 相同的底层 JDBC 连接)。

Hibernate 将使用什么序列进行插入?

"hibernate_sequence"AFAIK,如果您不声明自己的,Hibernate 会为您生成默认序列。

我以为它只是在桌子上做一个 max(field) + 1 ?

不这么认为,而且 Hibernate 不会在 1 之后从 1 重新开始这一事实TRUNCATE似乎证实了它没有。我建议激活 SQL 日志记录以查看在 INSERT 上针对您的数据库执行的确切语句。

我们指定的生成器@GeneratedValue只是一个“虚拟”生成器(不对应于我们创建的任何序列)。

我不是 100% 确定,但如果你没有声明任何@SequenceGenerator(或@TableGenerator),我认为指定生成器不会改变什么。

于 2010-05-25T18:59:57.107 回答
0

取决于您的应用程序。如果删除数据库中的行是好的,那么 truncate 也是好的。

只要您的实体上没有任何 Pre- 或 PostRemove 侦听器,应该没有问题。

另一方面......是否有可能在截断时仍然在 EntityManager 中加载实体,或者这是一个只写表(如日志表)。在这种情况下,您根本不会有任何问题。

于 2010-05-25T18:52:23.867 回答