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