001package com.avaje.ebean; 002 003import com.avaje.ebean.text.PathProperties; 004import org.jetbrains.annotations.Nullable; 005 006import java.io.Serializable; 007import java.sql.Timestamp; 008import java.util.Collection; 009import java.util.List; 010import java.util.Map; 011import java.util.Set; 012 013/** 014 * List of Expressions that make up a where or having clause. 015 * <p> 016 * An ExpressionList is returned from {@link Query#where()}. 017 * </p> 018 * <p> 019 * The ExpressionList has a list of convenience methods that create the standard 020 * expressions and add them to this list. 021 * </p> 022 * <p> 023 * The ExpressionList also duplicates methods that are found on the Query such 024 * as findList() and orderBy(). The purpose of these methods is provide a fluid 025 * API. The upside of this approach is that you can build and execute a query 026 * via chained methods. The down side is that this ExpressionList object has 027 * more methods than you would initially expect (the ones duplicated from 028 * Query). 029 * </p> 030 * 031 * @see Query#where() 032 */ 033public interface ExpressionList<T> extends Serializable { 034 035 /** 036 * Return the query that owns this expression list. 037 * <p> 038 * This is a convenience method solely to support a fluid API where the 039 * methods are chained together. Adding expressions returns this expression 040 * list and this method can be used after that to return back the original 041 * query so that further things can be added to it. 042 * </p> 043 */ 044 Query<T> query(); 045 046 /** 047 * Set the order by clause replacing the existing order by clause if there is 048 * one. 049 * <p> 050 * This follows SQL syntax using commas between each property with the 051 * optional asc and desc keywords representing ascending and descending order 052 * respectively. 053 * </p> 054 * <p> 055 * This is EXACTLY the same as {@link #orderBy(String)}. 056 * </p> 057 */ 058 Query<T> order(String orderByClause); 059 060 /** 061 * Return the OrderBy so that you can append an ascending or descending 062 * property to the order by clause. 063 * <p> 064 * This will never return a null. If no order by clause exists then an 'empty' 065 * OrderBy object is returned. 066 * </p> 067 */ 068 OrderBy<T> order(); 069 070 /** 071 * Return the OrderBy so that you can append an ascending or descending 072 * property to the order by clause. 073 * <p> 074 * This will never return a null. If no order by clause exists then an 'empty' 075 * OrderBy object is returned. 076 * </p> 077 */ 078 OrderBy<T> orderBy(); 079 080 /** 081 * Add an orderBy clause to the query. 082 * 083 * @see Query#orderBy(String) 084 */ 085 Query<T> orderBy(String orderBy); 086 087 /** 088 * Add an orderBy clause to the query. 089 * 090 * @see Query#orderBy(String) 091 */ 092 Query<T> setOrderBy(String orderBy); 093 094 /** 095 * Apply the path properties to the query replacing the select and fetch clauses. 096 */ 097 Query<T> apply(PathProperties pathProperties); 098 099 /** 100 * Perform an 'As of' query using history tables to return the object graph 101 * as of a time in the past. 102 * <p> 103 * To perform this query the DB must have underlying history tables. 104 * </p> 105 * 106 * @param asOf the date time in the past at which you want to view the data 107 */ 108 Query<T> asOf(Timestamp asOf); 109 110 /** 111 * Execute as a delete query deleting the 'root level' beans that match the predicates 112 * in the query. 113 * <p> 114 * Note that if the query includes joins then the generated delete statement may not be 115 * optimal depending on the database platform. 116 * </p> 117 * 118 * @return the number of beans/rows that were deleted. 119 */ 120 int delete(); 121 122 /** 123 * Execute the query iterating over the results. 124 * 125 * @see Query#findIterate() 126 */ 127 QueryIterator<T> findIterate(); 128 129 /** 130 * Execute the query process the beans one at a time. 131 * 132 * @see Query#findEach(QueryEachConsumer) 133 */ 134 void findEach(QueryEachConsumer<T> consumer); 135 136 /** 137 * Execute the query processing the beans one at a time with the ability to 138 * stop processing before reading all the beans. 139 * 140 * @see Query#findEachWhile(QueryEachWhileConsumer) 141 */ 142 void findEachWhile(QueryEachWhileConsumer<T> consumer); 143 144 /** 145 * Execute the query returning a list. 146 * 147 * @see Query#findList() 148 */ 149 List<T> findList(); 150 151 /** 152 * Execute the query returning the list of Id's. 153 * 154 * @see Query#findIds() 155 */ 156 List<Object> findIds(); 157 158 /** 159 * Return the count of entities this query should return. 160 * <p> 161 * This is the number of 'top level' or 'root level' entities. 162 * </p> 163 */ 164 int findRowCount(); 165 166 /** 167 * Execute the query returning a set. 168 * 169 * @see Query#findSet() 170 */ 171 Set<T> findSet(); 172 173 /** 174 * Execute the query returning a map. 175 * 176 * @see Query#findMap() 177 */ 178 Map<?, T> findMap(); 179 180 /** 181 * Return a typed map specifying the key property and type. 182 */ 183 <K> Map<K, T> findMap(String keyProperty, Class<K> keyType); 184 185 /** 186 * Execute the query returning a single bean. 187 * 188 * @see Query#findUnique() 189 */ 190 @Nullable 191 T findUnique(); 192 193 /** 194 * Execute find row count query in a background thread. 195 * <p> 196 * This returns a Future object which can be used to cancel, check the 197 * execution status (isDone etc) and get the value (with or without a 198 * timeout). 199 * </p> 200 * 201 * @return a Future object for the row count query 202 */ 203 FutureRowCount<T> findFutureRowCount(); 204 205 /** 206 * Execute find Id's query in a background thread. 207 * <p> 208 * This returns a Future object which can be used to cancel, check the 209 * execution status (isDone etc) and get the value (with or without a 210 * timeout). 211 * </p> 212 * 213 * @return a Future object for the list of Id's 214 */ 215 FutureIds<T> findFutureIds(); 216 217 /** 218 * Execute find list query in a background thread. 219 * <p> 220 * This returns a Future object which can be used to cancel, check the 221 * execution status (isDone etc) and get the value (with or without a 222 * timeout). 223 * </p> 224 * 225 * @return a Future object for the list result of the query 226 */ 227 FutureList<T> findFutureList(); 228 229 /** 230 * Return a PagedList for this query. 231 * <p> 232 * The benefit of using this over just using the normal {@link Query#setFirstRow(int)} and 233 * {@link Query#setMaxRows(int)} is that it additionally wraps an optional call to 234 * {@link Query#findFutureRowCount()} to determine total row count, total page count etc. 235 * </p> 236 * <p> 237 * Internally this works using {@link Query#setFirstRow(int)} and {@link Query#setMaxRows(int)} on 238 * the query. This translates into SQL that uses limit offset, rownum or row_number 239 * function to limit the result set. 240 * </p> 241 * 242 * @param pageIndex 243 * The zero based index of the page. 244 * @param pageSize 245 * The number of beans to return per page. 246 * @return The PagedList 247 */ 248 PagedList<T> findPagedList(int pageIndex, int pageSize); 249 250 /** 251 * Return versions of a @History entity bean. 252 * <p> 253 * Generally this query is expected to be a find by id or unique predicates query. 254 * It will execute the query against the history returning the versions of the bean. 255 * </p> 256 */ 257 List<Version<T>> findVersions(); 258 259 /** 260 * Return versions of a @History entity bean between the 2 timestamps. 261 * <p> 262 * Generally this query is expected to be a find by id or unique predicates query. 263 * It will execute the query against the history returning the versions of the bean. 264 * </p> 265 */ 266 List<Version<T>> findVersionsBetween(Timestamp start, Timestamp end); 267 268 /** 269 * Add some filter predicate expressions to the many property. 270 */ 271 ExpressionList<T> filterMany(String prop); 272 273 /** 274 * Specify specific properties to fetch on the main/root bean (aka partial 275 * object). 276 * 277 * @see Query#select(String) 278 */ 279 Query<T> select(String properties); 280 281 /** 282 * Set whether this query uses DISTINCT. 283 * <p> 284 * The select() clause MUST be specified when setDistinct(true) is set. The reason for this is that 285 * generally ORM queries include the "id" property and this doesn't make sense for distinct queries. 286 * </p> 287 * <pre>{@code 288 * 289 * List<Customer> customers = 290 * Ebean.find(Customer.class) 291 * .setDistinct(true) 292 * .select("name") // only select the customer name 293 * .findList(); 294 * 295 * }</pre> 296 */ 297 Query<T> setDistinct(boolean distinct); 298 299 /** 300 * Set the first row to fetch. 301 * 302 * @see Query#setFirstRow(int) 303 */ 304 Query<T> setFirstRow(int firstRow); 305 306 /** 307 * Set the maximum number of rows to fetch. 308 * 309 * @see Query#setMaxRows(int) 310 */ 311 Query<T> setMaxRows(int maxRows); 312 313 /** 314 * Set the name of the property which values become the key of a map. 315 * 316 * @see Query#setMapKey(String) 317 */ 318 Query<T> setMapKey(String mapKey); 319 320 /** 321 * Set to true to use the query for executing this query. 322 * 323 * @see Query#setUseCache(boolean) 324 */ 325 Query<T> setUseCache(boolean useCache); 326 327 /** 328 * Set to true to use the query for executing this query. 329 * 330 * @see Query#setUseQueryCache(boolean) 331 */ 332 Query<T> setUseQueryCache(boolean useCache); 333 334 /** 335 * Add expressions to the having clause. 336 * <p> 337 * The having clause is only used for queries based on raw sql (via SqlSelect 338 * annotation etc). 339 * </p> 340 */ 341 ExpressionList<T> having(); 342 343 /** 344 * Add another expression to the where clause. 345 */ 346 ExpressionList<T> where(); 347 348 /** 349 * Path exists - for the given path in a JSON document. 350 * 351 * <pre>{@code 352 * 353 * where().jsonExists("content", "path.other") 354 * 355 * }</pre> 356 * 357 * @param propertyName the property that holds a JSON document 358 * @param path the nested path in the JSON document in dot notation 359 */ 360 ExpressionList<T> jsonExists(String propertyName, String path); 361 362 /** 363 * Path does not exist - for the given path in a JSON document. 364 * 365 * <pre>{@code 366 * 367 * where().jsonNotExists("content", "path.other") 368 * 369 * }</pre> 370 * 371 * @param propertyName the property that holds a JSON document 372 * @param path the nested path in the JSON document in dot notation 373 */ 374 ExpressionList<T> jsonNotExists(String propertyName, String path); 375 376 /** 377 * Equal to expression for the value at the given path in the JSON document. 378 * 379 * <pre>{@code 380 * 381 * where().jsonEqualTo("content", "path.other", 34) 382 * 383 * }</pre> 384 * 385 * @param propertyName the property that holds a JSON document 386 * @param path the nested path in the JSON document in dot notation 387 * @param value the value used to test against the document path's value 388 */ 389 ExpressionList<T> jsonEqualTo(String propertyName, String path, Object value); 390 391 /** 392 * Not Equal to - for the given path in a JSON document. 393 * 394 * <pre>{@code 395 * 396 * where().jsonNotEqualTo("content", "path.other", 34) 397 * 398 * }</pre> 399 * 400 * @param propertyName the property that holds a JSON document 401 * @param path the nested path in the JSON document in dot notation 402 * @param value the value used to test against the document path's value 403 */ 404 ExpressionList<T> jsonNotEqualTo(String propertyName, String path, Object value); 405 406 /** 407 * Greater than - for the given path in a JSON document. 408 * 409 * <pre>{@code 410 * 411 * where().jsonGreaterThan("content", "path.other", 34) 412 * 413 * }</pre> 414 */ 415 ExpressionList<T> jsonGreaterThan(String propertyName, String path, Object value); 416 417 /** 418 * Greater than or equal to - for the given path in a JSON document. 419 * 420 * <pre>{@code 421 * 422 * where().jsonGreaterOrEqual("content", "path.other", 34) 423 * 424 * }</pre> 425 */ 426 ExpressionList<T> jsonGreaterOrEqual(String propertyName, String path, Object value); 427 428 /** 429 * Less than - for the given path in a JSON document. 430 * 431 * <pre>{@code 432 * 433 * where().jsonLessThan("content", "path.other", 34) 434 * 435 * }</pre> 436 */ 437 ExpressionList<T> jsonLessThan(String propertyName, String path, Object value); 438 439 /** 440 * Less than or equal to - for the given path in a JSON document. 441 * 442 * <pre>{@code 443 * 444 * where().jsonLessOrEqualTo("content", "path.other", 34) 445 * 446 * }</pre> 447 */ 448 ExpressionList<T> jsonLessOrEqualTo(String propertyName, String path, Object value); 449 450 /** 451 * Between - for the given path in a JSON document. 452 * 453 * <pre>{@code 454 * 455 * where().jsonBetween("content", "orderDate", lowerDateTime, upperDateTime) 456 * 457 * }</pre> 458 */ 459 ExpressionList<T> jsonBetween(String propertyName, String path, Object lowerValue, Object upperValue); 460 461 /** 462 * Add an Expression to the list. 463 * <p> 464 * This returns the list so that add() can be chained. 465 * </p> 466 * 467 * <pre>{@code 468 * 469 * Query<Customer> query = Ebean.find(Customer.class); 470 * query.where() 471 * .like("name","Rob%") 472 * .eq("status", Customer.ACTIVE); 473 * 474 * List<Customer> list = query.findList(); 475 * ... 476 * 477 * }</pre> 478 */ 479 ExpressionList<T> add(Expression expr); 480 481 /** 482 * Add a list of Expressions to this ExpressionList.s 483 */ 484 ExpressionList<T> addAll(ExpressionList<T> exprList); 485 486 /** 487 * Equal To - property is equal to a given value. 488 */ 489 ExpressionList<T> eq(String propertyName, Object value); 490 491 /** 492 * Not Equal To - property not equal to the given value. 493 */ 494 ExpressionList<T> ne(String propertyName, Object value); 495 496 /** 497 * Case Insensitive Equal To - property equal to the given value (typically 498 * using a lower() function to make it case insensitive). 499 */ 500 ExpressionList<T> ieq(String propertyName, String value); 501 502 /** 503 * Between - property between the two given values. 504 */ 505 ExpressionList<T> between(String propertyName, Object value1, Object value2); 506 507 /** 508 * Between - value between the two properties. 509 */ 510 ExpressionList<T> betweenProperties(String lowProperty, String highProperty, Object value); 511 512 /** 513 * Greater Than - property greater than the given value. 514 */ 515 ExpressionList<T> gt(String propertyName, Object value); 516 517 /** 518 * Greater Than or Equal to - property greater than or equal to the given 519 * value. 520 */ 521 ExpressionList<T> ge(String propertyName, Object value); 522 523 /** 524 * Less Than - property less than the given value. 525 */ 526 ExpressionList<T> lt(String propertyName, Object value); 527 528 /** 529 * Less Than or Equal to - property less than or equal to the given value. 530 */ 531 ExpressionList<T> le(String propertyName, Object value); 532 533 /** 534 * Is Null - property is null. 535 */ 536 ExpressionList<T> isNull(String propertyName); 537 538 /** 539 * Is Not Null - property is not null. 540 */ 541 ExpressionList<T> isNotNull(String propertyName); 542 543 /** 544 * A "Query By Example" type of expression. 545 * <p> 546 * Pass in an example entity and for each non-null scalar properties an 547 * expression is added. 548 * </p> 549 * <p> 550 * By Default this case sensitive, will ignore numeric zero values and will 551 * use a Like for string values (you must put in your own wildcards). 552 * </p> 553 * <p> 554 * To get control over the options you can create an ExampleExpression and set 555 * those options such as case insensitive etc. 556 * </p> 557 * 558 * <pre>{@code 559 * 560 * // create an example bean and set the properties 561 * // with the query parameters you want 562 * Customer example = new Customer(); 563 * example.setName("Rob%"); 564 * example.setNotes("%something%"); 565 * 566 * List<Customer> list = Ebean.find(Customer.class).where() 567 * // pass the bean into the where() clause 568 * .exampleLike(example) 569 * // you can add other expressions to the same query 570 * .gt("id", 2).findList(); 571 * 572 * }</pre> 573 * 574 * Similarly you can create an ExampleExpression 575 * 576 * <pre>{@code 577 * 578 * Customer example = new Customer(); 579 * example.setName("Rob%"); 580 * example.setNotes("%something%"); 581 * 582 * // create a ExampleExpression with more control 583 * ExampleExpression qbe = new ExampleExpression(example, true, LikeType.EQUAL_TO).includeZeros(); 584 * 585 * List<Customer> list = Ebean.find(Customer.class).where().add(qbe).findList(); 586 * 587 * }</pre> 588 */ 589 ExpressionList<T> exampleLike(Object example); 590 591 /** 592 * Case insensitive version of {@link #exampleLike(Object)} 593 */ 594 ExpressionList<T> iexampleLike(Object example); 595 596 /** 597 * Like - property like value where the value contains the SQL wild card 598 * characters % (percentage) and _ (underscore). 599 */ 600 ExpressionList<T> like(String propertyName, String value); 601 602 /** 603 * Case insensitive Like - property like value where the value contains the 604 * SQL wild card characters % (percentage) and _ (underscore). Typically uses 605 * a lower() function to make the expression case insensitive. 606 */ 607 ExpressionList<T> ilike(String propertyName, String value); 608 609 /** 610 * Starts With - property like value%. 611 */ 612 ExpressionList<T> startsWith(String propertyName, String value); 613 614 /** 615 * Case insensitive Starts With - property like value%. Typically uses a 616 * lower() function to make the expression case insensitive. 617 */ 618 ExpressionList<T> istartsWith(String propertyName, String value); 619 620 /** 621 * Ends With - property like %value. 622 */ 623 ExpressionList<T> endsWith(String propertyName, String value); 624 625 /** 626 * Case insensitive Ends With - property like %value. Typically uses a lower() 627 * function to make the expression case insensitive. 628 */ 629 ExpressionList<T> iendsWith(String propertyName, String value); 630 631 /** 632 * Contains - property like %value%. 633 */ 634 ExpressionList<T> contains(String propertyName, String value); 635 636 /** 637 * Case insensitive Contains - property like %value%. Typically uses a lower() 638 * function to make the expression case insensitive. 639 */ 640 ExpressionList<T> icontains(String propertyName, String value); 641 642 /** 643 * In - using a subQuery. 644 */ 645 ExpressionList<T> in(String propertyName, Query<?> subQuery); 646 647 /** 648 * In - property has a value in the array of values. 649 */ 650 ExpressionList<T> in(String propertyName, Object... values); 651 652 /** 653 * In - property has a value in the collection of values. 654 */ 655 ExpressionList<T> in(String propertyName, Collection<?> values); 656 657 /** 658 * Not In - property has a value in the array of values. 659 */ 660 ExpressionList<T> notIn(String propertyName, Object... values); 661 662 /** 663 * Not In - property has a value in the collection of values. 664 */ 665 ExpressionList<T> notIn(String propertyName, Collection<?> values); 666 667 /** 668 * Not In - using a subQuery. 669 */ 670 ExpressionList<T> notIn(String propertyName, Query<?> subQuery); 671 672 /** 673 * Exists expression 674 */ 675 ExpressionList<T> exists(Query<?> subQuery); 676 677 /** 678 * Not exists expression 679 */ 680 ExpressionList<T> notExists(Query<?> subQuery); 681 682 /** 683 * Id IN a list of id values. 684 */ 685 ExpressionList<T> idIn(List<?> idValues); 686 687 /** 688 * Id Equal to - ID property is equal to the value. 689 */ 690 ExpressionList<T> idEq(Object value); 691 692 /** 693 * All Equal - Map containing property names and their values. 694 * <p> 695 * Expression where all the property names in the map are equal to the 696 * corresponding value. 697 * </p> 698 * 699 * @param propertyMap 700 * a map keyed by property names. 701 */ 702 ExpressionList<T> allEq(Map<String, Object> propertyMap); 703 704 /** 705 * Add raw expression with a single parameter. 706 * <p> 707 * The raw expression should contain a single ? at the location of the 708 * parameter. 709 * </p> 710 * <p> 711 * When properties in the clause are fully qualified as table-column names 712 * then they are not translated. logical property name names (not fully 713 * qualified) will still be translated to their physical name. 714 * </p> 715 * 716 * <h4>Example:</h4> 717 * <pre>{@code 718 * 719 * // use a database function 720 * raw("add_days(orderDate, 10) < ?", someDate) 721 * 722 * }</pre> 723 */ 724 ExpressionList<T> raw(String raw, Object value); 725 726 /** 727 * Add raw expression with an array of parameters. 728 * <p> 729 * The raw expression should contain the same number of ? as there are 730 * parameters. 731 * </p> 732 * <p> 733 * When properties in the clause are fully qualified as table-column names 734 * then they are not translated. logical property name names (not fully 735 * qualified) will still be translated to their physical name. 736 * </p> 737 */ 738 ExpressionList<T> raw(String raw, Object[] values); 739 740 /** 741 * Add raw expression with no parameters. 742 * <p> 743 * When properties in the clause are fully qualified as table-column names 744 * then they are not translated. logical property name names (not fully 745 * qualified) will still be translated to their physical name. 746 * </p> 747 * 748 * <pre>{@code 749 * 750 * raw("orderQty < shipQty") 751 * 752 * }</pre> 753 */ 754 ExpressionList<T> raw(String raw); 755 756 /** 757 * And - join two expressions with a logical and. 758 */ 759 ExpressionList<T> and(Expression expOne, Expression expTwo); 760 761 /** 762 * Or - join two expressions with a logical or. 763 */ 764 ExpressionList<T> or(Expression expOne, Expression expTwo); 765 766 /** 767 * Negate the expression (prefix it with NOT). 768 */ 769 ExpressionList<T> not(Expression exp); 770 771 /** 772 * Return a list of expressions that will be joined by AND's. 773 */ 774 Junction<T> conjunction(); 775 776 /** 777 * Return a list of expressions that will be joined by OR's. 778 */ 779 Junction<T> disjunction(); 780 781 /** 782 * End a Conjunction or Disjunction returning the parent expression list. 783 * <p> 784 * Alternatively you can always use where() to return the top level expression 785 * list. 786 * </p> 787 */ 788 ExpressionList<T> endJunction(); 789 790}