details:   https://code.openbravo.com/erp/devel/pi/rev/0e3c102ec91e
changeset: 31527:0e3c102ec91e
user:      Asier Lostalé <asier.lostale <at> openbravo.com>
date:      Wed Feb 15 14:13:23 2017 +0100
summary:   fixed issue 20515: OBCriteria creates contention at JVM

  When using OBCriteria for same entity by several concurrent threads, there was
  contention at JVM due to locks in Class.forName(entityName).

  This Class.forName(entityName) always results in ClassNotFoundException 
because
  entityName is not an actual class name. Hibernate criteria can accept either 
an
  entity name or a class name. It has been changed to set class name instead of
  entity so that it finds the class in the classloader cache earlier removing 
contention.

  Note when criteria is used for scrolling, Hibernate's flow is different and it
  expects it to be an entity name, though in this case there's no contention 
because
  class is resolved by internal caches. This is also covered in the fix as 
exceptional
  case.

diffstat:

 src/org/openbravo/dal/service/OBCriteria.java |  33 ++++++++++++++++++++++----
 src/org/openbravo/dal/service/OBDal.java      |   9 ++++---
 2 files changed, 33 insertions(+), 9 deletions(-)

diffs (97 lines):

diff -r 0c31b06dd168 -r 0e3c102ec91e 
src/org/openbravo/dal/service/OBCriteria.java
--- a/src/org/openbravo/dal/service/OBCriteria.java     Thu Feb 16 13:32:25 
2017 +0530
+++ b/src/org/openbravo/dal/service/OBCriteria.java     Wed Feb 15 14:13:23 
2017 +0100
@@ -11,7 +11,7 @@
  * under the License. 
  * The Original Code is Openbravo ERP. 
  * The Initial Developer of the Original Code is Openbravo SLU 
- * All portions are Copyright (C) 2008-2016 Openbravo SLU 
+ * All portions are Copyright (C) 2008-2017 Openbravo SLU 
  * All Rights Reserved. 
  * Contributor(s):  ______________________________________.
  ************************************************************************
@@ -71,6 +71,8 @@
   private boolean initialized = false;
   private boolean modified = false;
 
+  private boolean scrolling = false;
+
   public OBCriteria(String entityOrClassName) {
     super(entityOrClassName, (SessionImplementor) 
SessionHandler.getInstance().getSession());
   }
@@ -123,16 +125,37 @@
    * See the scroll method on the Hibernate Criteria class.
    */
   public ScrollableResults scroll() throws HibernateException {
-    initialize();
-    return super.scroll();
+    scrolling = true;
+    try {
+      initialize();
+      return super.scroll();
+    } finally {
+      scrolling = false;
+    }
   }
 
   /**
    * See the scroll method on the Hibernate Criteria class.
    */
   public ScrollableResults scroll(ScrollMode scrollMode) throws 
HibernateException {
-    initialize();
-    return super.scroll(scrollMode);
+    scrolling = true;
+    try {
+      initialize();
+      return super.scroll(scrollMode);
+    } finally {
+      scrolling = false;
+    }
+  }
+
+  @Override
+  public String getEntityOrClassName() {
+    if (scrolling && entity != null) {
+      // When criteria is used for scrolling, Hibernate expects this method to 
return the entity
+      // name. For listing instead it can accept either entity or implementing 
class name, if entity
+      // name is returned, it performs worse. So return always class name but 
when scrolling.
+      return entity.getName();
+    }
+    return super.getEntityOrClassName();
   }
 
   /**
diff -r 0c31b06dd168 -r 0e3c102ec91e src/org/openbravo/dal/service/OBDal.java
--- a/src/org/openbravo/dal/service/OBDal.java  Thu Feb 16 13:32:25 2017 +0530
+++ b/src/org/openbravo/dal/service/OBDal.java  Wed Feb 15 14:13:23 2017 +0100
@@ -497,7 +497,7 @@
   public <T extends BaseOBObject> OBCriteria<T> createCriteria(Class<T> clz) {
     checkReadAccess(clz);
     final Entity entity = ModelProvider.getInstance().getEntity(clz);
-    final OBCriteria<T> obCriteria = new OBCriteria<T>(entity.getName(),
+    final OBCriteria<T> obCriteria = new OBCriteria<T>(clz.getName(),
         (SessionImplementor) 
SessionHandler.getInstance().getSession(poolName));
     obCriteria.setEntity(entity);
     return obCriteria;
@@ -515,7 +515,7 @@
   public <T extends BaseOBObject> OBCriteria<T> createCriteria(Class<T> clz, 
String alias) {
     checkReadAccess(clz);
     final Entity entity = ModelProvider.getInstance().getEntity(clz);
-    final OBCriteria<T> obCriteria = new OBCriteria<T>(entity.getName(), alias,
+    final OBCriteria<T> obCriteria = new OBCriteria<T>(clz.getName(), alias,
         (SessionImplementor) 
SessionHandler.getInstance().getSession(poolName));
     obCriteria.setEntity(entity);
     return obCriteria;
@@ -530,9 +530,10 @@
    */
   public <T extends BaseOBObject> OBCriteria<T> createCriteria(String 
entityName) {
     checkReadAccess(entityName);
-    final OBCriteria<T> obCriteria = new OBCriteria<T>(entityName,
+    Entity entity = ModelProvider.getInstance().getEntity(entityName);
+    final OBCriteria<T> obCriteria = new 
OBCriteria<T>(entity.getMappingClass().getName(),
         (SessionImplementor) 
SessionHandler.getInstance().getSession(poolName));
-    obCriteria.setEntity(ModelProvider.getInstance().getEntity(entityName));
+    obCriteria.setEntity(entity);
     return obCriteria;
   }
 

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
_______________________________________________
Openbravo-commits mailing list
Openbravo-commits@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openbravo-commits

Reply via email to