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