From ad0e085ff5e163910665ad09da0b99c822e42d9a Mon Sep 17 00:00:00 2001 From: Rob Bygrave Date: Thu, 8 Dec 2016 23:23:19 +1300 Subject: [PATCH] #915 - Refactor internals - Change update plan to string key --- .../avaje/ebean/bean/EntityBeanIntercept.java | 24 ++++++++++--------- .../ebeaninternal/api/SpiUpdatePlan.java | 4 ++-- .../server/core/PersistRequestBean.java | 14 +++++------ .../server/deploy/BeanDescriptor.java | 6 ++--- .../server/persist/dml/UpdateMeta.java | 2 +- .../server/persist/dml/UpdatePlan.java | 22 +++++++---------- 6 files changed, 34 insertions(+), 38 deletions(-) diff --git a/src/main/java/com/avaje/ebean/bean/EntityBeanIntercept.java b/src/main/java/com/avaje/ebean/bean/EntityBeanIntercept.java index 2ff325daa..359fd794d 100644 --- a/src/main/java/com/avaje/ebean/bean/EntityBeanIntercept.java +++ b/src/main/java/com/avaje/ebean/bean/EntityBeanIntercept.java @@ -696,40 +696,42 @@ public final class EntityBeanIntercept implements Serializable { /** * Return a dirty property hash taking into account embedded beans. */ - public int getDirtyPropertyHash() { - return addDirtyPropertyHash(37); + public StringBuilder getDirtyPropertyKey() { + StringBuilder sb = new StringBuilder(); + addDirtyPropertyKey(sb); + return sb; } /** * Add and return a dirty property hash recursing into embedded beans. */ - public int addDirtyPropertyHash(int hash) { + private void addDirtyPropertyKey(StringBuilder sb) { int len = getPropertyLength(); for (int i = 0; i < len; i++) { if (changedProps != null && changedProps[i]) { - // the property has been changed on this bean - hash = hash * 31 + (i + 1); + sb.append(i).append(','); } else if (embeddedDirty != null && embeddedDirty[i]) { // an embedded property has been changed - recurse EntityBean embeddedBean = (EntityBean) owner._ebean_getField(i); - hash = hash * 31 + embeddedBean._ebean_getIntercept().addDirtyPropertyHash(hash); + sb.append(i).append('['); + embeddedBean._ebean_getIntercept().addDirtyPropertyKey(sb); + sb.append(']'); } } - return hash; } /** * Return a loaded property hash. */ - public int getLoadedPropertyHash() { - int hash = 37; + public StringBuilder getLoadedPropertyKey() { + StringBuilder sb = new StringBuilder(); int len = getPropertyLength(); for (int i = 0; i < len; i++) { if (isLoadedProperty(i)) { - hash = hash * 31 + (i + 1); + sb.append(i).append(','); } } - return hash; + return sb; } /** diff --git a/src/main/java/com/avaje/ebeaninternal/api/SpiUpdatePlan.java b/src/main/java/com/avaje/ebeaninternal/api/SpiUpdatePlan.java index 1f634a33f..0d5b8a78a 100644 --- a/src/main/java/com/avaje/ebeaninternal/api/SpiUpdatePlan.java +++ b/src/main/java/com/avaje/ebeaninternal/api/SpiUpdatePlan.java @@ -41,12 +41,12 @@ public interface SpiUpdatePlan { /** * Return the time this plan was last used. */ - Long getTimeLastUsed(); + long getTimeLastUsed(); /** * Return the hash key for this plan. */ - Integer getKey(); + String getKey(); /** * Return the concurrency mode for this plan. diff --git a/src/main/java/com/avaje/ebeaninternal/server/core/PersistRequestBean.java b/src/main/java/com/avaje/ebeaninternal/server/core/PersistRequestBean.java index a67c0562e..50f4f9cdd 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/core/PersistRequestBean.java +++ b/src/main/java/com/avaje/ebeaninternal/server/core/PersistRequestBean.java @@ -1020,27 +1020,27 @@ public final class PersistRequestBean extends PersistRequest implements BeanP /** * Return the key for an update persist request. */ - public int getUpdatePlanHash() { + public String getUpdatePlanHash() { - int hash; + StringBuilder key; if (determineUpdateAllLoadedProperties()) { - hash = intercept.getLoadedPropertyHash(); + key = intercept.getLoadedPropertyKey(); } else { - hash = intercept.getDirtyPropertyHash(); + key = intercept.getDirtyPropertyKey(); } BeanProperty versionProperty = beanDescriptor.getVersionProperty(); if (versionProperty != null) { if (intercept.isLoadedProperty(versionProperty.getPropertyIndex())) { - hash = hash * 92821 + 7; + key.append('v'); } } if (publish) { - hash = hash * 92821; + key.append('p'); } - return hash; + return key.toString(); } /** diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptor.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptor.java index 2d94052d7..360a8e41a 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptor.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptor.java @@ -101,7 +101,7 @@ public class BeanDescriptor implements MetaBeanInfo, BeanType { private static final Logger logger = LoggerFactory.getLogger(BeanDescriptor.class); - private final ConcurrentHashMap updatePlanCache = new ConcurrentHashMap<>(); + private final ConcurrentHashMap updatePlanCache = new ConcurrentHashMap<>(); private final ConcurrentHashMap queryPlanCache = new ConcurrentHashMap<>(); @@ -1447,14 +1447,14 @@ public class BeanDescriptor implements MetaBeanInfo, BeanType { /** * Get a UpdatePlan for a given hash. */ - public SpiUpdatePlan getUpdatePlan(Integer key) { + public SpiUpdatePlan getUpdatePlan(String key) { return updatePlanCache.get(key); } /** * Add a UpdatePlan to the cache with a given hash. */ - public void putUpdatePlan(Integer key, SpiUpdatePlan plan) { + public void putUpdatePlan(String key, SpiUpdatePlan plan) { updatePlanCache.put(key, plan); } diff --git a/src/main/java/com/avaje/ebeaninternal/server/persist/dml/UpdateMeta.java b/src/main/java/com/avaje/ebeaninternal/server/persist/dml/UpdateMeta.java index 2d5680599..1e29dacda 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/persist/dml/UpdateMeta.java +++ b/src/main/java/com/avaje/ebeaninternal/server/persist/dml/UpdateMeta.java @@ -104,7 +104,7 @@ public final class UpdateMeta { private SpiUpdatePlan getDynamicUpdatePlan(PersistRequestBean persistRequest) { - int key = persistRequest.getUpdatePlanHash(); + String key = persistRequest.getUpdatePlanHash(); // check if we can use a cached UpdatePlan BeanDescriptor beanDescriptor = persistRequest.getBeanDescriptor(); diff --git a/src/main/java/com/avaje/ebeaninternal/server/persist/dml/UpdatePlan.java b/src/main/java/com/avaje/ebeaninternal/server/persist/dml/UpdatePlan.java index 012548a7e..404dfaa1b 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/persist/dml/UpdatePlan.java +++ b/src/main/java/com/avaje/ebeaninternal/server/persist/dml/UpdatePlan.java @@ -12,7 +12,7 @@ import java.sql.SQLException; */ public class UpdatePlan implements SpiUpdatePlan { - private final Integer key; + private final String key; private final ConcurrencyMode mode; @@ -24,21 +24,19 @@ public class UpdatePlan implements SpiUpdatePlan { private final boolean emptySetClause; - private Long timeLastUsed; + private long timeLastUsed; /** * Create a non cached UpdatePlan. */ - public UpdatePlan(ConcurrencyMode mode, String sql, Bindable set) { - + UpdatePlan(ConcurrencyMode mode, String sql, Bindable set) { this(null, mode, sql, set); } /** * Create a UpdatePlan with a given key. */ - public UpdatePlan(Integer key, ConcurrencyMode mode, String sql, Bindable set) { - + UpdatePlan(String key, ConcurrencyMode mode, String sql, Bindable set) { this.emptySetClause = (sql == null); this.key = key; this.mode = mode; @@ -55,10 +53,8 @@ public class UpdatePlan implements SpiUpdatePlan { * Run the prepared statement binding for the 'update set' properties. */ public void bindSet(DmlHandler bind, EntityBean bean) throws SQLException { - set.dmlBind(bind, bean); - - // not strictly 'thread safe' but object assignment is atomic + // atomic on 64 bit jvm this.timeLastUsed = System.currentTimeMillis(); } @@ -72,16 +68,14 @@ public class UpdatePlan implements SpiUpdatePlan { /** * Return the time this plan was last used. */ - public Long getTimeLastUsed() { - - // not thread safe but atomic + public long getTimeLastUsed() { return timeLastUsed; } /** - * Return the hash key. + * Return the key. */ - public Integer getKey() { + public String getKey() { return key; }