无法提交Hibernate事务

时间:2017-11-22 20:04:52

标签: java spring hibernate hibernate-mapping

我是Hibernate的新手。我正在尝试编写一个方法,插入或更新50条记录然后提交它&然后再次继续插入。我这样做是因为如果在插入最后一条记录时发生了某些事情,我想保留数据库中的所有先前记录。

这就是我在做的事情:

view.sendSubviewToBack

这样可以正常工作但在执行此方法后会发生异常。由于这个原因,此方法的返回值从未返回到调用方法。谁能帮我? stacktrace:

@Override
    public boolean updateStoreDetails(List<StoreDetailsDTO> storeDetailsDTOs){
        Session session = this.hibernateSessionFactory.getCurrentSession();
        int count = 0;
        boolean sessionEnded =false;

        for(StoreDetailsDTO storeDetailsDTOTmp : storeDetailsDTOs){
            if(sessionEnded){//At the very beginning, the transaction remains open dont know why. So  session.getTransaction().begin() causing exception
                session.getTransaction().begin();
                sessionEnded = false;
            }
            session.saveOrUpdate(storeDetailsDTOTmp);
            if ( ++count % 10 == 0 ) {      //If batch size is 50 clear session-level cache & to avoid OutOfMemoryException
                  logger.info("Clearing session after 50 batch size. Total rows inserted/updated till now: "+ count);
                  session.getTransaction().commit();
                  session.flush();
                  session.clear();
                  sessionEnded =true;

            } else if(count == storeDetailsDTOs.size()){
               session.getTransaction().commit();
               session.flush();
               session.clear();
            }
        }
        logger.info("Insertion completed. Total rows inserted/updated: "+ count);
        return true;
    }

4 个答案:

答案 0 :(得分:1)

仅当sessionEndedtrue但您仅在true之后将其设置为session.getTransaction().commit()时才会打开会话。更好的解决方案是在循环之外开始和结束会话。

答案 1 :(得分:1)

我已将@Transactional放在班级。我相信这导致了这个问题,虽然我不确定。删除后,我在执行时遇到了一些错误:this.hibernateSessionFactory.getCurrentSession();。我想我必须为此设置一个属性。

无论如何要实现我想要的东西我修改了方法:

@Override
    public boolean updateStoreDetails(List<StoreDetailsDTO> storeDetailsDTOs){
        Session session = this.hibernateSessionFactory.getCurrentSession();
        int count = 0;
        boolean sessionEnded =false;

        for(StoreDetailsDTO storeDetailsDTOTmp : storeDetailsDTOs){         
            session.saveOrUpdate(storeDetailsDTOTmp);
            //session.evict(storeDetailsDTOTmp);
            if ( ++count % 50 == 0 ) {      //If batch size is 50 clear session-level cache & to avoid OutOfMemoryException
                  logger.info("Clearing session after 50 batch size.");               
                  session.flush();
                  session.clear();                
            } 
        }       
        return true;
    }

我在插入50条记录后调用此方法。请注意,在修改方法后,我已在类级别保留@Transactional注释。

感谢大家的帮助!!

答案 2 :(得分:0)

以下是您可以在50条记录之后将记录刷新到DB中的代码,但是在发生故障的情况下提交/回滚所有这些通常是场景但是如果要提交50条记录,则在清除后执行提交。

    public void insert(List<T> items) {

    //begin transaction
    for (int i = 0; i < items.size(); i++) {
        T item = items.get(i);
        session.save(item);
        if (i % 50 == 0) {
            session.flush();
            session.clear();
        }           
    }
    session.flush();
    session.clear();

    //commit transaction
}

答案 3 :(得分:0)

标志检查中存在错误,导致交易无法开始。我做了改变,希望这会有效。

@Override 
public boolean updateStoreDetails(List<StoreDetailsDTO> storeDetailsDTOs)
{ 
Session session = this.hibernateSessionFactory.getCurrentSession(); 
int count = 0; 
boolean sessionEnded =true; for(StoreDetailsDTO storeDetailsDTOTmp : storeDetailsDTOs)
{ 
if(sessionEnded)
{
 session.getTransaction().begin(); sessionEnded = false;
 } session.saveOrUpdate(storeDetailsDTOTmp) ; 
if ( ++count % 10 == 0 ) 
{ 
//If batch size is 50 clear session-level cache & to avoid OutOfMemoryException 
logger.info("Clearing session after 50 batch size. Total rows inserted/updated till now: "+ count);
 session.getTransaction().commit();
 session.flush(); session.clear();
 sessionEnded =true; 
}
 else if(count == storeDetailsDTOs.size()){ 
session.getTransaction().commit();
 session.flush(); 
session.clear(); 
} 
} 
logger.info("Insertion completed. Total rows inserted/updated: "+ count);
 return true;
 }