Session.Save 是否正在向数据库发送请求?
Is Session.Save sending a request to the database?
我必须提高一个非常慢的代码的性能,而且我是 Hibernate 的新手。我仔细研究了代码并得出结论,问题在于它有大量实体要加载和 update
/insert
。为了将算法转换为更易于理解的示例,假设我们有这样一个算法:
for each competitionToSave in competitionsToSave
competition <- load a Competition by competitionToSave from database
winner <- load Person by competitionToSave.personID
do some preprocessing
if (newCompetition) then
insert competition
else
update competition
end if
end for
当competitionToSave
中有很多competition
时,这个算法当然是有问题的。所以,我的计划是select所有涉及到两个数据库请求最多的competition
s和winner
s,预处理数据,这将加快读取速度,但更重要的是,确保我将通过 insert
/update
批次保存 100 competition
s 而不是单独保存它们。由于我是 Hibernate 的新手,我查阅了 documentation 并找到了以下示例:
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
for ( int i=0; i<100000; i++ ) {
Customer customer = new Customer(.....);
session.save(customer);
if ( i % 20 == 0 ) { //20, same as the JDBC batch size
//flush a batch of inserts and release memory:
session.flush();
session.clear();
}
}
tx.commit();
session.close();
但是,我不确定我是否理解正确。关于方法 .save() 我看了:
Persist the given transient instance, first assigning a generated
identifier. (Or using the current value of the identifier property if
the assigned generator is used.) This operation cascades to associated
instances if the association is mapped with cascade="save-update".
但我不清楚是否每隔 save
就向数据库发送一次请求。如果我假设在取自文档的示例中 session.save(customer)
将对象的修改保存在 Session
中而不 向数据库发送请求并且然后在每第 20 个项目上 session.flush()
向数据库发送请求并且 session.clear()
删除 Session
?
的缓存
你的假设是正确的,尽管插入将被一个接一个地触发:
insert into Customer(id , name) values (1, 'na1');
insert into Customer(id , name) values (2, 'na2');
insert into Customer(id , name) values (3, 'na3');
您可以尝试利用批量插入功能来进一步提高性能。
有 hibernate 属性,您可以将其定义为 hibernate 的属性之一 SessionFactory
:
<property name="jdbc.batch_size">20</property>
使用这个批处理设置,每次刷新后你应该有这样的输出:
insert into Customer(id , name) values (1, 'na1') , (2, 'na2') ,(3, 'na3')..
一个插入而不是二十个。
我必须提高一个非常慢的代码的性能,而且我是 Hibernate 的新手。我仔细研究了代码并得出结论,问题在于它有大量实体要加载和 update
/insert
。为了将算法转换为更易于理解的示例,假设我们有这样一个算法:
for each competitionToSave in competitionsToSave
competition <- load a Competition by competitionToSave from database
winner <- load Person by competitionToSave.personID
do some preprocessing
if (newCompetition) then
insert competition
else
update competition
end if
end for
当competitionToSave
中有很多competition
时,这个算法当然是有问题的。所以,我的计划是select所有涉及到两个数据库请求最多的competition
s和winner
s,预处理数据,这将加快读取速度,但更重要的是,确保我将通过 insert
/update
批次保存 100 competition
s 而不是单独保存它们。由于我是 Hibernate 的新手,我查阅了 documentation 并找到了以下示例:
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
for ( int i=0; i<100000; i++ ) {
Customer customer = new Customer(.....);
session.save(customer);
if ( i % 20 == 0 ) { //20, same as the JDBC batch size
//flush a batch of inserts and release memory:
session.flush();
session.clear();
}
}
tx.commit();
session.close();
但是,我不确定我是否理解正确。关于方法 .save() 我看了:
Persist the given transient instance, first assigning a generated identifier. (Or using the current value of the identifier property if the assigned generator is used.) This operation cascades to associated instances if the association is mapped with cascade="save-update".
但我不清楚是否每隔 save
就向数据库发送一次请求。如果我假设在取自文档的示例中 session.save(customer)
将对象的修改保存在 Session
中而不 向数据库发送请求并且然后在每第 20 个项目上 session.flush()
向数据库发送请求并且 session.clear()
删除 Session
?
你的假设是正确的,尽管插入将被一个接一个地触发:
insert into Customer(id , name) values (1, 'na1');
insert into Customer(id , name) values (2, 'na2');
insert into Customer(id , name) values (3, 'na3');
您可以尝试利用批量插入功能来进一步提高性能。
有 hibernate 属性,您可以将其定义为 hibernate 的属性之一 SessionFactory
:
<property name="jdbc.batch_size">20</property>
使用这个批处理设置,每次刷新后你应该有这样的输出:
insert into Customer(id , name) values (1, 'na1') , (2, 'na2') ,(3, 'na3')..
一个插入而不是二十个。