Hibernate的一級緩存影響。
我們每次保存的東西都會保存在Session緩存中,這就是Hibernate的一級緩存,如果我們一直循環執行save等操作,緩存里東西會越來越多,速度也就越來越慢,服務器一直在循環處理,自然也會增加負載。
這本來就是Hibernate不擅長的地方,而且一級緩存不可以不用,如果我們要保存的數據量十分巨大,那么在程序中執行添加、更新方法時,Session對象自身開辟的一級緩存會不斷消耗,直至OutOfMemoryError (內存溢出異常)。
解決方案
批量插入優化
1、仍舊用Hibernate API來進行批處理,但在一定的量的時候,及時的清除緩存。
1)優化Hibernate,在配置文件中設置hibernate.jdbc.batch_size參數,來指定每次提交SQL的數量。 配置hibernate.jdbc.batch_size參數的原因就是盡量少讀數據庫,hibernate.jdbc.batch_size參數值越大,讀數據庫的次數越少,速度越快。
<!--設置hibernate.jdbc.batch_size參數--> <hibernate-configuration> <session-factory> ......... <property name="hibernate.jdbc.batch_size">50</property> ......... <session-factory> <hibernate-configuration>
2)程序及時清除緩存,即每插入一定量的數據后及時把它們從內部緩存中清除掉,釋放占用的內存
如下代碼:
// 每處理50條清空緩存
session.save(myObject);
if (i%50 == 0) {
session.flush();
session.clear();
}
// 在我的項目中寫法如下:
if (i%50 == 0) {
this.getHibernateTemplate().flush();
this.getHibernateTemplate().clear();
}
2、通過JDBC API來做批量插入,繞過Hibernate API。這個方法性能上是最好的,也是最快的。
由於session.connection()方法已經過時,我們可以通過下面方法獲得Connection連接,但是仍然可以使用的
private Connection getJdbcConnection(){
//1,獲取SessionFactory
SessionFactory factory=super.getHibernateTemplate().getSessionFactory();
//2,獲取數據源
DataSource ds=SessionFactoryUtils.getDataSource(factory);
try {
//3,通過數據源獲取Jdbc連接
return ds.getConnection();
} catch (SQLException e) {
logger.error("Hibernate-->Jdbc時沒有獲取到連接...", e);
}
return null;
}
示例代碼:
String insertSql = "insert into user(name,address) values(?,?)";
Session session = getHibernateTemplate().getSessionFactory().openSession();
Connection conn = session.connection();
PrepareStatement stmt = conn.prepareStatement(insertSql);
// 方式1:自動提交
conn.setAutoCommit(true);
for(int i = 0; i++; i<10000) {
stmt.setString(1, "testName");
stmt.setString(2, "testAddress");
stmt.execute();
}
// 方式2:批量提交
conn.setAutoCommit(false);
for(int i = 0; i++; i<10000) {
stmt.setString(1, "testName");
stmt.setString(2, "testAddress");
stmt.addBatch();
if (i % 100 == 0) {
stmt.executeBatch();
conn.commit();
}
}
stmt.executeBatch();
conn.commit();
// 關閉session
session.close();
批量更新與刪除優化
Hibernate2中,對於批量更新/刪除操作,都是先將符合要求的數據查出來,然后再做更新/刪除操作。這樣一來會占用大量內存,而且海量數據處理的時候性能很低。
而Hibernate3對批量更新/刪除提供了支持,能夠直接執行批量更新或批量刪除語句,無需把被更新或刪除的對象先加載到內存中,類似於JDBC的批量更新/刪除操作。
不過對於循環處理數據更新和刪除場景,建議還是使用JDBC,方法同上:批量插入的方法2。
轉自 : http://youngflying.com/2012/09/14/hibernate-batch-processing/