Java:在多线程环境中运行事务

时间:2014-02-26 03:07:41

标签: multithreading spring hibernate junit executorservice

我们推出的网站在短时间内会有很大的量。它基本上是门票。代码是用Java,Spring和& S编写的。休眠。我想通过生成多个线程并尝试使用JUnit测试用例获取票证来模仿高容量。问题是在我的DAO类中,代码只是在我开始事务后才死掉。我的意思是日志文件中没有错误跟踪或类似的东西。让我谈谈我的代码的方式。

DAO代码:

@Repository("customerTicketDAO")
public class CustomerTicketDAO extends BaseDAOImpl {// BaseDAOImpl extends HibernateDaoSupport

public void saveCustomerTicketUsingJDBC(String customerId) {
  try{
      getSession().getTransaction().begin(); //NOTHING HAPPENS AFTER THIS LINE OF CODE
      // A select query
      Query query1 = getSession().createSQLQuery("my query omitted on purpose");
      .
      .
      // An update query
      Query query2 = getSession().createSQLQuery("my query omitted on purpose");
      getSession().getTransaction().commite();
   } catch (Exception e) {
   }
}

可运行代码:

public class InsertCustomerTicketRunnable implements Runnable {

@Autowired
private CustomerTicketDAO customerTicketDAO;    

 public InsertCustomerTicketRunnable(String customerId) {
    this.customerId = customerId;
}     

 @Override
public void run() {
    if (customerTicketDAO != null) {
        customerTicketDAO.saveCustomerTicketUsingJDBC(customerId); 
    }
}
}

JUnit方法:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"file:src/test/resources/applicationContext-test.xml"})
public class DatabaseTest {
  @Before
public void init() {
    sessionFactory = (SessionFactory)applicationContext.getBean("sessionFactory");
    Session session = SessionFactoryUtils.getSession(sessionFactory, true);
    TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session));

    customerTicketDAO = (CustomerTicketDAO)applicationContext.getBean("customerTicketDAO");
}

@After
public void end() throws Exception {
    SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.unbindResource(sessionFactory);
    SessionFactoryUtils.closeSession(session);
  }

  @Test
public void saveCustomerTicketInMultipleThreads () throws Exception  {
    ExecutorService executor = Executors.newFixedThreadPool(NTHREDS);

    for (int i=0; i<1000; i++) {
        executor.submit(new InsertCustomerTicketRunnable(i));
    }

    // This will make the executor accept no new threads
    // and finish all existing threads in the queue
    executor.shutdown();
    // Wait until all threads are finish
    executor.awaitTermination(1, TimeUnit.SECONDS);
}

我发现没有数据插入数据库。有人可以指出我哪里出错了吗?

由于 拉吉

2 个答案:

答案 0 :(得分:3)

SessionFactory是线程安全的,但Session不是。所以我的猜测是你需要从每个线程中调用SessionFactoryUtils.getSession(),以便每个线程都有自己的实例。您当前正在从主线程调用它,因此所有子线程都尝试共享同一个实例。

答案 1 :(得分:0)

淘气,顽皮!

public void saveCustomerTicketUsingJDBC(String customerId) {
  try {
      getSession().getTransaction().begin(); //NOTHING HAPPENS AFTER THIS LINE OF CODE
      .
      .
   } catch (Exception e) {
   }
}

你永远不应该(好吧,几乎没有)有一个空的catch块,如果有问题,你会发现你的代码'只是简单地死了'没有日志消息。哦,看,这就是发生的事情;)

至少应该记录异常,这将有助于您找到问题所在(以及解决方案)。