#1174 - ENH: Support mapping @TenantId to an entity bean via @ManyToOne

This commit is contained in:
Rob Bygrave
2018-02-21 09:44:37 +13:00
parent 0b1c3a4233
commit eaa48468cd
9 changed files with 67 additions and 10 deletions
@@ -642,7 +642,7 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
* Create and return a new reference bean matching this beans Id value.
*/
public T createReference() {
return beanDescriptor.createReference(Boolean.FALSE, false, getBeanId(), null);
return beanDescriptor.createReference(getBeanId(), null);
}
/**
@@ -1204,7 +1204,7 @@ public class BeanDescriptor<T> implements BeanType<T> {
if (tenant != null && !query.isNativeSql()) {
Object tenantId = ebeanServer.currentTenantId();
if (tenantId != null) {
query.where().eq(tenant.getName(), tenantId);
tenant.addTenant(query, tenantId);
}
}
if (isDocStoreOnly()) {
@@ -1872,6 +1872,29 @@ public class BeanDescriptor<T> implements BeanType<T> {
}
}
/**
* Create a non read only reference bean without checking cacheSharableBeans.
*/
@SuppressWarnings("unchecked")
public T createReference(Object id, PersistenceContext pc) {
try {
EntityBean eb = createEntityBean();
id = convertSetId(id, eb);
EntityBeanIntercept ebi = eb._ebean_getIntercept();
ebi.setBeanLoader(ebeanServer);
ebi.setReference(idPropertyIndex);
if (pc != null) {
contextPut(pc, id, eb);
ebi.setPersistenceContext(pc);
}
return (T) eb;
} catch (Exception ex) {
throw new PersistenceException(ex);
}
}
/**
* Return the bean property traversing the object graph and taking into
* account inheritance.
@@ -2725,7 +2748,7 @@ public class BeanDescriptor<T> implements BeanType<T> {
*/
public void setTenantId(EntityBean entityBean, Object tenantId) {
if (tenant != null) {
tenant.setValue(entityBean, tenantId);
tenant.setTenantValue(entityBean, tenantId);
}
}
@@ -9,8 +9,10 @@ import io.ebean.config.dbplatform.DbEncryptFunction;
import io.ebean.config.dbplatform.DbPlatformType;
import io.ebean.plugin.Property;
import io.ebean.text.StringParser;
import io.ebean.util.SplitName;
import io.ebean.util.StringHelper;
import io.ebeaninternal.api.SpiExpressionRequest;
import io.ebeaninternal.api.SpiQuery;
import io.ebeaninternal.server.core.InternString;
import io.ebeaninternal.server.deploy.generatedproperty.GeneratedProperty;
import io.ebeaninternal.server.deploy.generatedproperty.GeneratedWhenCreated;
@@ -20,7 +22,6 @@ import io.ebeaninternal.server.el.ElPropertyChainBuilder;
import io.ebeaninternal.server.el.ElPropertyValue;
import io.ebeaninternal.server.properties.BeanPropertyGetter;
import io.ebeaninternal.server.properties.BeanPropertySetter;
import io.ebean.util.SplitName;
import io.ebeaninternal.server.query.SqlBeanLoad;
import io.ebeaninternal.server.query.SqlJoinType;
import io.ebeaninternal.server.text.json.ReadJson;
@@ -720,6 +721,20 @@ public class BeanProperty implements ElPropertyValue, Property {
bean._ebean_getIntercept().setChangedProperty(propertyIndex);
}
/**
* Add the tenantId predicate to the query.
*/
public void addTenant(SpiQuery<?> query, Object tenantId) {
query.where().eq(name, tenantId);
}
/**
* Set the tenantId onto the bean.
*/
public void setTenantValue(EntityBean entityBean, Object tenantId) {
setValue(entityBean, tenantId);
}
/**
* Set the value of the property without interception or
* PropertyChangeSupport.
@@ -967,7 +967,7 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> {
if (isManyToMany()) {
if (liveBean == null) {
// add new relationship (Map not allowed here)
liveVal.addBean(targetDescriptor.createReference(Boolean.FALSE, false, id, null));
liveVal.addBean(targetDescriptor.createReference(id, null));
}
} else {
@@ -8,6 +8,7 @@ import io.ebean.ValuePair;
import io.ebean.bean.EntityBean;
import io.ebean.bean.PersistenceContext;
import io.ebean.util.SplitName;
import io.ebeaninternal.api.SpiQuery;
import io.ebeaninternal.server.cache.CacheChangeSet;
import io.ebeaninternal.server.cache.CachedBeanData;
import io.ebeaninternal.server.core.DefaultSqlUpdate;
@@ -419,7 +420,7 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> {
// cacheData is the id value, maybe already in persistence context
Object assocBean = targetDescriptor.contextGet(context, cacheData);
if (assocBean == null) {
assocBean = targetDescriptor.createReference(Boolean.FALSE, false, cacheData, context);
assocBean = targetDescriptor.createReference(cacheData, context);
}
setValue(bean, assocBean);
}
@@ -605,6 +606,16 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> {
return localHelp.read(ctx);
}
public void addTenant(SpiQuery<?> query, Object tenantId) {
T refBean = targetDescriptor.createReference(tenantId, null);
query.where().eq(name, refBean);
}
public void setTenantValue(EntityBean entityBean, Object tenantId) {
T refBean = targetDescriptor.createReference(tenantId, null);
setValue(entityBean, refBean);
}
@Override
public void setValue(EntityBean bean, Object value) {
super.setValue(bean, value);
@@ -207,6 +207,9 @@ public class DeployBeanPropertyLists {
} else {
nonManys.add(prop);
if (prop.isTenantId()) {
tenant = prop;
}
if (prop instanceof BeanPropertyAssocOne<?>) {
BeanPropertyAssocOne<?> assocOne = (BeanPropertyAssocOne<?>) prop;
if (prop.isEmbedded()) {
@@ -227,8 +230,6 @@ public class DeployBeanPropertyLists {
}
} else if (prop.isDraftDirty()) {
draftDirty = prop;
} else if (prop.isTenantId()) {
tenant = prop;
}
if (!prop.isAggregation()) {
baseScalar.add(prop);
@@ -2,6 +2,7 @@ package io.ebeaninternal.server.deploy.parse;
import io.ebean.annotation.DbForeignKey;
import io.ebean.annotation.FetchPreference;
import io.ebean.annotation.TenantId;
import io.ebean.annotation.Where;
import io.ebean.config.NamingConvention;
import io.ebeaninternal.server.deploy.BeanDescriptorManager;
@@ -63,6 +64,9 @@ public class AnnotationAssocOnes extends AnnotationParser {
ManyToOne manyToOne = get(prop, ManyToOne.class);
if (manyToOne != null) {
readManyToOne(manyToOne, prop);
if (get(prop, TenantId.class) != null) {
prop.setTenantId();
}
}
OneToOne oneToOne = get(prop, OneToOne.class);
if (oneToOne != null) {
@@ -1138,7 +1138,7 @@ public final class DefaultPersister implements Persister {
// convert into a list of reference objects and perform delete by object
List<Object> refList = new ArrayList<>(childIds.size());
for (Object id : childIds) {
refList.add(targetDesc.createReference(null, false, id, null));
refList.add(targetDesc.createReference(id, null));
}
deleteList(refList, t, softDelete);