java嵌套事务_Hibernate 事务嵌套问题

问题描述:

现在在做一个多线程的爬虫,爬虫后的数据存入数据库。

使用的Spring SpringMVC Hibernate

但是当数据爬取6万或者8万9万(不定)的时候。会出现以下错误:

org.hibernate.TransactionException: nested transactions not supported

at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.begin(AbstractTransactionImpl.java:152)

at org.hibernate.internal.SessionImpl.beginTransaction(SessionImpl.java:1396)

at sun.reflect.GeneratedMethodAccessor71.invoke(Unknown Source)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

at java.lang.reflect.Method.invoke(Method.java:597)

at org.hibernate.context.internal.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:352)

at $Proxy31.beginTransaction(Unknown Source)

at com.whr.Dao.Impl.WorkDaoImpl.saveWorkList(WorkDaoImpl.java:60)

at com.whr.Spiders.Spider_ZhiLian.getJobs(Spider_ZhiLian.java:119)

at com.whr.Spiders.Spider_ZhiLian.run(Spider_ZhiLian.java:50)

at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)

at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)

at java.lang.Thread.run(Thread.java:619)

从控制台的打印来看,问题是事务嵌套了。

各种代码:

但是我的Dao代码如下:

@Repository

public class WorkDaoImpl implements WorkDao {

@Autowired

@Qualifier("sessionFactory")

private SessionFactory sessionFactory;

public Session getSession()

{

// 事务必须是开启的(Required),否则获取不到

return sessionFactory.getCurrentSession();

}

public List getAllWork() {

String hql = "from Work";

getSession().beginTransaction();

List list = (List) getSession().createQuery(hql).list();

getSession().getTransaction().commit();

return list;

}

public void saveWork(Work work)

{

getSession().save(work);

}

public void updateWork(Work work)

{

getSession().update(work);

getSession().flush();

}

public void deleteWork(Work work)

{

getSession().delete(work);

getSession().flush();

}

public void saveWorkList(List list)

{

Transaction tran = getSession().beginTransaction();

for (Work work : list) {

getSession().save(work);

}

tran.commit();

getSession().close();

}

从这段代码来看并没有进行事务的嵌套。

对问题更为细节的描述:

项目的思路是这样的有一个类叫Spider类(用于爬取数据),这个类实现了Runnable接口。原本计划Service层调用这个类,再在这个类中调用Dao层的东西。然后进行数据存储,然而后来发现多线程的类中并不能注入一个Dao的接口。所以做法是在Spider类的构造函数中加入了一个Dao的参数,在Service注入Spider的时候将Dao作为一个参数传入到Spider中。

这么说可能有点乱,各位见谅了。下面是各个类的代码:

Spider类的实现:

@Component

public class Spider_ZhiLian implements Runnable{

private WorkDao workDao;

private int start;//开始的页码

private int end;//结束的页码

private static Logger logger = Logger.getLogger(Spider_ZhiLian.class);

private CountDownLatch countDownLatch;//计数器,用于统计线程的时间

private WorkType workType;

public Spider_ZhiLian(WorkDao workDao,int start,int end,CountDownLatch countDownLatch,WorkType workType)

{

this.workDao = workDao;

this.end = end;

this.start = start;

this.countDownLatch = countDownLatch;

this.workType = workType;

}

public Spider_ZhiLian()

{

}

public void run() {

// TODO Auto-generated method stub

getJobs();

}

Service层:

private final int THREAD_NUMBER = 8;//开辟多少个线程完成这个任务

private static Logger logger = Logger.getLogger(WorkServiceImpl.class);

@Autowired

private WorkDao workDao;

@Autowired

private TaskExecutor taskExecutor;// 线程池

@Autowired

private Spider_ZhiLian spider_ZhiLian;

public List getAllWork() {

return workDao.getAllWork();

}

public void saveWork(int start, int end, WorkType workType)

{

long startTime= System.currentTimeMillis();//开始时间

int totalPage = end - start;//总共有多少页要解析

int everyThreadPage = totalPage/THREAD_NUMBER;//每个线程分到多少个页面

final CountDownLatch countDownLatch = new CountDownLatch(THREAD_NUMBER);//计数器,倒数到0的时候主线程统计总共用了多少时间

int i = 0;

for(i =0;i

{

this.taskExecutor.execute(new Spider_ZhiLian(workDao,i,i+everyThreadPage,countDownLatch,workType));

//logger.info("从 "+ i+ " 页到 "+ (i+everyThreadPage) +" 页 ");

}

this.taskExecutor.execute(new Spider_ZhiLian(workDao,i,totalPage,countDownLatch,workType));

//logger.info("从 "+ i+ " 页到 "+ totalPage +" 页 ");

try {

countDownLatch.await();

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

//System.out.println("所有线程执行总时间:"+(System.currentTimeMillis()-startTime)/1000+" 秒");

}

还有就是上面的Dao了。

事情就是这样的,还望大家帮忙分析分析是什么问题了。程序刚开始跑的时候没问题,时间长了就会出现最开始说的那个问题。

自己对问题的原因猜测:

由于创建多线程的时候Dao作为一个参数传入的,那么是不是所有的线程都用的同一个Dao的实例呢。如果是的话,那是不是在执行:

Transaction tran = getSession().beginTransaction();

的时候,一个线程的事务已经begin了,另一个线程又来begin所以导致了事务的嵌套呢?

因为这只是自己的一个猜测,也不敢十分肯定,所以特意来问问大家。

能看到这里无论您是否知道解决方法已经很感谢了。

但是还是求帮助啊啊啊啊啊啊啊!!!

先谢谢了!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值