All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.ebeaninternal.server.expression.DefaultExampleExpression Maven / Gradle / Ivy

There is a newer version: 15.8.0
Show newest version
package io.ebeaninternal.server.expression;

import io.ebean.ExampleExpression;
import io.ebean.LikeType;
import io.ebean.bean.EntityBean;
import io.ebean.event.BeanQueryRequest;
import io.ebean.util.SplitName;
import io.ebeaninternal.api.*;
import io.ebeaninternal.server.deploy.BeanDescriptor;
import io.ebeaninternal.server.deploy.BeanProperty;
import io.ebeaninternal.server.deploy.BeanPropertyAssocOne;

import java.util.ArrayList;

/**
 * A "Query By Example" type of expression.
 * 

* Pass in an example entity and for each non-null scalar properties an * expression is added. *

*

*

{@code
 * // create an example bean and set the properties
 * // with the query parameters you want
 * Customer example = new Customer();
 * example.setName("Rob%");
 * example.setNotes("%something%");
 *
 * List list = Ebean.find(Customer.class)
 *   .where()
 *   .exampleLike(example)
 *   .findList();
 *
 * }
*/ final class DefaultExampleExpression implements SpiExpression, ExampleExpression { /** * The example bean containing the properties. */ private final EntityBean entity; /** * Set to true to use case-insensitive expressions. */ private boolean caseInsensitive; /** * The type of like (RAW, STARTS_WITH, ENDS_WITH) */ private LikeType likeType; /** * By default zeros are excluded. */ private boolean includeZeros; /** * The non-null bean properties and found and together added as a list of * expressions (like or equal to expressions). */ private ArrayList list; /** * Construct the query by example expression. * * @param entity the example entity with non-null property values * @param caseInsensitive if true use case-insensitive expressions * @param likeType the type of Like wild card used */ DefaultExampleExpression(EntityBean entity, boolean caseInsensitive, LikeType likeType) { this.entity = entity; this.caseInsensitive = caseInsensitive; this.likeType = likeType; } DefaultExampleExpression(ArrayList source) { this.entity = null; this.list = new ArrayList<>(source.size()); for (SpiExpression expression : source) { list.add(expression.copyForPlanKey()); } } @Override public void prefixProperty(String path) { for (SpiExpression exp : list) { exp.prefixProperty(path); } } @Override public boolean naturalKey(NaturalKeyQueryData data) { // can't use naturalKey cache return false; } @Override public void simplify() { // do nothing } @Override public Object getIdEqualTo(String idName) { // always return null for this expression return null; } @Override public SpiExpression copyForPlanKey() { return new DefaultExampleExpression(list); } @Override public void containsMany(BeanDescriptor desc, ManyWhereJoins whereManyJoins) { list = buildExpressions(desc); for (SpiExpression expr : list) { expr.containsMany(desc, whereManyJoins); } } @Override public void prepareExpression(BeanQueryRequest request) { // do nothing } @Override public ExampleExpression includeZeros() { includeZeros = true; return this; } @Override public ExampleExpression caseInsensitive() { caseInsensitive = true; return this; } @Override public ExampleExpression useStartsWith() { likeType = LikeType.STARTS_WITH; return this; } @Override public ExampleExpression useContains() { likeType = LikeType.CONTAINS; return this; } @Override public ExampleExpression useEndsWith() { likeType = LikeType.ENDS_WITH; return this; } @Override public ExampleExpression useEqualTo() { likeType = LikeType.EQUAL_TO; return this; } @Override public void validate(SpiExpressionValidation validation) { for (SpiExpression expr : list) { expr.validate(validation); } } /** * Adds bind values to the request. */ @Override public void addBindValues(SpiExpressionBind request) { for (SpiExpression item : list) { item.addBindValues(request); } } /** * Generates and adds the sql to the request. */ @Override public void addSql(SpiExpressionRequest request) { if (list.isEmpty()) { request.append(SQL_TRUE); } else { request.append('('); for (int i = 0; i < list.size(); i++) { SpiExpression item = list.get(i); if (i > 0) { request.append(" and "); } item.addSql(request); } request.append(')'); } } /** * Return a hash for AutoTune query identification. */ @Override public void queryPlanHash(StringBuilder builder) { builder.append("Example["); for (SpiExpression expr : list) { expr.queryPlanHash(builder); builder.append(','); } builder.append(']'); } @Override public void queryBindKey(BindValuesKey key) { key.add(list.size()); for (SpiExpression expr : list) { expr.queryBindKey(key); } } @Override public boolean isSameByBind(SpiExpression other) { DefaultExampleExpression that = (DefaultExampleExpression) other; if (this.list.size() != that.list.size()) { return false; } for (int i = 0; i < list.size(); i++) { if (!list.get(i).isSameByBind(that.list.get(i))) { return false; } } return true; } /** * Build the List of expressions. */ private ArrayList buildExpressions(BeanDescriptor beanDescriptor) { ArrayList list = new ArrayList<>(); addExpressions(list, beanDescriptor, entity, null); return list; } /** * Add expressions to the list for all the non-null properties (and do this recursively). */ private void addExpressions(ArrayList list, BeanDescriptor beanDescriptor, EntityBean bean, String prefix) { for (BeanProperty beanProperty : beanDescriptor.propertiesAll()) { if (!beanProperty.isTransient()) { Object value = beanProperty.getValue(bean); if (value != null) { String propName = SplitName.add(prefix, beanProperty.name()); if (beanProperty.isScalar()) { if (value instanceof String) { list.add(new LikeExpression(propName, value, caseInsensitive, likeType)); } else { // exclude the zero values typically to weed out // primitive int and long that initialise to 0 if (includeZeros || !isZero(value)) { list.add(new SimpleExpression(propName, Op.EQ, value)); } } } else if ((beanProperty instanceof BeanPropertyAssocOne) && (value instanceof EntityBean)) { BeanPropertyAssocOne assocOne = (BeanPropertyAssocOne) beanProperty; BeanDescriptor targetDescriptor = assocOne.targetDescriptor(); addExpressions(list, targetDescriptor, (EntityBean) value, propName); } } } } } /** * Return true if the value is a numeric zero. */ private boolean isZero(Object value) { if (value instanceof Number) { return ((Number) value).doubleValue() == 0; } return false; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy