假设我有一张包含数百万行的表格.使用JPA,对该表的查询进行迭代的正确方法是什么,这样我就没有包含数百万个对象的所有内存列表?
例如,我怀疑如果表很大,以下内容会爆炸:
List<Model> models = entityManager().createQuery("from Model m", Model.class).getResultList();
for (Model model : models)
{
System.out.println(model.getId());
}
Run Code Online (Sandbox Code Playgroud)
分页(循环和手动更新setFirstResult()/ setMaxResult())真的是最好的解决方案吗?
编辑:我定位的主要用例是一种批处理作业.如果运行需要很长时间,那就没关系了.没有涉及Web客户端; 我只需要为每一行"做一些事情",一次一个(或一些小N).我只是想避免让它们同时存在于内存中.
我正在开发一个使用大型MySQL表的spring应用程序.当加载大表时,我得到一个OutOfMemoryException,因为驱动程序试图将整个表加载到应用程序内存中.
我试过用
statement.setFetchSize(Integer.MIN_VALUE);
Run Code Online (Sandbox Code Playgroud)
但是我打开的每个ResultSet都会挂起close(); 在线查找我发现这是因为它在关闭ResultSet之前尝试加载任何未读的行,但事实并非如此:
ResultSet existingRecords = getTableData(tablename);
try {
while (existingRecords.next()) {
// ...
}
} finally {
existingRecords.close(); // this line is hanging, and there was no exception in the try clause
}
Run Code Online (Sandbox Code Playgroud)
挂起也发生在小表(3行)上,如果我不关闭RecordSet(发生在一个方法中)然后connection.close()挂起.
堆栈跟踪挂起:
SocketInputStream.socketRead0(FileDescriptor,byte [],int,int,int)行:不可用[native method]
SocketInputStream.read(byte [],int,int)行:129
ReadAheadInputStream.fill(int)行:113
ReadAheadInputStream. readFromUnderlyingStreamIfNecessary(byte [],int,int)行:160
ReadAheadInputStream.read(byte [],int,int)行:188
MysqlIO.readFully(InputStream,byte [],int,int)行:2428 MysqlIO.reuseAndReadPacket(Buffer ,int)行:2882
MysqlIO.reuseAndReadPacket(Buffer)行:2871
MysqlIO.checkErrorPacket(int)行:3414
MysqlIO.checkErrorPacket()行:910
MysqlIO.nextRow(Field [],int,boolean,int,boolean,boolean, boolean,Buffer)行:1405
RowDataDynamic.nextRecord()行:413
RowDataDynamic.next()行:392 RowDataDynamic.close()行:170
JDBC4ResultSet(ResultSetImpl).realClose(boolean)行:7473 JDBC4ResultSet(ResultSetImpl).close( )line:881 DelegatingResultSet.close()行:152
DelegatingResultSet.close()行:152
DelegatingPreparedStatement(DelegatingStatement).clo se()行:163
(这是我的类)Database.close()行:84
我试图只获取对象bob的id列表,而不是bob列表.HQL请求没问题,但我知道是否可以使用标准?
一个例子 :
final StringBuilder hql = new StringBuilder();
hql.append( "select bob.id from " )
.append( bob.class.getName() ).append( " bob " )
.append( "where bob.id > 10");
final Query query = session.createQuery( hql.toString() );
return query.list();
Run Code Online (Sandbox Code Playgroud) 我试图使用Hibernate分页查询(PostgreSQL)
我为我的sql查询设置了setFirstResult(0),setMaxResults(20).我的代码如下:
Session session = getSessionFactory().getCurrentSession();
session.beginTransaction();
Query query = session.createQuery("FROM Customers");
query.setFirstResult(0);
query.setMaxResults(20);
List<T> entities = query.list();
session.getTransaction().commit();
Run Code Online (Sandbox Code Playgroud)
但是在查看SQL hibernate日志时,我仍然看到完整的SQL查询:
Hibernate: select customer0_.id as id9_, customer0_.customer_name as dst2_9_, customer0_.addres as dst3_9_ from tbl_customers customer0_
Run Code Online (Sandbox Code Playgroud)
为什么查询Hibernate分页SQL日志时没有LIMIT OFFSET?
有谁知道Hibernate分页机制?
我猜Hibernate将选择所有数据,将数据放入Resultset,然后在Resultset中进行分页,对吧?
下面的代码功能,但Hibernate永远不会放任何对象.调用session.clear()会导致有关获取连接类的异常,并且session.evict(currentObject)在检索下一个对象之前调用也无法释放内存.最终我耗尽了我的堆空间.
检查我的堆转储,StatefulPersistenceContext是指向我的对象的所有引用的垃圾收集器的根.
public class CriteriaReportSource implements JRDataSource {
private ScrollableResults sr;
private Object currentObject;
private Criteria c;
private static final int scrollSize = 10;
private int offset = 1;
public CriteriaReportSource(Criteria c) {
this.c = c;
advanceScroll();
}
private void advanceScroll() {
// ((Session) Main.em.getDelegate()).clear();
this.sr = c.setFirstResult(offset)
.setMaxResults(scrollSize)
.scroll(ScrollMode.FORWARD_ONLY);
offset += scrollSize;
}
public boolean next() {
if (sr.next()) {
currentObject = sr.get(0);
if (sr.isLast()) {
advanceScroll();
}
return true;
}
return false;
}
public …Run Code Online (Sandbox Code Playgroud) 我有以下查询,当我尝试使用 hibernate 执行它时,出现以下异常:
org.hibernate.exception.SQLGrammarException: 无法使用滚动执行查询。
在我的代码中,我滚动了 FORWARD_ONLY。任何人都可以提供一个完美的解决方案。
select * from (SELECT account_no AS accountno,rownum r FROM sc_dcm_postpaid_index WHERE groupid = 'SBG-2012'
and concat(trim(TO_CHAR(bill_date,'MONTH')),concat('-',TO_CHAR(bill_date,'YY')))='JUNE-12'
AND ROWID IN (SELECT MAX(ROWID) AS row_no ; FROM sc_dcm_postpaid_index
WHERE groupid= 'SBG-2012' and concat(trim(TO_CHAR(bill_date,'MONTH')),concat('-',TO_CHAR(bill_date,'YY')))='JUNE-12'
GROUP BY account_no HAVING COUNT (account_no) >= 1 ) ORDER BY account_no)where r >= 11 and r <= 21..
Run Code Online (Sandbox Code Playgroud)
此外,当我将查询更改为
SELECT account_no AS accountno,rownum r FROM sc_dcm_postpaid_index WHERE rownum >= 11 and rownum <= 21 groupid = 'SBG-2012'
and concat(trim(TO_CHAR(bill_date,'MONTH')),concat('-',TO_CHAR(bill_date,'YY')))='JUNE-12'
AND ROWID …Run Code Online (Sandbox Code Playgroud) Hibernate分页问题
我有一个与Hibernate分页有关的问题,并且在某种程度上已经解释了这个问题
使用Hibernate的ScrollableResults慢慢读取9000万条记录
细节
来自应用程序的HQL查询:
Query q = session.createQuery("from RequestDao r order by r.id desc");
q.setFirstResult(0);
q.setMaxResults(50);
Run Code Online (Sandbox Code Playgroud)
查询返回300万条记录,对于分页,我们只设置了50条记录,分页页面非常慢,因为在每次刷新时我们都会调用查询来获取3百万条记录,而我们只设置50条记录.
我的主要问题是
HQL是否总是进入并命中数据库,或者它是否会进入会话或内存以查找数据,如果它每次都进入数据库并获得结果集那么从性能的角度来看它是非常合适的,什么是最好的解决方案来改进它?
在hibernate中使用HQL有一种方法可以查询数据库并首先获取50条记录,然后根据用户的要求获取其他记录.这个挑战真的让应用程序陷入困境,那么解决这个问题的最佳方法是什么呢?
在日志中生成的HQL查询
from com.delta.dao.RequestDao r order by r.id desc
Run Code Online (Sandbox Code Playgroud)
Hibernate生成的查询
select
getrequest0_.ID as ID24_,
getrequest0_.TIME as START3_24_,
getrequest0_.STAT as STATUS24_,
getrequest0_.SUM as SUMMARY24_,
getrequest0_.OUTNAME as OUTPUT7_24_,
getrequest0_.INPNAME as INPUT8_24_,
getrequest0_.REQUEST_DATE as requestT9_24_,
getrequest0_.PARENT_ID as PARENT10_24_,
getrequest0_.INTER_TYPE as INTERPO60_24_,
getrequest0_.OPEN_INT as OPEN61_24_,
getrequest0_.SOURCE_TYPE as SOURCE62_24_,
getrequest0_.TARGET_TYPE as TARGET20_24_,
getrequest0_.SOURCE as SOURCE14_24_,
getrequest0_.COPY_DATA as …Run Code Online (Sandbox Code Playgroud) hibernate ×6
java ×6
jpa ×2
orm ×2
pagination ×2
performance ×2
batch-file ×1
criteria ×1
hql ×1
mysql ×1
spring ×1
streaming ×1