From 2a58b954e904e94203ae9148bc5e7db8a19a07ad Mon Sep 17 00:00:00 2001 From: rob bygrave Date: Fri, 4 Aug 2017 21:16:14 +1200 Subject: [PATCH] #1062 - Multi-tenant - Update statements should include tenantId in where clause --- .../server/core/PersistRequestBean.java | 17 +++++++++----- .../server/deploy/BeanDescriptor.java | 7 ++++++ .../server/persist/dml/DeleteMeta.java | 21 ++++++++++-------- .../server/persist/dml/MetaFactory.java | 20 ++++++++--------- .../server/persist/dml/UpdateMeta.java | 22 +++++++++++-------- .../persist/dmlbind/FactoryVersion.java | 13 +++++++---- 6 files changed, 63 insertions(+), 37 deletions(-) diff --git a/src/main/java/io/ebeaninternal/server/core/PersistRequestBean.java b/src/main/java/io/ebeaninternal/server/core/PersistRequestBean.java index 87fcec300..ea1fddc07 100644 --- a/src/main/java/io/ebeaninternal/server/core/PersistRequestBean.java +++ b/src/main/java/io/ebeaninternal/server/core/PersistRequestBean.java @@ -524,7 +524,7 @@ public final class PersistRequestBean extends PersistRequest implements BeanP /** * Prepare the update after potential modifications in a BeanPersistController. */ - public void postControllerPrepareUpdate() { + private void postControllerPrepareUpdate() { if (intercept.isNew() && controller != null) { // 'stateless update' - set dirty properties modified in controller preUpdate intercept.setNewBeanForUpdate(); @@ -1072,31 +1072,38 @@ public final class PersistRequestBean extends PersistRequest implements BeanP return version; } - public void executeInsert() { + private void setTenantId() { Object tenantId = transaction.getTenantId(); if (tenantId != null) { beanDescriptor.setTenantId(entityBean, tenantId); } + } + + private void executeInsert() { + setTenantId(); if (controller == null || controller.preInsert(this)) { beanManager.getBeanPersister().insert(this); } } - public void executeUpdate() { + private void executeUpdate() { + setTenantId(); if (controller == null || controller.preUpdate(this)) { postControllerPrepareUpdate(); beanManager.getBeanPersister().update(this); } } - public void executeSoftDelete() { + private void executeSoftDelete() { + setTenantId(); if (controller == null || controller.preSoftDelete(this)) { postControllerPrepareUpdate(); beanManager.getBeanPersister().update(this); } } - public int executeDelete() { + private int executeDelete() { + setTenantId(); if (controller == null || controller.preDelete(this)) { return beanManager.getBeanPersister().delete(this); } diff --git a/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptor.java b/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptor.java index cb4ec872a..f3740e1b5 100644 --- a/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptor.java +++ b/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptor.java @@ -3014,6 +3014,13 @@ public class BeanDescriptor implements MetaBeanInfo, BeanType { return versionProperty; } + /** + * Return the tenant property when multi-tenant partitioning support is used. + */ + public BeanProperty getTenantProperty() { + return tenant; + } + /** * Scalar properties without the unique id or secondary table properties. */ diff --git a/src/main/java/io/ebeaninternal/server/persist/dml/DeleteMeta.java b/src/main/java/io/ebeaninternal/server/persist/dml/DeleteMeta.java index 20b0bc14c..63f1a0d09 100644 --- a/src/main/java/io/ebeaninternal/server/persist/dml/DeleteMeta.java +++ b/src/main/java/io/ebeaninternal/server/persist/dml/DeleteMeta.java @@ -21,18 +21,19 @@ public final class DeleteMeta { private final String sqlDraftNone; private final BindableId id; - private final Bindable version; + private final Bindable tenantId; private final String tableName; private final boolean emptyStringAsNull; - public DeleteMeta(boolean emptyStringAsNull, BeanDescriptor desc, BindableId id, Bindable version) { + DeleteMeta(boolean emptyStringAsNull, BeanDescriptor desc, BindableId id, Bindable version, Bindable tenantId) { this.emptyStringAsNull = emptyStringAsNull; this.tableName = desc.getBaseTable(); this.id = id; this.version = version; + this.tenantId = tenantId; String tableName = desc.getBaseTable(); this.sqlNone = genSql(ConcurrencyMode.NONE, tableName); @@ -48,7 +49,7 @@ public final class DeleteMeta { } } - public boolean isEmptyStringAsNull() { + boolean isEmptyStringAsNull() { return emptyStringAsNull; } @@ -67,6 +68,9 @@ public final class DeleteMeta { EntityBean bean = persist.getEntityBean(); id.dmlBind(bind, bean); + if (tenantId != null) { + tenantId.dmlBind(bind, bean); + } switch (persist.getConcurrencyMode()) { case VERSION: @@ -102,21 +106,20 @@ public final class DeleteMeta { private String genSql(ConcurrencyMode conMode, String table) { - // delete ... where bcol=? and bc1=? and bc2 is null and ... - GenerateDmlRequest request = new GenerateDmlRequest(); - request.append("delete from ").append(table); request.append(" where "); request.setWhereIdMode(); id.dmlAppend(request); + if (tenantId != null) { + tenantId.dmlAppend(request); + } if (ConcurrencyMode.VERSION.equals(conMode)) { - if (version == null) { - return null; + if (version != null) { + version.dmlAppend(request); } - version.dmlAppend(request); } return request.toString(); diff --git a/src/main/java/io/ebeaninternal/server/persist/dml/MetaFactory.java b/src/main/java/io/ebeaninternal/server/persist/dml/MetaFactory.java index 287dc9350..672a70db5 100644 --- a/src/main/java/io/ebeaninternal/server/persist/dml/MetaFactory.java +++ b/src/main/java/io/ebeaninternal/server/persist/dml/MetaFactory.java @@ -39,7 +39,7 @@ public class MetaFactory { private final boolean emptyStringAsNull; - public MetaFactory(DatabasePlatform dbPlatform) { + MetaFactory(DatabasePlatform dbPlatform) { this.dbPlatform = dbPlatform; this.emptyStringAsNull = dbPlatform.isTreatEmptyStringsAsNull(); @@ -54,7 +54,7 @@ public class MetaFactory { /** * Create the UpdateMeta for the given bean type. */ - public UpdateMeta createUpdate(BeanDescriptor desc) { + UpdateMeta createUpdate(BeanDescriptor desc) { List setList = new ArrayList<>(); @@ -63,30 +63,30 @@ public class MetaFactory { assocOneFact.create(setList, desc, DmlMode.UPDATE); BindableId id = idFact.createId(desc); - - Bindable ver = versionFact.create(desc); + Bindable version = versionFact.create(desc); + Bindable tenantId = versionFact.createTenantId(desc); BindableList setBindable = new BindableList(setList); - return new UpdateMeta(emptyStringAsNull, desc, setBindable, id, ver); + return new UpdateMeta(emptyStringAsNull, desc, setBindable, id, version, tenantId); } /** * Create the DeleteMeta for the given bean type. */ - public DeleteMeta createDelete(BeanDescriptor desc) { + DeleteMeta createDelete(BeanDescriptor desc) { BindableId id = idFact.createId(desc); + Bindable version = versionFact.create(desc); + Bindable tenantId = versionFact.createTenantId(desc); - Bindable ver = versionFact.create(desc); - - return new DeleteMeta(emptyStringAsNull, desc, id, ver); + return new DeleteMeta(emptyStringAsNull, desc, id, version, tenantId); } /** * Create the InsertMeta for the given bean type. */ - public InsertMeta createInsert(BeanDescriptor desc) { + InsertMeta createInsert(BeanDescriptor desc) { BindableId id = idFact.createId(desc); diff --git a/src/main/java/io/ebeaninternal/server/persist/dml/UpdateMeta.java b/src/main/java/io/ebeaninternal/server/persist/dml/UpdateMeta.java index 29afa8a69..f86d969e3 100644 --- a/src/main/java/io/ebeaninternal/server/persist/dml/UpdateMeta.java +++ b/src/main/java/io/ebeaninternal/server/persist/dml/UpdateMeta.java @@ -22,6 +22,7 @@ public final class UpdateMeta { private final BindableList set; private final BindableId id; private final Bindable version; + private final Bindable tenantId; private final String tableName; @@ -30,12 +31,13 @@ public final class UpdateMeta { private final boolean emptyStringAsNull; - public UpdateMeta(boolean emptyStringAsNull, BeanDescriptor desc, BindableList set, BindableId id, Bindable version) { + UpdateMeta(boolean emptyStringAsNull, BeanDescriptor desc, BindableList set, BindableId id, Bindable version, Bindable tenantId) { this.emptyStringAsNull = emptyStringAsNull; this.tableName = desc.getBaseTable(); this.set = set; this.id = id; this.version = version; + this.tenantId = tenantId; String sqlNone = genSql(ConcurrencyMode.NONE, set, desc.getBaseTable()); String sqlVersion = genSql(ConcurrencyMode.VERSION, set, desc.getBaseTable()); @@ -47,7 +49,7 @@ public final class UpdateMeta { /** * Return true if empty strings should be treated as null. */ - public boolean isEmptyStringAsNull() { + boolean isEmptyStringAsNull() { return emptyStringAsNull; } @@ -68,6 +70,9 @@ public final class UpdateMeta { updatePlan.bindSet(bind, bean); id.dmlBind(bind, bean); + if (tenantId != null) { + tenantId.dmlBind(bind, bean); + } switch (persist.getConcurrencyMode()) { case VERSION: @@ -82,7 +87,7 @@ public final class UpdateMeta { /** * get or generate the sql based on the concurrency mode. */ - public SpiUpdatePlan getUpdatePlan(PersistRequestBean request) { + SpiUpdatePlan getUpdatePlan(PersistRequestBean request) { if (request.isDynamicUpdateSql()) { return getDynamicUpdatePlan(request); @@ -135,8 +140,6 @@ public final class UpdateMeta { private String genSql(ConcurrencyMode conMode, BindableList bindableList, String tableName) { - // update set col0=?, col1=?, col2=? where bcol=? and bc1=? and bc2=? - GenerateDmlRequest request = new GenerateDmlRequest(); request.append("update ").append(tableName).append(" set "); @@ -153,12 +156,13 @@ public final class UpdateMeta { request.setWhereIdMode(); id.dmlAppend(request); - + if (tenantId != null) { + tenantId.dmlAppend(request); + } if (ConcurrencyMode.VERSION.equals(conMode)) { - if (version == null) { - return null; + if (version != null) { + version.dmlAppend(request); } - version.dmlAppend(request); } return request.toString(); diff --git a/src/main/java/io/ebeaninternal/server/persist/dmlbind/FactoryVersion.java b/src/main/java/io/ebeaninternal/server/persist/dmlbind/FactoryVersion.java index 12dcf45d9..374204dfa 100644 --- a/src/main/java/io/ebeaninternal/server/persist/dmlbind/FactoryVersion.java +++ b/src/main/java/io/ebeaninternal/server/persist/dmlbind/FactoryVersion.java @@ -18,10 +18,15 @@ public class FactoryVersion { public Bindable create(BeanDescriptor desc) { BeanProperty versionProperty = desc.getVersionProperty(); - if (versionProperty == null) { - return null; - } + return (versionProperty == null) ? null : new BindableProperty(versionProperty); + } - return new BindableProperty(versionProperty); + /** + * Create a Bindable for TenantId If multi-tenant with partitioning is on this bean type. + */ + public Bindable createTenantId(BeanDescriptor desc) { + + BeanProperty tenant = desc.getTenantProperty(); + return (tenant == null) ? null : new BindableProperty(tenant); } }