mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
#274 - Predicate using a foreign key column sometimes adds an extra join
This commit is contained in:
@@ -60,12 +60,12 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
|
||||
|
||||
private final ConcurrentHashMap<HashQueryPlan, CQueryPlan> queryPlanCache = new ConcurrentHashMap<HashQueryPlan, CQueryPlan>();
|
||||
|
||||
private final ConcurrentHashMap<String, ElPropertyValue> elGetCache = new ConcurrentHashMap<String, ElPropertyValue>();
|
||||
private final ConcurrentHashMap<String, ElPropertyValue> elCache = new ConcurrentHashMap<String, ElPropertyValue>();
|
||||
|
||||
private final ConcurrentHashMap<String, ElPropertyDeploy> elDeployCache = new ConcurrentHashMap<String, ElPropertyDeploy>();
|
||||
|
||||
private final ConcurrentHashMap<String, ElComparator<T>> comparatorCache = new ConcurrentHashMap<String, ElComparator<T>>();
|
||||
|
||||
private final ConcurrentHashMap<String, BeanFkeyProperty> fkeyMap = new ConcurrentHashMap<String, BeanFkeyProperty>();
|
||||
|
||||
public enum EntityType {
|
||||
ORM, EMBEDDED, SQL
|
||||
}
|
||||
@@ -630,7 +630,7 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
|
||||
* foreign keys don't require an extra join.
|
||||
*/
|
||||
public void add(BeanFkeyProperty fkey) {
|
||||
fkeyMap.put(fkey.getName(), fkey);
|
||||
elDeployCache.put(fkey.getName(), fkey);
|
||||
}
|
||||
|
||||
public void initialiseFkeys() {
|
||||
@@ -1379,7 +1379,15 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
|
||||
* Get an Expression language Value object.
|
||||
*/
|
||||
public ElPropertyValue getElGetValue(String propName) {
|
||||
return getElPropertyValue(propName, false);
|
||||
ElPropertyValue elGetValue = elCache.get(propName);
|
||||
if (elGetValue != null) {
|
||||
return elGetValue;
|
||||
}
|
||||
elGetValue = buildElGetValue(propName, null, false);
|
||||
if (elGetValue != null) {
|
||||
elCache.put(propName, elGetValue);
|
||||
}
|
||||
return elGetValue;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1389,36 +1397,30 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
|
||||
* </p>
|
||||
*/
|
||||
public ElPropertyDeploy getElPropertyDeploy(String propName) {
|
||||
ElPropertyDeploy fk = fkeyMap.get(propName);
|
||||
if (fk != null) {
|
||||
return fk;
|
||||
ElPropertyDeploy elProp = elDeployCache.get(propName);
|
||||
if (elProp != null) {
|
||||
return elProp;
|
||||
}
|
||||
return getElPropertyValue(propName, true);
|
||||
}
|
||||
|
||||
private ElPropertyValue getElPropertyValue(String propName, boolean propertyDeploy) {
|
||||
ElPropertyValue elGetValue = elGetCache.get(propName);
|
||||
if (elGetValue == null) {
|
||||
// need to build it potentially navigating the BeanDescriptors
|
||||
elGetValue = buildElGetValue(propName, null, propertyDeploy);
|
||||
if (elGetValue == null) {
|
||||
return null;
|
||||
}
|
||||
if (elGetValue instanceof BeanFkeyProperty) {
|
||||
fkeyMap.put(propName, (BeanFkeyProperty) elGetValue);
|
||||
} else {
|
||||
elGetCache.put(propName, elGetValue);
|
||||
}
|
||||
if (!propName.contains(".")) {
|
||||
// No period means simple property and no need to look for
|
||||
// foreign key properties (in order to avoid an extra join)
|
||||
elProp = getElGetValue(propName);
|
||||
} else {
|
||||
elProp = buildElGetValue(propName, null, true);
|
||||
}
|
||||
return elGetValue;
|
||||
if (elProp != null) {
|
||||
elDeployCache.put(propName, elProp);
|
||||
}
|
||||
return elProp;
|
||||
}
|
||||
|
||||
protected ElPropertyValue buildElGetValue(String propName, ElPropertyChainBuilder chain, boolean propertyDeploy) {
|
||||
|
||||
if (propertyDeploy && chain != null) {
|
||||
BeanFkeyProperty fk = fkeyMap.get(propName);
|
||||
if (fk != null) {
|
||||
return fk.create(chain.getExpression(), chain.isContainsMany());
|
||||
ElPropertyDeploy fk = elDeployCache.get(propName);
|
||||
if (fk != null && fk instanceof BeanFkeyProperty) {
|
||||
// propertyDeploy chain for foreign key column
|
||||
return ((BeanFkeyProperty)fk).create(chain.getExpression(), chain.isContainsMany());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,10 @@ public final class BeanFkeyProperty implements ElPropertyValue {
|
||||
this.placeHolder = calcPlaceHolder(prefix, dbColumn);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "prefix:"+prefix+" name:"+name+" dbColumn:"+dbColumn+" ph:"+placeHolder;
|
||||
}
|
||||
|
||||
public int getDeployOrder() {
|
||||
return deployOrder;
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@ import com.avaje.ebeaninternal.server.lib.util.StringHelper;
|
||||
import com.avaje.ebeaninternal.server.query.SplitName;
|
||||
import com.avaje.ebeaninternal.server.type.ScalarType;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
|
||||
/**
|
||||
* A ElGetValue based on a chain of properties.
|
||||
@@ -41,9 +43,9 @@ public class ElPropertyChain implements ElPropertyValue {
|
||||
private final ScalarType<?> scalarType;
|
||||
|
||||
private final ElPropertyValue lastElPropertyValue;
|
||||
|
||||
|
||||
public ElPropertyChain(boolean containsMany, boolean embedded, String expression, ElPropertyValue[] chain) {
|
||||
|
||||
|
||||
this.containsMany = containsMany;
|
||||
this.chain = chain;
|
||||
this.expression = expression;
|
||||
@@ -51,19 +53,19 @@ public class ElPropertyChain implements ElPropertyValue {
|
||||
if (dotPos > -1){
|
||||
this.name = expression.substring(dotPos+1);
|
||||
if (embedded){
|
||||
int embPos = expression.lastIndexOf('.',dotPos-1);
|
||||
int embPos = expression.lastIndexOf('.',dotPos-1);
|
||||
this.prefix = embPos == -1 ? null : expression.substring(0, embPos);
|
||||
|
||||
|
||||
} else {
|
||||
this.prefix = expression.substring(0, dotPos);
|
||||
}
|
||||
} else {
|
||||
this.prefix = null;
|
||||
this.name = expression;
|
||||
}
|
||||
}
|
||||
|
||||
this.assocId = chain[chain.length-1].isAssocId();
|
||||
|
||||
|
||||
this.last = chain.length-1;
|
||||
this.lastBeanProperty = chain[chain.length-1].getBeanProperty();
|
||||
if (lastBeanProperty != null){
|
||||
@@ -77,6 +79,10 @@ public class ElPropertyChain implements ElPropertyValue {
|
||||
this.placeHolderEncrypted = getElPlaceHolder(prefix, lastElPropertyValue, true);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "expr:"+expression+" chain:"+ Arrays.toString(chain);
|
||||
}
|
||||
|
||||
private String getElPlaceHolder(String prefix, ElPropertyValue lastElPropertyValue, boolean encrypted) {
|
||||
if (prefix == null){
|
||||
return lastElPropertyValue.getElPlaceholder(encrypted);
|
||||
|
||||
Reference in New Issue
Block a user