(首先,这不是我的代码。其次,为了保护有罪的人,我更改了类名以隐藏任何特定于我的雇主的内容,所以如果事情彼此不对应,那就是原因!)。
有人可以帮我解决一个疑问吗?我被要求调查一个完整连接池的问题,这段代码似乎有异味。
我们的日志中有很多关于org.hibernate.SessionException: Session is closed!
以下代码的内容,这些代码使用了表现不佳的连接池。
呼叫通过 Web 服务进入:
1 @Stateless
2 @WebService(name="MyWebService", targetNamespace="http://www.mycompany.com/2010/01/WebService/myWebService")
3 @WebContext(contextRoot="/myContextRoot", secureWSDLAccess=false)
4 public class MyWebService implements IMyWebService {
6 @WebMethod
7 @NotNull
8 public ArrayList<SearchResult> performSearch(ArrayList<String> criteria) {
9 GetAllResponses caller = new GetAllResponses();
10 return caller.doSearch(criteria);
11 }
13 }
GetAllResponses
课程如下:
1 public class GetAllResponses {
2 private static MyHome myHome = new MyHome();
4 public SearchResult doSearch(ArrayList<String> criteria) {
5 return doSearchInternal(criteria.elementAt(0), criteria.elementAt(1));
6 }
8 private SearchResult doSearchInternal(String a, String b) {
9 DataObject info = myHome.findDataObject(a, b);
10 return info.getAsSearchResult();
11 }
12 }
MyHome
如下:
1 @Stateless
2 @Local({MyHomeInterface.class})
3 public class MyHome {
4 private Session session;
6 public DataObject findDataObject(String a, String b) {
7 try {
8 this.session = MyHibernateUtil.getSessionFactory().getCurrentSession();
9 Transaction tx = this.session.beginTransaction();
10 //do stuff with session and return a DataObject
11 } catch (Exception ex) {
12 ex.printStackTrace();
13 } finally {
14 this.session.close();
15 }
16 }
18 public DataObject doAnotherFind(String a, String b) {
19 try {
20 this.session = MyHibernateUtil.getSessionFactory().getCurrentSession();
21 Transaction tx = this.session.beginTransaction();
22 //do stuff with session and return a DataObject
23 } catch (Exception ex) {
24 ex.printStackTrace();
25 } finally {
26 this.session.close();
27 }
28 }
30 }
请注意如何GetAllResponses
将MyHome
类的第 2 行实例化为静态字段,并在第 8 行和第 20 行分配MyHome
该字段。session
根据我对事物的理解,SSBMyHome
不是由 J2EE 服务器(JBoss 4.2.2 GA)管理的,因为它已被实例化为GetAllResponses
类的静态字段,而不是在 JNDI 上查找。因此,两个线程可以同时访问同一个实例MyHome
,并且由于会话存储在字段中session
,第一次调用很容易Session
被另一个调用替换Session
,从而导致各种问题,包括org.hibernate.SessionException: Session is closed!
第 9 行和第 21 行MyHome
(例如,两个线程调用findDataObject
,第一个线程在第二个线程运行第 8 行之后和第 9 行之前运行第 14 行)。
我对么?