如何使用JPA(或至少使用Hibernate)处理大型数据集?

Rom*_*man 18 java performance hibernate jpa java-ee

我需要让我的网络应用程序使用非常庞大的数据集.目前我得到的是OutOfMemoryException或输出1-2分钟.

让我们把它简单,假设我们有在DB 2个表:WorkerWorkLog在第一个约1000列,并在第二个10个000 000行.后期表有几个字段,包括'workerId'和'hoursWorked'字段等.我们需要的是:

  1. 计算每个用户的总工作小时数;

  2. 每个用户的工作时间列表.

纯SQL中每个任务最直接的方法(IMO)是:

1)

select Worker.name, sum(hoursWorked) from Worker, WorkLog 
   where Worker.id = WorkLog.workerId 
   group by Worker.name;

//results of this query should be transformed to Multimap<Worker, Long>
Run Code Online (Sandbox Code Playgroud)

2)

select Worker.name, WorkLog.start, WorkLog.hoursWorked from Worker, WorkLog
   where Worker.id = WorkLog.workerId;

//results of this query should be transformed to Multimap<Worker, Period>
//if it was JDBC then it would be vitally 
//to set resultSet.setFetchSize (someSmallNumber), ~100
Run Code Online (Sandbox Code Playgroud)

所以,我有两个问题:

  1. 如何使用JPA(或至少使用Hibernate)实现我的每个方法;
  2. 你会如何处理这个问题(当然有JPA或Hibernate)?

Pas*_*ent 18

假设我们在DB中有2个表:Worker和WorkLog在第一个中有大约1000行,在第二个中有10 000 000行

对于像这样的高容量,我的建议是使用来自Hibernate StatelessSession接口:

或者,Hibernate提供了一个面向命令的API,可用于以分离对象的形式将数据流入和流出数据库.A StatelessSession没有与之关联的持久性上下文,也没有提供许多更高级别的生命周期语义.特别是,无状态会话不实现第一级缓存,也不与任何第二级或查询缓存交互.它不实现事务性后写或自动脏检查.使用无状态会话执行的操作永远不会级联到关联的实例.无状态会话将忽略集合.通过无状态会话执行的操作绕过Hibernate的事件模型和拦截器.由于缺少第一级缓存,无状态会话容易受到数据别名影响.无状态会话是一种更低级别的抽象,更接近底层JDBC.

StatelessSession session = sessionFactory.openStatelessSession();
Transaction tx = session.beginTransaction();

ScrollableResults customers = session.getNamedQuery("GetCustomers")
    .scroll(ScrollMode.FORWARD_ONLY);
while ( customers.next() ) {
    Customer customer = (Customer) customers.get(0);
    customer.updateStuff(...);
    session.update(customer);
}

tx.commit();
session.close();
Run Code Online (Sandbox Code Playgroud)

在此代码示例中,Customer 查询返回的实例将立即分离.它们永远不会与任何持久化上下文相关联.

接口定义的insert(), update()delete()操作 StatelessSession被视为直接数据库行级操作.它们导致立即执行SQL INSERT, UPDATEDELETE 分别执行 .他们有不同的语义的save(), saveOrUpdate()delete() 操作由定义的Session 接口.