有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java编写数据加载器的最佳方法是什么?

我正在使用Spring2.5及其附带的Hibernate。我正在运行Oracle 11g数据库

我已经创建了扩展HibernateTemplate的DAO。现在我想编写一个加载程序,在person表中插入500万行。我用一种简单的方式写了这篇文章,比如从CSV文件中读取一行,将它转换成一个人,保存到表中。继续执行此操作,直到CSV文件为空

问题是大约450000行的堆空间用完了。因此,我将内存大小从1024m增加了一倍,到2048m,现在大约900000行的内存用完了

我读过一些关于关闭Hibernate的查询缓存的文章,但是我没有使用二级缓存,所以我认为这不是问题所在

我读过一些关于JDBC2批处理的文章,但我认为这不适用于hibernate

所以,我想知道关于冬眠是否有一个基本的东西是我遗漏的


共 (3) 个答案

  1. # 1 楼答案

    根据我使用EclipseLink的经验,在插入/更新多个记录时,保持一个事务处于打开状态会导致您所经历的症状

    您正在使用一个EntityManager(某种类型,JPA或Hybernate特定的-它仍然在管理Entity)。它试图在事务的生命周期中将工作集保存在内存中

    一个普遍的解决办法是承诺&;在每N次插入后重新启动事务;对我来说,典型的N是1000


    作为脚注,对于EclipseLink的某些版本(未定义,已经有几年了),刷新/清除会话并没有解决问题

  2. # 2 楼答案

    听上去,由于第一级缓存(Hibernate会话),您的空间不足。您可以定期刷新Hibernate会话以降低内存使用率,并通过每隔几千行提交一次来将工作分解成块,从而避免数据库的事务日志变得太大

    但是使用Hibernate来完成这样的加载任务会很慢,因为JDBC很慢。如果您对环境有一个很好的了解,您对数据量有一个上限,并且您有一个足够大的处理窗口,那么您可以管理,但是,如果您希望它在多个不同的客户端站点中工作,并且希望尽可能减少由于某些客户端站点的加载作业不工作而花费在解决问题上的时间,那么您应该使用数据库的大容量复制工具

    大容量复制方法意味着数据库暂停所有约束检查、索引构建和事务日志记录,而是集中精力尽可能快地将数据导入。因为JDBC没有从数据库中获得任何类似于这种级别的合作,所以它无法与之竞争。在上一个作业中,我们将运行时间超过8小时的JDBC加载程序任务替换为运行时间为20分钟的SQLLoader任务

    您确实牺牲了数据库独立性,但所有数据库都有一个大容量复制工具(因为DBA依赖于它们),因此每个数据库都有一个非常相似的过程,只有您调用的exe和指定文件格式的方式应该更改。通过这种方式,您可以充分利用处理窗口

  3. # 3 楼答案

    老实说,我不会用hibernate来做这个。ORM的设计目的不是将数百万行加载到DBs中。不是说你不能,但这有点像用电钻挖游泳池;你应该用挖掘机,而不是钻头

    在您的情况下,我会使用数据库附带的加载程序将CSV直接加载到DB。如果您不想这样做,是的,批量插入将更加有效。我不认为Hibernate让你很容易做到这一点。如果我是你,我只会使用普通JDBC,或者最多使用SpringJDBC

    如果实体中有复杂的业务逻辑,并且必须使用Hibernate,那么可以按照Richard的建议刷新每N条记录。不过,我会认为这是一个非常糟糕的黑客。