001package io.ebean; 002 003import javax.annotation.Nonnull; 004import javax.annotation.Nullable; 005import javax.persistence.NonUniqueResultException; 006import java.sql.Connection; 007import java.sql.Timestamp; 008import java.util.List; 009import java.util.Map; 010import java.util.Optional; 011import java.util.Set; 012import java.util.function.Consumer; 013import java.util.function.Predicate; 014import java.util.stream.Stream; 015 016/** 017 * Object relational query for finding a List, Set, Map or single entity bean. 018 * <p> 019 * Example: Create the query using the API. 020 * </p> 021 * <p> 022 * <pre>{@code 023 * 024 * List<Order> orderList = DB.find(Order.class) 025 * .where() 026 * .like("customer.name","rob%") 027 * .gt("orderDate",lastWeek) 028 * .order("customer.id, id desc") 029 * .setMaxRows(50) 030 * .findList(); 031 * 032 * ... 033 * }</pre> 034 * <p> 035 * Example: The same query using the query language 036 * </p> 037 * <pre>{@code 038 * 039 * String oql = 040 * +" where customer.name like :custName and orderDate > :minOrderDate " 041 * +" order by customer.id, id desc " 042 * +" limit 50 "; 043 * 044 * List<Order> orderList = DB.createQuery(Order.class, oql) 045 * .setParameter("custName", "Rob%") 046 * .setParameter("minOrderDate", lastWeek) 047 * .findList(); 048 * ... 049 * }</pre> 050 * <h3>AutoTune</h3> 051 * <p> 052 * Ebean has built in support for "AutoTune". This is a mechanism where a query 053 * can be automatically tuned based on profiling information that is collected. 054 * </p> 055 * <p> 056 * This is effectively the same as automatically using select() and fetch() to 057 * build a query that will fetch all the data required by the application and no 058 * more. 059 * </p> 060 * <p> 061 * It is expected that AutoTune will be the default approach for many queries 062 * in a system. It is possibly not as useful where the result of a query is sent 063 * to a remote client or where there is some requirement for "Read Consistency" 064 * guarantees. 065 * </p> 066 * <h3>Query Language</h3> 067 * <p> 068 * <b>Partial Objects</b> 069 * </p> 070 * <p> 071 * The <em>find</em> and <em>fetch</em> clauses support specifying a list of 072 * properties to fetch. This results in objects that are "partially populated". 073 * If you try to get a property that was not populated a "lazy loading" query 074 * will automatically fire and load the rest of the properties of the bean (This 075 * is very similar behaviour as a reference object being "lazy loaded"). 076 * </p> 077 * <p> 078 * Partial objects can be saved just like fully populated objects. If you do 079 * this you should remember to include the <em>"Version"</em> property in the 080 * initial fetch. If you do not include a version property then optimistic 081 * concurrency checking will occur but only include the fetched properties. 082 * Refer to "ALL Properties/Columns" mode of Optimistic Concurrency checking. 083 * </p> 084 * <pre>{@code 085 * [ select [ ( * | {fetch properties} ) ] ] 086 * [ fetch {path} [ ( * | {fetch properties} ) ] ] 087 * [ where {predicates} ] 088 * [ order by {order by properties} ] 089 * [ limit {max rows} [ offset {first row} ] ] 090 * }</pre> 091 * <p> 092 * <b>SELECT</b> [ ( <i>*</i> | <i>{fetch properties}</i> ) ] 093 * </p> 094 * <p> 095 * With the select you can specify a list of properties to fetch. 096 * </p> 097 * <p> 098 * <b>FETCH</b> <b>{path}</b> [ ( <i>*</i> | <i>{fetch properties}</i> ) ] 099 * </p> 100 * <p> 101 * With the fetch you specify the associated property to fetch and populate. The 102 * path is a OneToOne, ManyToOne, OneToMany or ManyToMany property. 103 * </p> 104 * <p> 105 * For fetch of a path we can optionally specify a list of properties to fetch. 106 * If you do not specify a list of properties ALL the properties for that bean 107 * type are fetched. 108 * </p> 109 * <p> 110 * <b>WHERE</b> <b>{list of predicates}</b> 111 * </p> 112 * <p> 113 * The list of predicates which are joined by AND OR NOT ( and ). They can 114 * include named (or positioned) bind parameters. These parameters will need to 115 * be bound by {@link Query#setParameter(String, Object)}. 116 * </p> 117 * <p> 118 * <b>ORDER BY</b> <b>{order by properties}</b> 119 * </p> 120 * <p> 121 * The list of properties to order the result. You can include ASC (ascending) 122 * and DESC (descending) in the order by clause. 123 * </p> 124 * <p> 125 * <b>LIMIT</b> <b>{max rows}</b> [ OFFSET <i>{first row}</i> ] 126 * </p> 127 * <p> 128 * The limit offset specifies the max rows and first row to fetch. The offset is 129 * optional. 130 * </p> 131 * <h4>Examples of Ebean's Query Language</h4> 132 * <p> 133 * Find orders fetching its id, shipDate and status properties. Note that the id 134 * property is always fetched even if it is not included in the list of fetch 135 * properties. 136 * </p> 137 * <pre>{@code 138 * 139 * select (shipDate, status) 140 * 141 * }</pre> 142 * <p> 143 * Find orders with a named bind variable (that will need to be bound via 144 * {@link Query#setParameter(String, Object)}). 145 * </p> 146 * <pre>{@code 147 * 148 * where customer.name like :custLike 149 * 150 * }</pre> 151 * <p> 152 * Find orders and also fetch the customer with a named bind parameter. This 153 * will fetch and populate both the order and customer objects. 154 * </p> 155 * <pre>{@code 156 * 157 * fetch customer 158 * where customer.id = :custId 159 * 160 * }</pre> 161 * <p> 162 * Find orders and also fetch the customer, customer shippingAddress, order 163 * details and related product. Note that customer and product objects will be 164 * "Partial Objects" with only some of their properties populated. The customer 165 * objects will have their id, name and shipping address populated. The product 166 * objects (associated with each order detail) will have their id, sku and name 167 * populated. 168 * </p> 169 * <pre>{@code 170 * 171 * fetch customer (name) 172 * fetch customer.shippingAddress 173 * fetch details 174 * fetch details.product (sku, name) 175 * 176 * }</pre> 177 * 178 * @param <T> the type of Entity bean this query will fetch. 179 */ 180public interface Query<T> { 181 182 /** 183 * For update mode. 184 */ 185 enum ForUpdate { 186 /** 187 * Standard For update clause. 188 */ 189 BASE, 190 191 /** 192 * For update with No Wait option. 193 */ 194 NOWAIT, 195 196 /** 197 * For update with Skip Locked option. 198 */ 199 SKIPLOCKED 200 } 201 202 /** 203 * Set RawSql to use for this query. 204 */ 205 Query<T> setRawSql(RawSql rawSql); 206 207 /** 208 * Perform an 'As of' query using history tables to return the object graph 209 * as of a time in the past. 210 * <p> 211 * To perform this query the DB must have underlying history tables. 212 * </p> 213 * 214 * @param asOf the date time in the past at which you want to view the data 215 */ 216 Query<T> asOf(Timestamp asOf); 217 218 /** 219 * Execute the query against the draft set of tables. 220 */ 221 Query<T> asDraft(); 222 223 /** 224 * Convert the query to a DTO bean query. 225 * <p> 226 * We effectively use the underlying ORM query to build the SQL and then execute 227 * and map it into DTO beans. 228 */ 229 <D> DtoQuery<D> asDto(Class<D> dtoClass); 230 231 /** 232 * Convert the query to a UpdateQuery. 233 * <p> 234 * Typically this is used with query beans to covert a query bean 235 * query into an UpdateQuery like the examples below. 236 * </p> 237 * 238 * <pre>{@code 239 * 240 * int rowsUpdated = new QCustomer() 241 * .name.startsWith("Rob") 242 * .asUpdate() 243 * .set("active", false) 244 * .update();; 245 * 246 * }</pre> 247 * 248 * <pre>{@code 249 * 250 * int rowsUpdated = new QContact() 251 * .notes.note.startsWith("Make Inactive") 252 * .email.endsWith("@foo.com") 253 * .customer.id.equalTo(42) 254 * .asUpdate() 255 * .set("inactive", true) 256 * .setRaw("email = lower(email)") 257 * .update(); 258 * 259 * }</pre> 260 */ 261 UpdateQuery<T> asUpdate(); 262 263 /** 264 * Cancel the query execution if supported by the underlying database and 265 * driver. 266 * <p> 267 * This must be called from a different thread to the query executor. 268 * </p> 269 */ 270 void cancel(); 271 272 /** 273 * Return a copy of the query. 274 * <p> 275 * This is so that you can use a Query as a "prototype" for creating other 276 * query instances. You could create a Query with various where expressions 277 * and use that as a "prototype" - using this copy() method to create a new 278 * instance that you can then add other expressions then execute. 279 * </p> 280 */ 281 Query<T> copy(); 282 283 /** 284 * Specify the PersistenceContextScope to use for this query. 285 * <p/> 286 * When this is not set the 'default' configured on {@link io.ebean.config.DatabaseConfig#setPersistenceContextScope(PersistenceContextScope)} 287 * is used - this value defaults to {@link PersistenceContextScope#TRANSACTION}. 288 * <p/> 289 * Note that the same persistence Context is used for subsequent lazy loading and query join queries. 290 * <p/> 291 * Note that #findEach uses a 'per object graph' PersistenceContext so this scope is ignored for 292 * queries executed as #findIterate, #findEach, #findEachWhile. 293 * 294 * @param scope The scope to use for this query and subsequent lazy loading. 295 */ 296 Query<T> setPersistenceContextScope(PersistenceContextScope scope); 297 298 /** 299 * Set the index(es) to search for a document store which uses partitions. 300 * <p> 301 * For example, when executing a query against ElasticSearch with daily indexes we can 302 * explicitly specify the indexes to search against. 303 * </p> 304 * <pre>{@code 305 * 306 * // explicitly specify the indexes to search 307 * query.setDocIndexName("logstash-2016.11.5,logstash-2016.11.6") 308 * 309 * // search today's index 310 * query.setDocIndexName("$today") 311 * 312 * // search the last 3 days 313 * query.setDocIndexName("$last-3") 314 * 315 * }</pre> 316 * <p> 317 * If the indexName is specified with ${daily} e.g. "logstash-${daily}" ... then we can use 318 * $today and $last-x as the search docIndexName like the examples below. 319 * </p> 320 * <pre>{@code 321 * 322 * // search today's index 323 * query.setDocIndexName("$today") 324 * 325 * // search the last 3 days 326 * query.setDocIndexName("$last-3") 327 * 328 * }</pre> 329 * 330 * @param indexName The index or indexes to search against 331 * @return This query 332 */ 333 Query<T> setDocIndexName(String indexName); 334 335 /** 336 * Return the ExpressionFactory used by this query. 337 */ 338 ExpressionFactory getExpressionFactory(); 339 340 /** 341 * Returns true if this query was tuned by autoTune. 342 */ 343 boolean isAutoTuned(); 344 345 /** 346 * Explicitly specify whether to use AutoTune for this query. 347 * <p> 348 * If you do not call this method on a query the "Implicit AutoTune mode" is 349 * used to determine if AutoTune should be used for a given query. 350 * </p> 351 * <p> 352 * AutoTune can add additional fetch paths to the query and specify which 353 * properties are included for each path. If you have explicitly defined some 354 * fetch paths AutoTune will not remove them. 355 * </p> 356 */ 357 Query<T> setAutoTune(boolean autoTune); 358 359 /** 360 * Execute the query allowing properties with invalid JSON to be collected and not fail the query. 361 * <pre>{@code 362 * 363 * // fetch a bean with JSON content 364 * EBasicJsonList bean= DB.find(EBasicJsonList.class) 365 * .setId(42) 366 * .setAllowLoadErrors() // collect errors into bean state if we have invalid JSON 367 * .findOne(); 368 * 369 * 370 * // get the invalid JSON errors from the bean state 371 * Map<String, Exception> errors = server().getBeanState(bean).getLoadErrors(); 372 * 373 * // If this map is not empty tell we have invalid JSON 374 * // and should try and fix the JSON content or inform the user 375 * 376 * }</pre> 377 */ 378 Query<T> setAllowLoadErrors(); 379 380 /** 381 * Set the default lazy loading batch size to use. 382 * <p> 383 * When lazy loading is invoked on beans loaded by this query then this sets the 384 * batch size used to load those beans. 385 * 386 * @param lazyLoadBatchSize the number of beans to lazy load in a single batch 387 */ 388 Query<T> setLazyLoadBatchSize(int lazyLoadBatchSize); 389 390 /** 391 * Execute the query including soft deleted rows. 392 * <p> 393 * This means that Ebean will not add any predicates to the query for filtering out 394 * soft deleted rows. You can still add your own predicates for the deleted properties 395 * and effectively you have full control over the query to include or exclude soft deleted 396 * rows as needed for a given use case. 397 * </p> 398 */ 399 Query<T> setIncludeSoftDeletes(); 400 401 /** 402 * Disable read auditing for this query. 403 * <p> 404 * This is intended to be used when the query is not a user initiated query and instead 405 * part of the internal processing in an application to load a cache or document store etc. 406 * In these cases we don't want the query to be part of read auditing. 407 * </p> 408 */ 409 Query<T> setDisableReadAuditing(); 410 411 /** 412 * Specify the properties to fetch on the root level entity bean in comma delimited format. 413 * <p> 414 * The Id property is automatically included in the properties to fetch unless setDistinct(true) 415 * is set on the query. 416 * </p> 417 * <p> 418 * Use {@link #fetch(String, String)} to specify specific properties to fetch 419 * on other non-root level paths of the object graph. 420 * </p> 421 * <pre>{@code 422 * 423 * List<Customer> customers = DB.find(Customer.class) 424 * // Only fetch the customer id, name and status. 425 * // This is described as a "Partial Object" 426 * .select("name, status") 427 * .where.ilike("name", "rob%") 428 * .findList(); 429 * 430 * }</pre> 431 * 432 * @param fetchProperties the properties to fetch for this bean (* = all properties). 433 */ 434 Query<T> select(String fetchProperties); 435 436 /** 437 * Apply the fetchGroup which defines what part of the object graph to load. 438 */ 439 Query<T> select(FetchGroup<T> fetchGroup); 440 441 /** 442 * Specify a path to fetch eagerly including specific properties. 443 * <p> 444 * Ebean will endeavour to fetch this path using a SQL join. If Ebean determines that it can 445 * not use a SQL join (due to maxRows or because it would result in a cartesian product) Ebean 446 * will automatically convert this fetch query into a "query join" - i.e. use fetchQuery(). 447 * </p> 448 * <pre>{@code 449 * 450 * // query orders... 451 * List<Order> orders = DB.find(Order.class) 452 * // fetch the customer... 453 * // ... getting the customers name and phone number 454 * .fetch("customer", "name, phoneNumber") 455 * 456 * // ... also fetch the customers billing address (* = all properties) 457 * .fetch("customer.billingAddress", "*") 458 * .findList(); 459 * }</pre> 460 * <p> 461 * If columns is null or "*" then all columns/properties for that path are fetched. 462 * </p> 463 * <pre>{@code 464 * 465 * // fetch customers (their id, name and status) 466 * List<Customer> customers = DB.find(Customer.class) 467 * .select("name, status") 468 * .fetch("contacts", "firstName,lastName,email") 469 * .findList(); 470 * 471 * }</pre> 472 * 473 * @param path the property path we wish to fetch eagerly. 474 * @param fetchProperties properties of the associated bean that you want to include in the 475 * fetch (* means all properties, null also means all properties). 476 */ 477 Query<T> fetch(String path, String fetchProperties); 478 479 /** 480 * Fetch the path and properties using a "query join" (separate SQL query). 481 * <p> 482 * This is the same as: 483 * </p> 484 * <pre>{@code 485 * 486 * fetch(path, fetchProperties, new FetchConfig().query()) 487 * 488 * }</pre> 489 * <p> 490 * This would be used instead of a fetch() when we use a separate SQL query to fetch this 491 * part of the object graph rather than a SQL join. 492 * </p> 493 * <p> 494 * We might typically get a performance benefit when the path to fetch is a OneToMany 495 * or ManyToMany, the 'width' of the 'root bean' is wide and the cardinality of the many 496 * is high. 497 * </p> 498 * 499 * @param path the property path we wish to fetch eagerly. 500 * @param fetchProperties properties of the associated bean that you want to include in the 501 * fetch (* means all properties, null also means all properties). 502 */ 503 Query<T> fetchQuery(String path, String fetchProperties); 504 505 /** 506 * Fetch the path and properties using L2 bean cache. 507 * 508 * @param path The path of the beans we are fetching from L2 cache. 509 * @param fetchProperties The properties that should be loaded. 510 */ 511 Query<T> fetchCache(String path, String fetchProperties); 512 513 /** 514 * Fetch the path and properties lazily (via batch lazy loading). 515 * <p> 516 * This is the same as: 517 * </p> 518 * <pre>{@code 519 * 520 * fetch(path, fetchProperties, new FetchConfig().lazy()) 521 * 522 * }</pre> 523 * <p> 524 * The reason for using fetchLazy() is to either: 525 * </p> 526 * <ul> 527 * <li>Control/tune what is fetched as part of lazy loading</li> 528 * <li>Make use of the L2 cache, build this part of the graph from L2 cache</li> 529 * </ul> 530 * 531 * @param path the property path we wish to fetch lazily. 532 * @param fetchProperties properties of the associated bean that you want to include in the 533 * fetch (* means all properties, null also means all properties). 534 */ 535 Query<T> fetchLazy(String path, String fetchProperties); 536 537 /** 538 * Additionally specify a FetchConfig to use a separate query or lazy loading 539 * to load this path. 540 * <pre>{@code 541 * 542 * // fetch customers (their id, name and status) 543 * List<Customer> customers = DB.find(Customer.class) 544 * .select("name, status") 545 * .fetch("contacts", "firstName,lastName,email", new FetchConfig().lazy(10)) 546 * .findList(); 547 * 548 * }</pre> 549 * 550 * @param path the property path we wish to fetch eagerly. 551 */ 552 Query<T> fetch(String path, String fetchProperties, FetchConfig fetchConfig); 553 554 /** 555 * Specify a path to fetch eagerly including all its properties. 556 * <p> 557 * Ebean will endeavour to fetch this path using a SQL join. If Ebean determines that it can 558 * not use a SQL join (due to maxRows or because it would result in a cartesian product) Ebean 559 * will automatically convert this fetch query into a "query join" - i.e. use fetchQuery(). 560 * </p> 561 * <pre>{@code 562 * 563 * // fetch customers (their id, name and status) 564 * List<Customer> customers = DB.find(Customer.class) 565 * // eager fetch the contacts 566 * .fetch("contacts") 567 * .findList(); 568 * 569 * }</pre> 570 * 571 * @param path the property path we wish to fetch eagerly. 572 */ 573 Query<T> fetch(String path); 574 575 /** 576 * Fetch the path eagerly using a "query join" (separate SQL query). 577 * <p> 578 * This is the same as: 579 * </p> 580 * <pre>{@code 581 * 582 * fetch(path, new FetchConfig().query()) 583 * 584 * }</pre> 585 * <p> 586 * This would be used instead of a fetch() when we use a separate SQL query to fetch this 587 * part of the object graph rather than a SQL join. 588 * </p> 589 * <p> 590 * We might typically get a performance benefit when the path to fetch is a OneToMany 591 * or ManyToMany, the 'width' of the 'root bean' is wide and the cardinality of the many 592 * is high. 593 * </p> 594 * 595 * @param path the property path we wish to fetch eagerly 596 */ 597 Query<T> fetchQuery(String path); 598 599 /** 600 * Fetch the path eagerly using L2 cache. 601 */ 602 Query<T> fetchCache(String path); 603 604 /** 605 * Fetch the path lazily (via batch lazy loading). 606 * <p> 607 * This is the same as: 608 * </p> 609 * <pre>{@code 610 * 611 * fetch(path, new FetchConfig().lazy()) 612 * 613 * }</pre> 614 * <p> 615 * The reason for using fetchLazy() is to either: 616 * </p> 617 * <ul> 618 * <li>Control/tune what is fetched as part of lazy loading</li> 619 * <li>Make use of the L2 cache, build this part of the graph from L2 cache</li> 620 * </ul> 621 * 622 * @param path the property path we wish to fetch lazily. 623 */ 624 Query<T> fetchLazy(String path); 625 626 /** 627 * Additionally specify a JoinConfig to specify a "query join" and or define 628 * the lazy loading query. 629 * <pre>{@code 630 * 631 * // fetch customers (their id, name and status) 632 * List<Customer> customers = DB.find(Customer.class) 633 * // lazy fetch contacts with a batch size of 100 634 * .fetch("contacts", new FetchConfig().lazy(100)) 635 * .findList(); 636 * 637 * }</pre> 638 */ 639 Query<T> fetch(String path, FetchConfig fetchConfig); 640 641 /** 642 * Apply the path properties replacing the select and fetch clauses. 643 * <p> 644 * This is typically used when the FetchPath is applied to both the query and the JSON output. 645 * </p> 646 */ 647 Query<T> apply(FetchPath fetchPath); 648 649 /** 650 * Execute the query using the given transaction. 651 */ 652 Query<T> usingTransaction(Transaction transaction); 653 654 /** 655 * Execute the query using the given connection. 656 */ 657 Query<T> usingConnection(Connection connection); 658 659 /** 660 * Execute the query using the given database. 661 */ 662 Query<T> usingDatabase(Database database); 663 664 /** 665 * Execute the query returning the list of Id's. 666 * <p> 667 * This query will execute against the Database that was used to create it. 668 * </p> 669 */ 670 @Nonnull 671 <A> List<A> findIds(); 672 673 /** 674 * Execute the query iterating over the results. 675 * <p> 676 * Note that findIterate (and findEach and findEachWhile) uses a "per graph" 677 * persistence context scope and adjusts jdbc fetch buffer size for large 678 * queries. As such it is better to use findList for small queries. 679 * </p> 680 * <p> 681 * Remember that with {@link QueryIterator} you must call {@link QueryIterator#close()} 682 * when you have finished iterating the results (typically in a finally block). 683 * </p> 684 * <p> 685 * findEach() and findEachWhile() are preferred to findIterate() as they ensure 686 * the jdbc statement and resultSet are closed at the end of the iteration. 687 * </p> 688 * <p> 689 * This query will execute against the Database that was used to create it. 690 * </p> 691 * <pre>{@code 692 * 693 * Query<Customer> query = DB.find(Customer.class) 694 * .where().eq("status", Status.NEW) 695 * .order().asc("id"); 696 * 697 * // use try with resources to ensure QueryIterator is closed 698 * 699 * try (QueryIterator<Customer> it = query.findIterate()) { 700 * while (it.hasNext()) { 701 * Customer customer = it.next(); 702 * // do something with customer ... 703 * } 704 * } 705 * 706 * }</pre> 707 */ 708 @Nonnull 709 QueryIterator<T> findIterate(); 710 711 /** 712 * Execute the query returning the result as a Stream. 713 * <p> 714 * Note that this can support very large queries iterating 715 * any number of results. To do so internally it can use 716 * multiple persistence contexts. 717 * </p> 718 * <pre>{@code 719 * 720 * // use try with resources to ensure Stream is closed 721 * 722 * try (Stream<Customer> stream = query.findStream()) { 723 * stream 724 * .map(...) 725 * .collect(...); 726 * } 727 * 728 * }</pre> 729 */ 730 @Nonnull 731 Stream<T> findStream(); 732 733 /** 734 * Deprecated - migrate to findStream. 735 * <p> 736 * Execute the query returning the result as a Stream. 737 * <p> 738 * Note that this uses multiple persistence contexts such that we can use 739 * it with a large number of results. 740 * </p> 741 * <pre>{@code 742 * 743 * // use try with resources to ensure Stream is closed 744 * 745 * try (Stream<Customer> stream = query.findLargeStream()) { 746 * stream 747 * .map(...) 748 * .collect(...); 749 * } 750 * 751 * }</pre> 752 */ 753 @Nonnull 754 @Deprecated 755 Stream<T> findLargeStream(); 756 757 /** 758 * Execute the query processing the beans one at a time. 759 * <p> 760 * This method is appropriate to process very large query results as the 761 * beans are consumed one at a time and do not need to be held in memory 762 * (unlike #findList #findSet etc) 763 * </p> 764 * <p> 765 * Note that findEach (and findEachWhile and findIterate) uses a "per graph" 766 * persistence context scope and adjusts jdbc fetch buffer size for large 767 * queries. As such it is better to use findList for small queries. 768 * </p> 769 * <p> 770 * Note that internally Ebean can inform the JDBC driver that it is expecting larger 771 * resultSet and specifically for MySQL this hint is required to stop it's JDBC driver 772 * from buffering the entire resultSet. As such, for smaller resultSets findList() is 773 * generally preferable. 774 * </p> 775 * <p> 776 * Compared with #findEachWhile this will always process all the beans where as 777 * #findEachWhile provides a way to stop processing the query result early before 778 * all the beans have been read. 779 * </p> 780 * <p> 781 * This method is functionally equivalent to findIterate() but instead of using an 782 * iterator uses the Consumer interface which is better suited to use with Java8 closures. 783 * </p> 784 * <pre>{@code 785 * 786 * DB.find(Customer.class) 787 * .where().eq("status", Status.NEW) 788 * .order().asc("id") 789 * .findEach((Customer customer) -> { 790 * 791 * // do something with customer 792 * System.out.println("-- visit " + customer); 793 * }); 794 * 795 * }</pre> 796 * 797 * @param consumer the consumer used to process the queried beans. 798 */ 799 void findEach(Consumer<T> consumer); 800 801 /** 802 * Execute the query using callbacks to a visitor to process the resulting 803 * beans one at a time. 804 * <p> 805 * Note that findEachWhile (and findEach and findIterate) uses a "per graph" 806 * persistence context scope and adjusts jdbc fetch buffer size for large 807 * queries. As such it is better to use findList for small queries. 808 * </p> 809 * <p> 810 * This method is functionally equivalent to findIterate() but instead of using an 811 * iterator uses the Predicate (SAM) interface which is better suited to use with Java8 closures. 812 * </p> 813 * <pre>{@code 814 * 815 * DB.find(Customer.class) 816 * .fetch("contacts", new FetchConfig().query(2)) 817 * .where().eq("status", Status.NEW) 818 * .order().asc("id") 819 * .setMaxRows(2000) 820 * .findEachWhile((Customer customer) -> { 821 * 822 * // do something with customer 823 * System.out.println("-- visit " + customer); 824 * 825 * // return true to continue processing or false to stop 826 * return (customer.getId() < 40); 827 * }); 828 * 829 * }</pre> 830 * 831 * @param consumer the consumer used to process the queried beans. 832 */ 833 void findEachWhile(Predicate<T> consumer); 834 835 /** 836 * Execute the query returning the list of objects. 837 * <p> 838 * This query will execute against the Database that was used to create it. 839 * </p> 840 * <pre>{@code 841 * 842 * List<Customer> customers = DB.find(Customer.class) 843 * .where().ilike("name", "rob%") 844 * .findList(); 845 * 846 * }</pre> 847 */ 848 @Nonnull 849 List<T> findList(); 850 851 /** 852 * Execute the query returning the set of objects. 853 * <p> 854 * This query will execute against the Database that was used to create it. 855 * </p> 856 * <pre>{@code 857 * 858 * Set<Customer> customers = DB.find(Customer.class) 859 * .where().ilike("name", "rob%") 860 * .findSet(); 861 * 862 * }</pre> 863 */ 864 @Nonnull 865 Set<T> findSet(); 866 867 /** 868 * Execute the query returning a map of the objects. 869 * <p> 870 * This query will execute against the Database that was used to create it. 871 * </p> 872 * <p> 873 * You can use setMapKey() so specify the property values to be used as keys 874 * on the map. If one is not specified then the id property is used. 875 * </p> 876 * <pre>{@code 877 * 878 * Map<String, Product> map = DB.find(Product.class) 879 * .setMapKey("sku") 880 * .findMap(); 881 * 882 * }</pre> 883 */ 884 @Nonnull 885 <K> Map<K, T> findMap(); 886 887 /** 888 * Execute the query returning a list of values for a single property. 889 * <p> 890 * <h3>Example 1:</h3> 891 * <pre>{@code 892 * 893 * List<String> names = 894 * DB.find(Customer.class) 895 * .select("name") 896 * .order().asc("name") 897 * .findSingleAttributeList(); 898 * 899 * }</pre> 900 * <p> 901 * <h3>Example 2:</h3> 902 * <pre>{@code 903 * 904 * List<String> names = 905 * DB.find(Customer.class) 906 * .setDistinct(true) 907 * .select("name") 908 * .where().eq("status", Customer.Status.NEW) 909 * .order().asc("name") 910 * .setMaxRows(100) 911 * .findSingleAttributeList(); 912 * 913 * }</pre> 914 * 915 * @return the list of values for the selected property 916 */ 917 @Nonnull 918 <A> List<A> findSingleAttributeList(); 919 920 /** 921 * Execute a query returning a single value of a single property/column. 922 * <p> 923 * <pre>{@code 924 * 925 * String name = 926 * DB.find(Customer.class) 927 * .select("name") 928 * .where().eq("id", 42) 929 * .findSingleAttribute(); 930 * 931 * }</pre> 932 */ 933 <A> A findSingleAttribute(); 934 935 /** 936 * Return true if this is countDistinct query. 937 */ 938 boolean isCountDistinct(); 939 940 /** 941 * Execute the query returning true if a row is found. 942 * <p> 943 * The query is executed using max rows of 1 and will only select the id property. 944 * This method is really just a convenient way to optimise a query to perform a 945 * 'does a row exist in the db' check. 946 * </p> 947 * 948 * <h2>Example using a query bean:</h2> 949 * <pre>{@code 950 * 951 * boolean userExists = 952 * new QContact() 953 * .email.equalTo("[email protected]") 954 * .exists(); 955 * 956 * }</pre> 957 * 958 * <h2>Example:</h2> 959 * <pre>{@code 960 * 961 * boolean userExists = query() 962 * .where().eq("email", "[email protected]") 963 * .exists(); 964 * 965 * }</pre> 966 * 967 * @return True if the query finds a matching row in the database 968 */ 969 boolean exists(); 970 971 /** 972 * Execute the query returning either a single bean or null (if no matching 973 * bean is found). 974 * <p> 975 * If more than 1 row is found for this query then a NonUniqueResultException is 976 * thrown. 977 * </p> 978 * <p> 979 * This is useful when your predicates dictate that your query should only 980 * return 0 or 1 results. 981 * </p> 982 * <pre>{@code 983 * 984 * // assuming the sku of products is unique... 985 * Product product = DB.find(Product.class) 986 * .where().eq("sku", "aa113") 987 * .findOne(); 988 * ... 989 * }</pre> 990 * <p> 991 * It is also useful with finding objects by their id when you want to specify 992 * further join information. 993 * </p> 994 * <pre>{@code 995 * 996 * // Fetch order 1 and additionally fetch join its order details... 997 * Order order = DB.find(Order.class) 998 * .setId(1) 999 * .fetch("details") 1000 * .findOne(); 1001 * 1002 * // the order details were eagerly loaded 1003 * List<OrderDetail> details = order.getDetails(); 1004 * ... 1005 * }</pre> 1006 * 1007 * @throws NonUniqueResultException if more than one result was found 1008 */ 1009 @Nullable 1010 T findOne(); 1011 1012 /** 1013 * Execute the query returning an optional bean. 1014 */ 1015 @Nonnull 1016 Optional<T> findOneOrEmpty(); 1017 1018 /** 1019 * Return versions of a @History entity bean. 1020 * <p> 1021 * Note that this query will work against view based history implementations 1022 * but not sql2011 standards based implementations that require a start and 1023 * end timestamp to be specified. 1024 * </p> 1025 * <p> 1026 * Generally this query is expected to be a find by id or unique predicates query. 1027 * It will execute the query against the history returning the versions of the bean. 1028 * </p> 1029 */ 1030 @Nonnull 1031 List<Version<T>> findVersions(); 1032 1033 /** 1034 * Return versions of a @History entity bean between the 2 timestamps. 1035 * <p> 1036 * Generally this query is expected to be a find by id or unique predicates query. 1037 * It will execute the query against the history returning the versions of the bean. 1038 * </p> 1039 */ 1040 @Nonnull 1041 List<Version<T>> findVersionsBetween(Timestamp start, Timestamp end); 1042 1043 /** 1044 * Execute as a delete query deleting the 'root level' beans that match the predicates 1045 * in the query. 1046 * <p> 1047 * Note that if the query includes joins then the generated delete statement may not be 1048 * optimal depending on the database platform. 1049 * </p> 1050 * 1051 * @return the number of beans/rows that were deleted. 1052 */ 1053 int delete(); 1054 1055 /** 1056 * Execute as a delete query returning the number of rows deleted using the given transaction. 1057 * <p> 1058 * Note that if the query includes joins then the generated delete statement may not be 1059 * optimal depending on the database platform. 1060 * </p> 1061 * 1062 * @return the number of beans/rows that were deleted. 1063 */ 1064 int delete(Transaction transaction); 1065 1066 /** 1067 * Execute the UpdateQuery returning the number of rows updated. 1068 * 1069 * @return the number of beans/rows updated. 1070 */ 1071 int update(); 1072 1073 /** 1074 * Execute the UpdateQuery returning the number of rows updated using the given transaction. 1075 * 1076 * @return the number of beans/rows updated. 1077 */ 1078 int update(Transaction transaction); 1079 1080 /** 1081 * Return the count of entities this query should return. 1082 * <p> 1083 * This is the number of 'top level' or 'root level' entities. 1084 * </p> 1085 */ 1086 int findCount(); 1087 1088 /** 1089 * Execute find row count query in a background thread. 1090 * <p> 1091 * This returns a Future object which can be used to cancel, check the 1092 * execution status (isDone etc) and get the value (with or without a 1093 * timeout). 1094 * </p> 1095 * 1096 * @return a Future object for the row count query 1097 */ 1098 @Nonnull 1099 FutureRowCount<T> findFutureCount(); 1100 1101 /** 1102 * Execute find Id's query in a background thread. 1103 * <p> 1104 * This returns a Future object which can be used to cancel, check the 1105 * execution status (isDone etc) and get the value (with or without a 1106 * timeout). 1107 * </p> 1108 * 1109 * @return a Future object for the list of Id's 1110 */ 1111 @Nonnull 1112 FutureIds<T> findFutureIds(); 1113 1114 /** 1115 * Execute find list query in a background thread. 1116 * <p> 1117 * This query will execute in it's own PersistenceContext and using its own transaction. 1118 * What that means is that it will not share any bean instances with other queries. 1119 * </p> 1120 * 1121 * @return a Future object for the list result of the query 1122 */ 1123 @Nonnull 1124 FutureList<T> findFutureList(); 1125 1126 /** 1127 * Return a PagedList for this query using firstRow and maxRows. 1128 * <p> 1129 * The benefit of using this over findList() is that it provides functionality to get the 1130 * total row count etc. 1131 * </p> 1132 * <p> 1133 * If maxRows is not set on the query prior to calling findPagedList() then a 1134 * PersistenceException is thrown. 1135 * </p> 1136 * <pre>{@code 1137 * 1138 * PagedList<Order> pagedList = DB.find(Order.class) 1139 * .setFirstRow(50) 1140 * .setMaxRows(20) 1141 * .findPagedList(); 1142 * 1143 * // fetch the total row count in the background 1144 * pagedList.loadRowCount(); 1145 * 1146 * List<Order> orders = pagedList.getList(); 1147 * int totalRowCount = pagedList.getTotalRowCount(); 1148 * 1149 * }</pre> 1150 * 1151 * @return The PagedList 1152 */ 1153 @Nonnull 1154 PagedList<T> findPagedList(); 1155 1156 /** 1157 * Set a named bind parameter. Named parameters have a colon to prefix the name. 1158 * <pre>{@code 1159 * 1160 * // a query with a named parameter 1161 * String oql = "find order where status = :orderStatus"; 1162 * 1163 * List<Order> list = DB.find(Order.class, oql) 1164 * .setParameter("orderStatus", OrderStatus.NEW) 1165 * .findList(); 1166 * 1167 * }</pre> 1168 * 1169 * @param name the parameter name 1170 * @param value the parameter value 1171 */ 1172 Query<T> setParameter(String name, Object value); 1173 1174 /** 1175 * Set an ordered bind parameter according to its position. Note that the 1176 * position starts at 1 to be consistent with JDBC PreparedStatement. You need 1177 * to set a parameter value for each ? you have in the query. 1178 * <pre>{@code 1179 * 1180 * // a query with a positioned parameter 1181 * String oql = "where status = ? order by id desc"; 1182 * 1183 * List<Order> list = DB.createQuery(Order.class, oql) 1184 * .setParameter(1, OrderStatus.NEW) 1185 * .findList(); 1186 * 1187 * }</pre> 1188 * 1189 * @param position the parameter bind position starting from 1 (not 0) 1190 * @param value the parameter bind value. 1191 */ 1192 Query<T> setParameter(int position, Object value); 1193 1194 /** 1195 * Bind the next positioned parameter. 1196 * 1197 * <pre>{@code 1198 * 1199 * // a query with a positioned parameters 1200 * String oql = "where status = ? and name = ?"; 1201 * 1202 * List<Order> list = DB.createQuery(Order.class, oql) 1203 * .setParameter(OrderStatus.NEW) 1204 * .setParameter("Rob") 1205 * .findList(); 1206 * 1207 * }</pre> 1208 */ 1209 Query<T> setParameter(Object value); 1210 1211 /** 1212 * Bind all the positioned parameters. 1213 * <p> 1214 * A convenience for multiple calls to {@link #setParameter(Object)} 1215 */ 1216 Query<T> setParameters(Object... values); 1217 1218 /** 1219 * Set the Id value to query. This is used with findOne(). 1220 * <p> 1221 * You can use this to have further control over the query. For example adding 1222 * fetch joins. 1223 * </p> 1224 * <pre>{@code 1225 * 1226 * Order order = DB.find(Order.class) 1227 * .setId(1) 1228 * .fetch("details") 1229 * .findOne(); 1230 * 1231 * // the order details were eagerly fetched 1232 * List<OrderDetail> details = order.getDetails(); 1233 * 1234 * }</pre> 1235 */ 1236 Query<T> setId(Object id); 1237 1238 /** 1239 * Return the Id value. 1240 */ 1241 Object getId(); 1242 1243 /** 1244 * Add a single Expression to the where clause returning the query. 1245 * <pre>{@code 1246 * 1247 * List<Order> newOrders = DB.find(Order.class) 1248 * .where().eq("status", Order.NEW) 1249 * .findList(); 1250 * ... 1251 * 1252 * }</pre> 1253 */ 1254 Query<T> where(Expression expression); 1255 1256 /** 1257 * Add Expressions to the where clause with the ability to chain on the 1258 * ExpressionList. You can use this for adding multiple expressions to the 1259 * where clause. 1260 * <pre>{@code 1261 * 1262 * List<Order> orders = DB.find(Order.class) 1263 * .where() 1264 * .eq("status", Order.NEW) 1265 * .ilike("customer.name","rob%") 1266 * .findList(); 1267 * 1268 * }</pre> 1269 * 1270 * @return The ExpressionList for adding expressions to. 1271 * @see Expr 1272 */ 1273 ExpressionList<T> where(); 1274 1275 /** 1276 * Add Full text search expressions for Document store queries. 1277 * <p> 1278 * This is currently ElasticSearch only and provides the full text 1279 * expressions such as Match and Multi-Match. 1280 * </p> 1281 * <p> 1282 * This automatically makes this query a "Doc Store" query and will execute 1283 * against the document store (ElasticSearch). 1284 * </p> 1285 * <p> 1286 * Expressions added here are added to the "query" section of an ElasticSearch 1287 * query rather than the "filter" section. 1288 * </p> 1289 * <p> 1290 * Expressions added to the where() are added to the "filter" section of an 1291 * ElasticSearch query. 1292 * </p> 1293 */ 1294 ExpressionList<T> text(); 1295 1296 /** 1297 * This applies a filter on the 'many' property list rather than the root 1298 * level objects. 1299 * <p> 1300 * Typically you will use this in a scenario where the cardinality is high on 1301 * the 'many' property you wish to join to. Say you want to fetch customers 1302 * and their associated orders... but instead of getting all the orders for 1303 * each customer you only want to get the new orders they placed since last 1304 * week. In this case you can use filterMany() to filter the orders. 1305 * </p> 1306 * <pre>{@code 1307 * 1308 * List<Customer> list = DB.find(Customer.class) 1309 * .fetch("orders") 1310 * .where().ilike("name", "rob%") 1311 * .filterMany("orders").eq("status", Order.Status.NEW).gt("orderDate", lastWeek) 1312 * .findList(); 1313 * 1314 * }</pre> 1315 * <p> 1316 * Please note you have to be careful that you add expressions to the correct 1317 * expression list - as there is one for the 'root level' and one for each 1318 * filterMany that you have. 1319 * </p> 1320 * 1321 * @param propertyName the name of the many property that you want to have a filter on. 1322 * @return the expression list that you add filter expressions for the many to. 1323 */ 1324 ExpressionList<T> filterMany(String propertyName); 1325 1326 /** 1327 * Add Expressions to the Having clause return the ExpressionList. 1328 * <p> 1329 * Currently only beans based on raw sql will use the having clause. 1330 * </p> 1331 * <p> 1332 * Note that this returns the ExpressionList (so you can add multiple 1333 * expressions to the query in a fluent API way). 1334 * </p> 1335 * 1336 * @return The ExpressionList for adding more expressions to. 1337 * @see Expr 1338 */ 1339 ExpressionList<T> having(); 1340 1341 /** 1342 * Add an expression to the having clause returning the query. 1343 * <p> 1344 * Currently only beans based on raw sql will use the having clause. 1345 * </p> 1346 * <p> 1347 * This is similar to {@link #having()} except it returns the query rather 1348 * than the ExpressionList. This is useful when you want to further specify 1349 * something on the query. 1350 * </p> 1351 * 1352 * @param addExpressionToHaving the expression to add to the having clause. 1353 * @return the Query object 1354 */ 1355 Query<T> having(Expression addExpressionToHaving); 1356 1357 /** 1358 * Set the order by clause replacing the existing order by clause if there is 1359 * one. 1360 * <p> 1361 * This follows SQL syntax using commas between each property with the 1362 * optional asc and desc keywords representing ascending and descending order 1363 * respectively. 1364 */ 1365 Query<T> orderBy(String orderByClause); 1366 1367 /** 1368 * Set the order by clause replacing the existing order by clause if there is 1369 * one. 1370 * <p> 1371 * This follows SQL syntax using commas between each property with the 1372 * optional asc and desc keywords representing ascending and descending order 1373 * respectively. 1374 */ 1375 Query<T> order(String orderByClause); 1376 1377 /** 1378 * Return the OrderBy so that you can append an ascending or descending 1379 * property to the order by clause. 1380 * <p> 1381 * This will never return a null. If no order by clause exists then an 'empty' 1382 * OrderBy object is returned. 1383 * <p> 1384 * This is the same as <code>orderBy()</code> 1385 */ 1386 OrderBy<T> order(); 1387 1388 /** 1389 * Return the OrderBy so that you can append an ascending or descending 1390 * property to the order by clause. 1391 * <p> 1392 * This will never return a null. If no order by clause exists then an 'empty' 1393 * OrderBy object is returned. 1394 * <p> 1395 * This is the same as <code>order()</code> 1396 */ 1397 OrderBy<T> orderBy(); 1398 1399 /** 1400 * Set an OrderBy object to replace any existing OrderBy clause. 1401 */ 1402 Query<T> setOrder(OrderBy<T> orderBy); 1403 1404 /** 1405 * Set an OrderBy object to replace any existing OrderBy clause. 1406 */ 1407 Query<T> setOrderBy(OrderBy<T> orderBy); 1408 1409 /** 1410 * Set whether this query uses DISTINCT. 1411 * <p> 1412 * The select() clause MUST be specified when setDistinct(true) is set. The reason for this is that 1413 * generally ORM queries include the "id" property and this doesn't make sense for distinct queries. 1414 * </p> 1415 * <pre>{@code 1416 * 1417 * List<Customer> customers = 1418 * DB.find(Customer.class) 1419 * .setDistinct(true) 1420 * .select("name") 1421 * .findList(); 1422 * 1423 * }</pre> 1424 */ 1425 Query<T> setDistinct(boolean isDistinct); 1426 1427 /** 1428 * Extended version for setDistinct in conjunction with "findSingleAttributeList"; 1429 * 1430 * <pre>{@code 1431 * 1432 * List<CountedValue<Order.Status>> orderStatusCount = 1433 * 1434 * DB.find(Order.class) 1435 * .select("status") 1436 * .where() 1437 * .gt("orderDate", LocalDate.now().minusMonths(3)) 1438 * 1439 * // fetch as single attribute with a COUNT 1440 * .setCountDistinct(CountDistinctOrder.COUNT_DESC_ATTR_ASC) 1441 * .findSingleAttributeList(); 1442 * 1443 * for (CountedValue<Order.Status> entry : orderStatusCount) { 1444 * System.out.println(" count:" + entry.getCount()+" orderStatus:" + entry.getValue() ); 1445 * } 1446 * 1447 * // produces 1448 * 1449 * count:3 orderStatus:NEW 1450 * count:1 orderStatus:SHIPPED 1451 * count:1 orderStatus:COMPLETE 1452 * 1453 * }</pre> 1454 */ 1455 Query<T> setCountDistinct(CountDistinctOrder orderBy); 1456 1457 /** 1458 * Return the first row value. 1459 */ 1460 int getFirstRow(); 1461 1462 /** 1463 * Set the first row to return for this query. 1464 * 1465 * @param firstRow the first row to include in the query result. 1466 */ 1467 Query<T> setFirstRow(int firstRow); 1468 1469 /** 1470 * Return the max rows for this query. 1471 */ 1472 int getMaxRows(); 1473 1474 /** 1475 * Set the maximum number of rows to return in the query. 1476 * 1477 * @param maxRows the maximum number of rows to return in the query. 1478 */ 1479 Query<T> setMaxRows(int maxRows); 1480 1481 /** 1482 * Set the property to use as keys for a map. 1483 * <p> 1484 * If no property is set then the id property is used. 1485 * </p> 1486 * <pre>{@code 1487 * 1488 * // Assuming sku is unique for products... 1489 * 1490 * Map<String,Product> productMap = DB.find(Product.class) 1491 * .setMapKey("sku") // sku map keys... 1492 * .findMap(); 1493 * 1494 * }</pre> 1495 * 1496 * @param mapKey the property to use as keys for a map. 1497 */ 1498 Query<T> setMapKey(String mapKey); 1499 1500 /** 1501 * Set this to false to not use the bean cache. 1502 * <p> 1503 * This method is now superseded by {@link #setBeanCacheMode(CacheMode)} 1504 * which provides more explicit options controlled bean cache use. 1505 * </p> 1506 * <p> 1507 * This method is likely to be deprecated in the future with migration 1508 * over to setUseBeanCache(). 1509 * </p> 1510 */ 1511 default Query<T> setUseCache(boolean useCache) { 1512 return setBeanCacheMode(useCache ? CacheMode.ON : CacheMode.OFF); 1513 } 1514 1515 /** 1516 * Set the mode to use the bean cache when executing this query. 1517 * <p> 1518 * By default "find by id" and "find by natural key" will use the bean cache 1519 * when bean caching is enabled. Setting this to false means that the query 1520 * will not use the bean cache and instead hit the database. 1521 * </p> 1522 * <p> 1523 * By default findList() with natural keys will not use the bean cache. In that 1524 * case we need to explicitly use the bean cache. 1525 * </p> 1526 */ 1527 Query<T> setBeanCacheMode(CacheMode beanCacheMode); 1528 1529 /** 1530 * Set the {@link CacheMode} to use the query for executing this query. 1531 */ 1532 Query<T> setUseQueryCache(CacheMode queryCacheMode); 1533 1534 /** 1535 * Calls {@link #setUseQueryCache(CacheMode)} with <code>ON</code> or <code>OFF</code>. 1536 */ 1537 default Query<T> setUseQueryCache(boolean enabled) { 1538 return setUseQueryCache(enabled ? CacheMode.ON : CacheMode.OFF); 1539 } 1540 1541 /** 1542 * Set the profile location of this query. This is used to relate query execution metrics 1543 * back to a location like a specific line of code. 1544 */ 1545 Query<T> setProfileLocation(ProfileLocation profileLocation); 1546 1547 /** 1548 * Set a label on the query. 1549 * <p> 1550 * This label can be used to help identify query performance metrics but we can also use 1551 * profile location enhancement on Finders so for some that would be a better option. 1552 * </p> 1553 */ 1554 Query<T> setLabel(String label); 1555 1556 /** 1557 * Set to true if this query should execute against the doc store. 1558 * <p> 1559 * When setting this you may also consider disabling lazy loading. 1560 * </p> 1561 */ 1562 Query<T> setUseDocStore(boolean useDocStore); 1563 1564 /** 1565 * When set to true when you want the returned beans to be read only. 1566 */ 1567 Query<T> setReadOnly(boolean readOnly); 1568 1569 /** 1570 * Will be deprecated - migrate to use setBeanCacheMode(CacheMode.RECACHE). 1571 * <p> 1572 * When set to true all the beans from this query are loaded into the bean cache. 1573 */ 1574 Query<T> setLoadBeanCache(boolean loadBeanCache); 1575 1576 /** 1577 * Set a timeout on this query. 1578 * <p> 1579 * This will typically result in a call to setQueryTimeout() on a 1580 * preparedStatement. If the timeout occurs an exception will be thrown - this 1581 * will be a SQLException wrapped up in a PersistenceException. 1582 * </p> 1583 * 1584 * @param secs the query timeout limit in seconds. Zero means there is no limit. 1585 */ 1586 Query<T> setTimeout(int secs); 1587 1588 /** 1589 * A hint which for JDBC translates to the Statement.fetchSize(). 1590 * <p> 1591 * Gives the JDBC driver a hint as to the number of rows that should be 1592 * fetched from the database when more rows are needed for ResultSet. 1593 * </p> 1594 * <p> 1595 * Note that internally findEach and findEachWhile will set the fetch size 1596 * if it has not already as these queries expect to process a lot of rows. 1597 * If we didn't then Postgres and MySql for example would eagerly pull back 1598 * all the row data and potentially consume a lot of memory in the process. 1599 * </p> 1600 * <p> 1601 * As findEach and findEachWhile automatically set the fetch size we don't have 1602 * to do so generally but we might still wish to for tuning a specific use case. 1603 * </p> 1604 */ 1605 Query<T> setBufferFetchSizeHint(int fetchSize); 1606 1607 /** 1608 * Return the sql that was generated for executing this query. 1609 * <p> 1610 * This is only available after the query has been executed and provided only 1611 * for informational purposes. 1612 * </p> 1613 */ 1614 String getGeneratedSql(); 1615 1616 /** 1617 * Execute using "for update" clause which results in the DB locking the record. 1618 */ 1619 Query<T> forUpdate(); 1620 1621 /** 1622 * Execute using "for update" clause with "no wait" option. 1623 * <p> 1624 * This is typically a Postgres and Oracle only option at this stage. 1625 * </p> 1626 */ 1627 Query<T> forUpdateNoWait(); 1628 1629 /** 1630 * Execute using "for update" clause with "skip locked" option. 1631 * <p> 1632 * This is typically a Postgres and Oracle only option at this stage. 1633 * </p> 1634 */ 1635 Query<T> forUpdateSkipLocked(); 1636 1637 /** 1638 * Return true if this query has forUpdate set. 1639 */ 1640 boolean isForUpdate(); 1641 1642 /** 1643 * Return the "for update" mode to use. 1644 */ 1645 ForUpdate getForUpdateMode(); 1646 1647 /** 1648 * Set root table alias. 1649 */ 1650 Query<T> alias(String alias); 1651 1652 /** 1653 * Set the base table to use for this query. 1654 * <p> 1655 * Typically this is used when a table has partitioning and we wish to specify a specific 1656 * partition/table to query against. 1657 * </p> 1658 * <pre>{@code 1659 * 1660 * QOrder() 1661 * .setBaseTable("order_2019_05") 1662 * .status.equalTo(Status.NEW) 1663 * .findList(); 1664 * 1665 * }</pre> 1666 */ 1667 Query<T> setBaseTable(String baseTable); 1668 1669 /** 1670 * Return the type of beans being queried. 1671 */ 1672 Class<T> getBeanType(); 1673 1674 /** 1675 * Restrict the query to only return subtypes of the given inherit type. 1676 * 1677 * <pre>{@code 1678 * 1679 * List<Animal> animals = 1680 * new QAnimal() 1681 * .name.startsWith("Fluffy") 1682 * .setInheritType(Cat.class) 1683 * .findList(); 1684 * 1685 * }</pre> 1686 * 1687 * @param type An inheritance subtype of the 1688 */ 1689 Query<T> setInheritType(Class<? extends T> type); 1690 1691 /** 1692 * Returns the inherit type. This is normally the same as getBeanType() returns as long as no other type is set. 1693 */ 1694 Class<? extends T> getInheritType(); 1695 1696 /** 1697 * Return the type of query being executed. 1698 */ 1699 QueryType getQueryType(); 1700 1701 /** 1702 * Set true if you want to disable lazy loading. 1703 * <p> 1704 * That is, once the object graph is returned further lazy loading is disabled. 1705 * </p> 1706 */ 1707 Query<T> setDisableLazyLoading(boolean disableLazyLoading); 1708 1709 /** 1710 * Returns the set of properties or paths that are unknown (do not map to known properties or paths). 1711 * <p> 1712 * Validate the query checking the where and orderBy expression paths to confirm if 1713 * they represent valid properties or paths for the given bean type. 1714 * </p> 1715 */ 1716 Set<String> validate(); 1717 1718 /** 1719 * Controls, if paginated queries should always append an 'order by id' statement at the end to 1720 * guarantee a deterministic sort result. This may affect performance. 1721 * If this is not enabled, and an orderBy is set on the query, it's up to the programmer that 1722 * this query provides a deterministic result. 1723 */ 1724 Query<T> orderById(boolean orderById); 1725 1726}