mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
#210 - ENH: Add Query.setLazyLoadBatch(int size) method ... for per query control
This commit is contained in:
@@ -340,22 +340,32 @@ public interface Query<T> extends Serializable {
|
||||
*/
|
||||
public Query<T> setAutofetch(boolean autofetch);
|
||||
|
||||
/**
|
||||
* Set the default lazy loading batch size to use.
|
||||
* <p>
|
||||
* When lazy loading is invoked on beans loaded by this query then this sets the
|
||||
* batch size used to load those beans.
|
||||
*
|
||||
* @param lazyLoadBatchSize the number of beans to lazy load in a single batch
|
||||
*/
|
||||
public Query<T> setLazyLoadBatchSize(int lazyLoadBatchSize);
|
||||
|
||||
/**
|
||||
* Explicitly set a comma delimited list of the properties to fetch on the
|
||||
* 'main' entity bean (aka partial object). Note that '*' means all
|
||||
* properties.
|
||||
*
|
||||
*
|
||||
* <pre class="code">
|
||||
* Query<Customer> query = Ebean.createQuery(Customer.class);
|
||||
*
|
||||
*
|
||||
* // Only fetch the customer id, name and status.
|
||||
* // This is described as a "Partial Object"
|
||||
* query.select("name, status");
|
||||
* query.where("lower(name) like :custname").setParameter("custname", "rob%");
|
||||
*
|
||||
*
|
||||
* List<Customer> customerList = query.findList();
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* @param fetchProperties
|
||||
* the properties to fetch for this bean (* = all properties).
|
||||
*/
|
||||
|
||||
@@ -11,6 +11,8 @@ import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
*/
|
||||
public interface LoadBeanBuffer {
|
||||
|
||||
public int getBatchSize();
|
||||
|
||||
public List<EntityBeanIntercept> getBatch();
|
||||
|
||||
public BeanDescriptor<?> getBeanDescriptor();
|
||||
|
||||
@@ -59,4 +59,7 @@ public class LoadBeanRequest extends LoadRequest {
|
||||
return lazyLoadProperty;
|
||||
}
|
||||
|
||||
public int getBatchSize() {
|
||||
return getLoadContext().getBatchSize();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,16 +11,16 @@ import com.avaje.ebeaninternal.server.core.OrmQueryRequest;
|
||||
*/
|
||||
public interface LoadContext {
|
||||
|
||||
/**
|
||||
* Return the minimum batch size when using QueryIterator with query joins.
|
||||
*/
|
||||
public int getSecondaryQueriesMinBatchSize(OrmQueryRequest<?> parentRequest, int defaultQueryBatch);
|
||||
/**
|
||||
* Return the minimum batch size when using QueryIterator with query joins.
|
||||
*/
|
||||
public int getSecondaryQueriesMinBatchSize(OrmQueryRequest<?> parentRequest, int defaultQueryBatch);
|
||||
|
||||
/**
|
||||
* Execute any secondary (+query) queries if there are any defined.
|
||||
* @param parentRequest the originating query request
|
||||
*/
|
||||
public void executeSecondaryQueries(OrmQueryRequest<?> parentRequest, int defaultQueryBatch);
|
||||
public void executeSecondaryQueries(OrmQueryRequest<?> parentRequest);
|
||||
|
||||
/**
|
||||
* Register any secondary queries (+query or +lazy) with their
|
||||
|
||||
@@ -13,6 +13,8 @@ import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocMany;
|
||||
*/
|
||||
public interface LoadManyBuffer {
|
||||
|
||||
public int getBatchSize();
|
||||
|
||||
public List<BeanCollection<?>> getBatch();
|
||||
|
||||
public BeanPropertyAssocMany<?> getBeanProperty();
|
||||
|
||||
@@ -18,12 +18,11 @@ public class LoadManyRequest extends LoadRequest {
|
||||
|
||||
private final boolean loadCache;
|
||||
|
||||
public LoadManyRequest(LoadManyBuffer loadContext, int batchSize, boolean lazy,boolean onlyIds, boolean loadCache) {
|
||||
this(loadContext, null, batchSize, lazy, onlyIds, loadCache);
|
||||
public LoadManyRequest(LoadManyBuffer loadContext, boolean lazy, boolean onlyIds, boolean loadCache) {
|
||||
this(loadContext, null, lazy, onlyIds, loadCache);
|
||||
}
|
||||
|
||||
public LoadManyRequest(LoadManyBuffer loadContext, OrmQueryRequest<?> parentRequest, int batchSize, boolean lazy,
|
||||
boolean onlyIds, boolean loadCache) {
|
||||
public LoadManyRequest(LoadManyBuffer loadContext, OrmQueryRequest<?> parentRequest, boolean lazy, boolean onlyIds, boolean loadCache) {
|
||||
|
||||
super(parentRequest, lazy);
|
||||
this.loadContext = loadContext;
|
||||
@@ -69,4 +68,10 @@ public class LoadManyRequest extends LoadRequest {
|
||||
return loadCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the batch size used for this load context.
|
||||
*/
|
||||
public int getBatchSize() {
|
||||
return loadContext.getBatchSize();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,9 +13,6 @@ public interface LoadSecondaryQuery {
|
||||
|
||||
/**
|
||||
* Execute the secondary query with a given batch size.
|
||||
*
|
||||
* @param parentRequest
|
||||
* the originating query request
|
||||
*/
|
||||
public void loadSecondaryQuery(OrmQueryRequest<?> parentRequest, int requestedBatchSize, boolean all);
|
||||
public void loadSecondaryQuery(OrmQueryRequest<?> parentRequest);
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ import com.avaje.ebeaninternal.server.querydefn.OrmQueryProperties;
|
||||
*/
|
||||
public interface SpiQuery<T> extends Query<T> {
|
||||
|
||||
public enum Mode {
|
||||
public enum Mode {
|
||||
NORMAL(false), LAZYLOAD_MANY(false), LAZYLOAD_BEAN(true), REFRESH_BEAN(true);
|
||||
Mode(boolean loadContextBean) {
|
||||
this.loadContextBean = loadContextBean;
|
||||
@@ -89,6 +89,11 @@ public interface SpiQuery<T> extends Query<T> {
|
||||
*/
|
||||
public PersistenceContextScope getPersistenceContextScope();
|
||||
|
||||
/**
|
||||
* Return the default lazy load batch size.
|
||||
*/
|
||||
public int getLazyLoadBatchSize();
|
||||
|
||||
/**
|
||||
* Return true if select all properties was used to ensure the property
|
||||
* invoking a lazy load was included in the query.
|
||||
|
||||
@@ -130,6 +130,11 @@ public class DefaultBeanLoader {
|
||||
String mode = loadRequest.isLazy() ? "+lazy" : "+query";
|
||||
query.setLoadDescription(mode, loadRequest.getDescription());
|
||||
|
||||
if (loadRequest.isLazy()) {
|
||||
// cascade the batch size (if set) for further lazy loading
|
||||
query.setLazyLoadBatchSize(loadRequest.getBatchSize());
|
||||
}
|
||||
|
||||
// potentially changes the joins and selected properties
|
||||
ctx.configureQuery(query);
|
||||
|
||||
@@ -198,7 +203,7 @@ public class DefaultBeanLoader {
|
||||
boolean useManyIdCache = beanCollection != null && parentDesc.isManyPropCaching();
|
||||
if (useManyIdCache) {
|
||||
Boolean readOnly = null;
|
||||
if (ebi != null && ebi.isReadOnly()) {
|
||||
if (ebi.isReadOnly()) {
|
||||
readOnly = Boolean.TRUE;
|
||||
}
|
||||
if (parentDesc.cacheManyPropLoad(many, beanCollection, parentId, readOnly)) {
|
||||
@@ -240,10 +245,8 @@ public class DefaultBeanLoader {
|
||||
query.setLazyLoadManyPath(many.getName());
|
||||
query.setPersistenceContext(pc);
|
||||
|
||||
if (ebi != null) {
|
||||
if (ebi.isReadOnly()) {
|
||||
query.setReadOnly(true);
|
||||
}
|
||||
if (ebi.isReadOnly()) {
|
||||
query.setReadOnly(true);
|
||||
}
|
||||
|
||||
server.findUnique(query, t);
|
||||
@@ -314,6 +317,11 @@ public class DefaultBeanLoader {
|
||||
String mode = loadRequest.isLazy() ? "+lazy" : "+query";
|
||||
query.setLoadDescription(mode, loadRequest.getDescription());
|
||||
|
||||
if (loadRequest.isLazy()) {
|
||||
// cascade the batch size (if set) for further lazy loading
|
||||
query.setLazyLoadBatchSize(loadRequest.getBatchSize());
|
||||
}
|
||||
|
||||
ctx.configureQuery(query, loadRequest.getLazyLoadProperty());
|
||||
|
||||
// make sure the query doesn't use the cache
|
||||
@@ -353,7 +361,6 @@ public class DefaultBeanLoader {
|
||||
private void refreshBeanInternal(EntityBean bean, SpiQuery.Mode mode, int embeddedOwnerIndex) {
|
||||
|
||||
EntityBeanIntercept ebi = bean._ebean_getIntercept();
|
||||
;
|
||||
PersistenceContext pc = ebi.getPersistenceContext();
|
||||
if (Mode.REFRESH_BEAN == mode) {
|
||||
// need a new PersistenceContext for REFRESH
|
||||
@@ -375,9 +382,7 @@ public class DefaultBeanLoader {
|
||||
// a reference with no existing persistenceContext
|
||||
pc = new DefaultPersistenceContext();
|
||||
pc.put(id, bean);
|
||||
if (ebi != null) {
|
||||
ebi.setPersistenceContext(pc);
|
||||
}
|
||||
ebi.setPersistenceContext(pc);
|
||||
}
|
||||
|
||||
if (embeddedOwnerIndex == -1) {
|
||||
@@ -393,9 +398,7 @@ public class DefaultBeanLoader {
|
||||
}
|
||||
|
||||
SpiQuery<?> query = (SpiQuery<?>) server.createQuery(desc.getBeanType());
|
||||
if (ebi != null) {
|
||||
query.setLazyLoadProperty(ebi.getLazyLoadProperty());
|
||||
}
|
||||
query.setLazyLoadProperty(ebi.getLazyLoadProperty());
|
||||
|
||||
if (embeddedOwnerIndex > -1) {
|
||||
String embeddedBeanPropertyName = ebi.getProperty(embeddedOwnerIndex);
|
||||
|
||||
@@ -28,7 +28,6 @@ import com.avaje.ebeaninternal.server.loadcontext.DLoadContext;
|
||||
import com.avaje.ebeaninternal.server.query.CQueryPlan;
|
||||
import com.avaje.ebeaninternal.server.query.CancelableQuery;
|
||||
import com.avaje.ebeaninternal.server.transaction.DefaultPersistenceContext;
|
||||
import com.avaje.ebeaninternal.server.transaction.NoopPersistenceContext;
|
||||
|
||||
/**
|
||||
* Wraps the objects involved in executing a Query.
|
||||
@@ -79,8 +78,8 @@ public final class OrmQueryRequest<T> extends BeanRequest implements BeanQueryRe
|
||||
return ebeanServer.getDatabasePlatform().getLikeClause();
|
||||
}
|
||||
|
||||
public void executeSecondaryQueries(int defaultQueryBatch) {
|
||||
loadContext.executeSecondaryQueries(this, defaultQueryBatch);
|
||||
public void executeSecondaryQueries() {
|
||||
loadContext.executeSecondaryQueries(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -405,4 +404,12 @@ public final class OrmQueryRequest<T> extends BeanRequest implements BeanQueryRe
|
||||
return query.isLogSecondaryQuery();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the batch size for lazy loading on this bean query request.
|
||||
*/
|
||||
public int getLazyLoadBatchSize() {
|
||||
|
||||
int batchSize = query.getLazyLoadBatchSize();
|
||||
return (batchSize > 0) ? batchSize : ebeanServer.getLazyLoadBatchSize();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ public class DLoadBeanContext extends DLoadBaseContext implements LoadBeanContex
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public void loadSecondaryQuery(OrmQueryRequest<?> parentRequest, int requestedBatchSize, boolean all) {
|
||||
public void loadSecondaryQuery(OrmQueryRequest<?> parentRequest) {
|
||||
|
||||
if (!queryFetch) {
|
||||
throw new IllegalStateException("Not expecting loadSecondaryQuery() to be called?");
|
||||
@@ -111,7 +111,11 @@ public class DLoadBeanContext extends DLoadBaseContext implements LoadBeanContex
|
||||
this.batchSize = batchSize;
|
||||
this.list = new ArrayList<EntityBeanIntercept>(batchSize);
|
||||
}
|
||||
|
||||
|
||||
public int getBatchSize() {
|
||||
return batchSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the buffer is full.
|
||||
*/
|
||||
|
||||
@@ -56,7 +56,7 @@ public class DLoadContext implements LoadContext {
|
||||
|
||||
this.persistenceContext = request.getPersistenceContext();
|
||||
this.ebeanServer = request.getServer();
|
||||
this.defaultBatchSize = ebeanServer.getLazyLoadBatchSize();
|
||||
this.defaultBatchSize = request.getLazyLoadBatchSize();
|
||||
this.rootDescriptor = request.getBeanDescriptor();
|
||||
|
||||
SpiQuery<?> query = request.getQuery();
|
||||
@@ -104,18 +104,13 @@ public class DLoadContext implements LoadContext {
|
||||
/**
|
||||
* Execute all the secondary queries.
|
||||
*/
|
||||
public void executeSecondaryQueries(OrmQueryRequest<?> parentRequest, int defaultQueryBatch) {
|
||||
public void executeSecondaryQueries(OrmQueryRequest<?> parentRequest) {
|
||||
|
||||
if (secQuery != null){
|
||||
for (int i = 0; i < secQuery.size(); i++) {
|
||||
OrmQueryProperties properties = secQuery.get(i);
|
||||
|
||||
int batchSize = properties.getQueryFetchBatch();
|
||||
if (batchSize == 0){
|
||||
batchSize = defaultQueryBatch;
|
||||
}
|
||||
LoadSecondaryQuery load = getLoadSecondaryQuery(properties.getPath());
|
||||
load.loadSecondaryQuery(parentRequest, batchSize, properties.isQueryFetchAll());
|
||||
load.loadSecondaryQuery(parentRequest);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -201,10 +196,6 @@ public class DLoadContext implements LoadContext {
|
||||
return useAutofetchManager;
|
||||
}
|
||||
|
||||
public String getRelativePath() {
|
||||
return relativePath;
|
||||
}
|
||||
|
||||
protected String getFullPath(String path) {
|
||||
if (relativePath == null) {
|
||||
return path;
|
||||
|
||||
@@ -83,8 +83,7 @@ public class DLoadManyContext extends DLoadBaseContext implements LoadManyContex
|
||||
bc.setLoader(0, currentBuffer);
|
||||
}
|
||||
|
||||
|
||||
public void loadSecondaryQuery(OrmQueryRequest<?> parentRequest, int requestedBatchSize, boolean all){
|
||||
public void loadSecondaryQuery(OrmQueryRequest<?> parentRequest) {
|
||||
|
||||
if (!queryFetch) {
|
||||
throw new IllegalStateException("Not expecting loadSecondaryQuery() to be called?");
|
||||
@@ -93,7 +92,7 @@ public class DLoadManyContext extends DLoadBaseContext implements LoadManyContex
|
||||
if (bufferList != null) {
|
||||
for (LoadBuffer loadBuffer : bufferList) {
|
||||
if (!loadBuffer.list.isEmpty()) {
|
||||
LoadManyRequest req = new LoadManyRequest(loadBuffer, parentRequest, requestedBatchSize, false, false, false);
|
||||
LoadManyRequest req = new LoadManyRequest(loadBuffer, parentRequest, false, false, false);
|
||||
parent.getEbeanServer().loadMany(req);
|
||||
if (!queryProps.isQueryFetchAll()) {
|
||||
// Stop - only fetch the first batch ... the rest will be lazy loaded
|
||||
@@ -127,6 +126,10 @@ public class DLoadManyContext extends DLoadBaseContext implements LoadManyContex
|
||||
this.batchSize = batchSize;
|
||||
this.list = new ArrayList<BeanCollection<?>>(batchSize);
|
||||
}
|
||||
|
||||
public int getBatchSize() {
|
||||
return batchSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the buffer is full.
|
||||
@@ -188,7 +191,7 @@ public class DLoadManyContext extends DLoadBaseContext implements LoadManyContex
|
||||
boolean useCache = context.hitCache && !onlyIds;
|
||||
if (useCache) {
|
||||
EntityBean ownerBean = bc.getOwnerBean();
|
||||
BeanDescriptor<? extends Object> parentDesc = context.desc.getBeanDescriptor(ownerBean.getClass());
|
||||
BeanDescriptor<?> parentDesc = context.desc.getBeanDescriptor(ownerBean.getClass());
|
||||
Object parentId = parentDesc.getId(ownerBean);
|
||||
if (parentDesc.cacheManyPropLoad(context.property, bc, parentId, context.parent.isReadOnly())) {
|
||||
// we loaded the bean from cache
|
||||
@@ -199,7 +202,7 @@ public class DLoadManyContext extends DLoadBaseContext implements LoadManyContex
|
||||
|
||||
// Should reduce the list by checking each beanCollection in the L2 first before executing the query
|
||||
|
||||
LoadManyRequest req = new LoadManyRequest(this, batchSize, true, onlyIds, useCache);
|
||||
LoadManyRequest req = new LoadManyRequest(this, true, onlyIds, useCache);
|
||||
context.parent.getEbeanServer().loadMany(req);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,14 +25,14 @@ public class CQueryEngine {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(CQueryEngine.class);
|
||||
|
||||
private final DatabasePlatform dbPlatform;
|
||||
|
||||
private static final int defaultSecondaryQueryBatchSize = 100;
|
||||
|
||||
private final boolean forwardOnlyHintOnFindIterate;
|
||||
|
||||
private final CQueryBuilder queryBuilder;
|
||||
|
||||
private final int defaultSecondaryQueryBatchSize = 100;
|
||||
|
||||
public CQueryEngine(DatabasePlatform dbPlatform, Binder binder) {
|
||||
this.dbPlatform = dbPlatform;
|
||||
this.forwardOnlyHintOnFindIterate = dbPlatform.isForwardOnlyHintOnFindIterate();
|
||||
this.queryBuilder = new CQueryBuilder(dbPlatform, binder);
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@ public class CQueryEngine {
|
||||
|
||||
try {
|
||||
|
||||
if (!cquery.prepareBindExecuteQueryForwardOnly(dbPlatform.isForwardOnlyHintOnFindIterate())) {
|
||||
if (!cquery.prepareBindExecuteQueryForwardOnly(forwardOnlyHintOnFindIterate)) {
|
||||
// query has been cancelled already
|
||||
logger.trace("Future fetch already cancelled");
|
||||
return null;
|
||||
@@ -131,7 +131,15 @@ public class CQueryEngine {
|
||||
logSql(cquery);
|
||||
}
|
||||
|
||||
// first check batch sizes set on query joins
|
||||
int iterateBufferSize = request.getSecondaryQueriesMinBatchSize(defaultSecondaryQueryBatchSize);
|
||||
if (iterateBufferSize < 1) {
|
||||
// not set on query joins so check if batch size set on query itself
|
||||
int queryBatch = request.getQuery().getLazyLoadBatchSize();
|
||||
if (queryBatch > 0) {
|
||||
iterateBufferSize = queryBatch;
|
||||
}
|
||||
}
|
||||
|
||||
QueryIterator<T> readIterate = cquery.readIterate(iterateBufferSize, request);
|
||||
|
||||
@@ -178,7 +186,7 @@ public class CQueryEngine {
|
||||
logFindManySummary(cquery);
|
||||
}
|
||||
|
||||
request.executeSecondaryQueries(defaultSecondaryQueryBatchSize);
|
||||
request.executeSecondaryQueries();
|
||||
|
||||
return beanCollection;
|
||||
|
||||
@@ -223,7 +231,7 @@ public class CQueryEngine {
|
||||
logFindBeanSummary(cquery);
|
||||
}
|
||||
|
||||
request.executeSecondaryQueries(defaultSecondaryQueryBatchSize);
|
||||
request.executeSecondaryQueries();
|
||||
|
||||
return (T)bean;
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ class CQueryIteratorWithBuffer<T> implements QueryIterator<T> {
|
||||
}
|
||||
}
|
||||
// execute secondary queries
|
||||
request.executeSecondaryQueries(bufferSize);
|
||||
request.executeSecondaryQueries();
|
||||
}
|
||||
return !buffer.isEmpty();
|
||||
|
||||
|
||||
@@ -88,7 +88,10 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
|
||||
private int firstRow;
|
||||
|
||||
private int totalHits;
|
||||
/**
|
||||
* Lazy loading batch size (can override server wide default).
|
||||
*/
|
||||
private int lazyLoadBatchSize;
|
||||
|
||||
/**
|
||||
* The where clause from a parsed query string.
|
||||
@@ -251,14 +254,6 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
}
|
||||
}
|
||||
|
||||
public int getTotalHits() {
|
||||
return totalHits;
|
||||
}
|
||||
|
||||
public void setTotalHits(int totalHits) {
|
||||
this.totalHits = totalHits;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query<T> apply(PathProperties pathProperties) {
|
||||
pathProperties.apply(this);
|
||||
@@ -295,6 +290,16 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLazyLoadBatchSize() {
|
||||
return lazyLoadBatchSize;
|
||||
}
|
||||
|
||||
public Query<T> setLazyLoadBatchSize(int lazyLoadBatchSize) {
|
||||
this.lazyLoadBatchSize = lazyLoadBatchSize;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getLazyLoadProperty() {
|
||||
return lazyLoadProperty;
|
||||
}
|
||||
@@ -1168,18 +1173,6 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
return query;
|
||||
}
|
||||
|
||||
public DefaultOrmQuery<T> addWhere(String addToWhereClause) {
|
||||
return where(addToWhereClause);
|
||||
}
|
||||
|
||||
public DefaultOrmQuery<T> addWhere(Expression expression) {
|
||||
return where(expression);
|
||||
}
|
||||
|
||||
public ExpressionList<T> addWhere() {
|
||||
return where();
|
||||
}
|
||||
|
||||
public DefaultOrmQuery<T> where(String addToWhereClause) {
|
||||
if (additionalWhere == null) {
|
||||
additionalWhere = addToWhereClause;
|
||||
@@ -1217,18 +1210,6 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
}
|
||||
}
|
||||
|
||||
public DefaultOrmQuery<T> addHaving(String addToHavingClause) {
|
||||
return having(addToHavingClause);
|
||||
}
|
||||
|
||||
public DefaultOrmQuery<T> addHaving(Expression expression) {
|
||||
return having(expression);
|
||||
}
|
||||
|
||||
public ExpressionList<T> addHaving() {
|
||||
return having();
|
||||
}
|
||||
|
||||
public DefaultOrmQuery<T> having(String addToHavingClause) {
|
||||
if (additionalHaving == null) {
|
||||
additionalHaving = addToHavingClause;
|
||||
|
||||
Reference in New Issue
Block a user