我该怎么做才能确保Spring是线程安全的?

时间:2012-12-06 01:57:02

标签: spring hibernate

我可以通过在Spring中配置数据源来了解:

<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
  <property name="jndiName" value="jdbc/dev"/>
  <property name="lookupOnStartup" value="false"/>
  <property name="cache" value="true"/>
  <property name="proxyInterface" value="javax.sql.DataSource"/>
</bean>

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
  <property name="dataSource">
    <ref bean="dataSource"/>
  </property>
  ...
</bean>

在Spring中配置我的BOC和DAO对象:

<bean id="Dao" class="com.dao.impl.DaoImpl">
  <property name="sessionFactory" ref="sessionFactory"/>
</bean>

<bean id="Bo" class="com.bo.impl.BoImpl">
  <property name="theDao">
    <ref local="Dao"/>
  </property>
</bean>

目前我正在测试3个用户,1个成功地将数据插入到数据库中,1个挂起,1个在操作中丢失,这意味着没有响应,Websphere Application Server中没有捕获日志。有3个用户同时使用该应用程序的测试用例失败了,我可以知道当有1000个用户同时使用该应用程序时,我怎么能确保所有这些都是线程安全的?


更新

回应@Adrian Shum查询:

关于BO的事情,我不确定这是什么模式。但我是BOC代表业务对象控制器,拥有这个单元类的目的是将业务逻辑与DAO对象分开。最终这将结束XHTML / JSP是前端,BO是业务控制器,DAO关注hibernate和查询构造。

为了检索会话工厂,每个DAO对象都必须扩展HibernateDaoSupport,这就是Spring-Hibernate Integration根据本教程工作的方式。以下是一些代码段:

class DAO extends HibernateDaoSupport implements IDao {

  public void save( Pojo pojo ) {
    getHibernateTemplate().save(pojo);
  }

  public void update( Pojo pojo ) {
    getHibernateTemplate().update(pojo);
  }

  public void delete( Pojo pojo ) {
    getHibernateTemplate().delete(pojo);
  }
}

我知道Spring对象默认是单例。这是否意味着每个线程只有一个对象,或者整个JVM实例只有一个对象?如果我将这些BO和DAO对象声明为会话范围,如下所示:

<bean id="Dao" class="com.dao.impl.DaoImpl" scope="session">
  <property name="sessionFactory" ref="sessionFactory"/>
</bean>

<bean id="Bo" class="com.bo.impl.BoImpl" scope="session">
  <property name="theDao">
    <ref local="Dao"/>
  </property>
</bean>

关于数据更新或检索,可能会发生这种情况,因为我们正在测试的3个用户是在同一记录上进行的。可能有一个锁,因为我注意到有一个函数正在执行此代码:

Query queryA = session.createQuery("Delete From TableA where fieldA = :theID");
queryA.setParameter("theID", "XX");
queryA.executeUpdate();

Query queryB = session.createQuery("Delete From TableB where fieldB = :theID");
queryB.setParameter("theID", "YY");
queryB.executeUpdate();

// update tableB object
session.save(tableBObj);

// update each tableA object
for(TableAObj obj : TableAObjList) {                
  session.save(obj);
  session.flush();
  session.evict(obj);
}

TableA(从属)和TableB(主)彼此有关系。我知道TableA和TableB之间有一个数据库设计,但这超出了这个问题。我只是好奇这个函数是否会导致并发问题,即使我把这个类作为单例?

2 个答案:

答案 0 :(得分:1)

从您的问题来看,显然线程安全性与Spring无关。

可能有很多地方可能出错,例如:(我真的不知道你的BO意味着什么,因为它似乎不是一个众所周知的模式。我假设你的“用户”将在BO中调​​用方法和BO将调用DAO来执行数据检索工作)

你是如何使用会话工厂的?我希望你没有参加一个会议并继续使用它。如何显示一些关于如何使用它的代码片段会很棒。

如果您的BO是单身人士,它是否会为个人“用户会话”保留任何状态?处理中使用的任何共享对象都不是线程安全的吗?

与DAO相关的问题是数据检索和更新,您是否已完成了避免死锁的工作?例如,函数A将更新表X然后更新表Y,而函数B更新Y然后是X.您是否已完成工作以确保对于2个用户更新相同记录,后者更新将不会以静默方式覆盖前者一个(如果更新不是幂等的。)

导致你的问题可能有很多原因,但我相信其中99.999%与Spring(或Hibernate)无关。

答案 1 :(得分:0)

我解决了问题。这是因为DB2无法通过向表中添加新列来处理并发问题,并将其作为主键。