2014-02-26 142 views
1

我们正在推出一个网站,其短时间内的音量很大。它基本上是给门票。该代码是用Java编写的,Spring Hibernate是Spring的。我想通过产生多个线程来模仿高容量,并试图使用JUnit测试用例来获取票据。问题是,在我的DAO类中,代码只是在我开始交易后死亡。我的意思是在日志文件中没有错误跟踪或类似的东西。让我介绍一下我的代码的方式。Java:在多线程环境中运行事务

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); 
} 

我看到被插入到数据库中的数据。有人能指出我哪里出错了吗?

感谢 拉吉

回答

3

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

+0

我一定会尝试你的建议,并让你知道。谢谢你的建议。 – Raj

+0

就是这样。我已经将你的回答标记为对这个问题的回答。非常感谢大卫。 – Raj

+0

很高兴能帮到你! –

0

淘气,淘气!

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

你永远不应该(很好,几乎没有)有一个空catch块,如果有问题,你会发现你的代码“只是单纯的死”没有日志消息。哦,看,这就是发生了什么;)

在最起码你应该记录异常,这将很大程度上帮助你找到问题是什么(并从那里,解决方案)。

+0

为了简洁,我省略了那段代码。我在异常块中有一个记录器。 – Raj