I have a question about Hibernate. Should I put a lot of records in my database. In particular I have a list of objects, and for each of these I check if there is a DB, I make an update if there is otherwise save the new object. The problem is that even trying to batch insert entries are slow! I am using spring+hibernate and mysql
Table
Code:
create table `cash_outflow`(
`cashoutflow_id` int(10) unsigned not null ,
`year` varchar(4) not null,
`title_id` varchar(4) not null,
`function_id` varchar(10) default null,
`service_id` varchar(10) default null,
`operation_id` varchar(10) not null,
`preventive` int(255) unsigned,
`final_balance` int(255) unsigned,
primary key(`cashoutflow_id`))engine = InnoDB;
method for insert
Code:
public void insertCashOutflow(List<CashOutflow> result){
// List<CashOutflow> resultUpdate = new ArrayList<CashOutflow>();
List<CashOutflow> resultSave = new ArrayList<CashOutflow>();
int newId=0;
for(CashOutflow data: result){
if(findByIntervento(data.getOperationId(),data.getYear())!=null){
CashOutflow dataDB = findByIntervento(data.getOperationId(),data.getYear());
if(data.getFinalBalance()!=0){
dataDB.setFinalBalance(data.getFinalBalance());
}
if(data.getPreventive()!=0){
dataDB.setPreventive(data.getPreventive());}
getHibernateTemplate().update(dataDB);
// resultUpdate.add(dataDB);
}else{
resultSave.add(data);
}
}
saveCashOutflow(resultSave);
}
batch insert
Code:
public void saveCashOutflow(List<CashOutflow> result){
CashOutflow lastId = findLastId();
int id=0;
if(lastId==null){
id=1;
}else{
id =lastId.getCashOutflowId()+1;}
Session session = getHibernateTemplate().getSessionFactory().openSession();
Transaction tx = session.beginTransaction();
int i=0;
for(CashOutflow cash: result){
cash.setCashOutflowId(id);
session.save(cash);
if( i % 100 == 0 ) { // Same as the JDBC batch size
//flush a batch of inserts and release memory:
session.flush();
session.clear();
}
i++;
id++;
}
tx.commit();
session.close();
}
@Override
public CashOutflow findByIntervento(String operationId,String year) {
List list = getHibernateTemplate().find("from CashOutflow where operationId=? and year=?",operationId,year);
if(list.isEmpty()){
return null;
}else{
return (CashOutflow) list.get(0);
}
}
application context
Code:
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource" />
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<!-- Crea automaticamente il database servendosi delle annotazioni nelle classi nel package domain -->
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.jdbc.batch_size">50</prop>
<prop key="hibernate.cache.use_second_level_cache">false</prop>
<prop key="hibernate.order_inserts">true</prop>
<prop key="hibernate.order_updates">true</prop>
</props>
</property>
<!-- Indicates to Hibernate which package include the classes and the annotations for
the mapping with db -->
<property name="packagesToScan">
<list>
<!-- <value>it.uniroma2.model</value> -->
<value>it.uniroma2.dao</value>
<value>it.uniroma2.domain</value>
</list>
</property>
</bean>
<!-- Bean to admin the transaction in Hibernate -->
<bean id="txManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!-- Tag to use @Transactional funzioni -->
<tx:annotation-driven transaction-manager="txManager" />