Session.Save отправляет запрос в базу данных?
Мне нужно улучшить производительность очень медленного кода, и я довольно новичок в 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
Этот алгоритм, конечно, проблематичен, когда есть много competition
в competitionToSave
, Итак, мой план состоит в том, чтобы выбрать все competition
с и winner
больше всего задействовано в двух запросах к базе данных - данные предварительной обработки, которые ускорят чтение, но, что более важно, гарантируют, что я сохраню через insert
/update
партии из 100 competition
s вместо того, чтобы сохранять их отдельно. Поскольку я довольно новичок в Hibernate, я ознакомился с документацией и нашел следующий пример:
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() я прочитал:
Сохраните данный временный экземпляр, сначала назначив сгенерированный идентификатор. (Или используя текущее значение свойства идентификатора, если используется назначенный генератор.) Эта операция распространяется каскадно на связанные экземпляры, если сопоставление отображается с помощью cascade="save-update".
Но мне неясно, отправляется ли запрос в базу данных при каждом save
, Я точен, если я предполагаю, что в примере, взятом из документации session.save(customer)
сохраняет модификацию объекта в Session
без отправки запроса в базу данных, а затем на каждый 20-й пункт session.flush()
отправляет запрос в базу данных и session.clear()
удаляет кеш Session
?
1 ответ
Вы правы в своих предположениях, хотя вставки будут срабатывать один за другим:
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')..
Одна вставка вместо двадцати.