001package com.avaje.ebean; 002 003import com.avaje.ebean.bean.EntityBean; 004import com.avaje.ebean.text.PathProperties; 005import com.avaje.ebean.util.ClassUtil; 006import org.jetbrains.annotations.Nullable; 007 008import javax.persistence.MappedSuperclass; 009import java.util.List; 010import java.util.Map; 011import java.util.Set; 012import java.util.UUID; 013 014/** 015 * A MappedSuperclass base class that provides convenience methods for inserting, updating and 016 * deleting beans. 017 * 018 * <p> 019 * By having your entity beans extend this it provides a 'Active Record' style programming model for 020 * Ebean users. 021 * 022 * <p> 023 * Note that there is a avaje-ebeanorm-mocker project that enables you to use Mockito or similar 024 * tools to still mock out the underlying 'default EbeanServer' for testing purposes. 025 * 026 * <p> 027 * You may choose not use this Model mapped superclass if you don't like the 'Active Record' style 028 * or if you believe it 'pollutes' your entity beans. 029 * 030 * <p> 031 * You can use Dependency Injection like Guice or Spring to construct and wire a EbeanServer instance 032 * and have that same instance used with this Model and Finder. The way that works is that when the 033 * DI container creates the EbeanServer instance it can be registered with the Ebean singleton. In this 034 * way the EbeanServer instance can be injected as per normal Guice / Spring dependency injection and 035 * that same instance also used to support the Model and Finder active record style. 036 * 037 * <p> 038 * If you choose to use the Model mapped superclass you will probably also chose to additionally add 039 * a {@link Find} as a public static field to complete the active record pattern and provide a 040 * relatively nice clean way to write queries. 041 * 042 * <h3>Typical common @MappedSuperclass</h3> 043 * <pre>{@code 044 * 045 * // Typically there is a common base model that has some 046 * // common properties like the ones below 047 * 048 * @MappedSuperclass 049 * public class BaseModel extends Model { 050 * 051 * @Id Long id; 052 * 053 * @Version Long version; 054 * 055 * @CreatedTimestamp Timestamp whenCreated; 056 * 057 * @UpdatedTimestamp Timestamp whenUpdated; 058 * 059 * ... 060 * 061 * }</pre> 062 * 063 * <h3>Extend the Model</h3> 064 * <pre>{@code 065 * 066 * // Extend the mappedSuperclass 067 * 068 * @Entity @Table(name="oto_account") 069 * public class Customer extends BaseModel { 070 * 071 * // Add a static Find 072 * // ... with Long being the type of our @Id property. 073 * // ... Note the {} at the end as Find is an abstract class. 074 * 075 * public static final Find<Long,Account> find = new Find<Long,Account>(){}; 076 * 077 * String name; 078 * ... 079 * } 080 * 081 * }</pre> 082 * 083 * <h3>Modal: save()</h3> 084 * <pre>{@code 085 * 086 * // Active record style ... save(), delete() etc 087 * Customer customer = new Customer(); 088 * customer.setName("AC234"); 089 * 090 * // save() method inherited from Model 091 * customer.save(); 092 * 093 * }</pre> 094 * 095 * <h3>Find byId</h3> 096 * <pre>{@code 097 * 098 * // find byId 099 * Customer customer = Customer.find.byId(42); 100 * 101 * }</pre> 102 * 103 * <h3>Find where</h3> 104 * <pre>{@code 105 * 106 * // find where ... 107 * List<Customer> customers = 108 * Customer.find 109 * .where().gt("startDate", lastMonth) 110 * .findList(); 111 * 112 * }</pre> 113 */ 114@MappedSuperclass 115public abstract class Model { 116 117 /** 118 * Return the underlying 'default' EbeanServer. 119 * 120 * <p> 121 * This provides full access to the API such as explicit transaction demarcation etc. 122 * 123 * <p> 124 * Example: 125 * <pre>{@code 126 * 127 * Transaction transaction = Customer.db().beginTransaction(); 128 * try { 129 * 130 * // turn off cascade persist for this transaction 131 * transaction.setPersistCascade(false); 132 * 133 * // extra control over jdbc batching for this transaction 134 * transaction.setBatchGetGeneratedKeys(false); 135 * transaction.setBatchMode(true); 136 * transaction.setBatchSize(20); 137 * 138 * Customer customer = new Customer(); 139 * customer.setName("Roberto"); 140 * customer.save(); 141 * 142 * Customer otherCustomer = new Customer(); 143 * otherCustomer.setName("Franko"); 144 * otherCustomer.save(); 145 * 146 * transaction.commit(); 147 * 148 * } finally { 149 * transaction.end(); 150 * } 151 * 152 * }</pre> 153 */ 154 public static EbeanServer db() { 155 return Ebean.getDefaultServer(); 156 } 157 158 /** 159 * Return a named EbeanServer that is typically different to the default server. 160 * 161 * <p> 162 * If you are using multiple databases then each database has a name and maps to a single 163 * EbeanServer. You can use this method to get an EbeanServer for another database. 164 * 165 * @param server 166 * The name of the EbeanServer. If this is null then the default EbeanServer is returned. 167 */ 168 public static EbeanServer db(String server) { 169 return Ebean.getServer(server); 170 } 171 172 /** 173 * Marks the entity bean as dirty. 174 * <p> 175 * This is used so that when a bean that is otherwise unmodified is updated the version 176 * property is updated. 177 * <p> 178 * An unmodified bean that is saved or updated is normally skipped and this marks the bean as 179 * dirty so that it is not skipped. 180 * 181 * <pre>{@code 182 * 183 * Customer customer = Customer.find.byId(id); 184 * 185 * // mark the bean as dirty so that a save() or update() will 186 * // increment the version property 187 * customer.markAsDirty(); 188 * customer.save(); 189 * 190 * }</pre> 191 * 192 * @see EbeanServer#markAsDirty(Object) 193 */ 194 public void markAsDirty() { 195 db().markAsDirty(this); 196 } 197 198 /** 199 * Mark the property as unset or 'not loaded'. 200 * <p> 201 * This would be used to specify a property that we did not wish to include in a stateless update. 202 * </p> 203 * <pre>{@code 204 * 205 * // populate an entity bean from JSON or whatever 206 * User user = ...; 207 * 208 * // mark the email property as 'unset' so that it is not 209 * // included in a 'stateless update' 210 * user.markPropertyUnset("email"); 211 * 212 * user.update(); 213 * 214 * }</pre> 215 * 216 * @param propertyName the name of the property on the bean to be marked as 'unset' 217 */ 218 public void markPropertyUnset(String propertyName) { 219 ((EntityBean)this)._ebean_getIntercept().setPropertyLoaded(propertyName, false); 220 } 221 222 /** 223 * Insert or update this entity depending on its state. 224 * 225 * <p> 226 * Ebean will detect if this is a new bean or a previously fetched bean and perform either an 227 * insert or an update based on that. 228 * 229 * @see EbeanServer#save(Object) 230 */ 231 public void save() { 232 db().save(this); 233 } 234 235 /** 236 * Update this entity. 237 * 238 * @see EbeanServer#update(Object) 239 */ 240 public void update() { 241 db().update(this); 242 } 243 244 /** 245 * Insert this entity. 246 * 247 * @see EbeanServer#insert(Object) 248 */ 249 public void insert() { 250 db().insert(this); 251 } 252 253 /** 254 * Delete this bean. 255 * <p> 256 * This will return true if the bean was deleted successfully or JDBC batch is being used. 257 * </p> 258 * <p> 259 * If there is no current transaction one will be created and committed for 260 * you automatically. 261 * </p> 262 * <p> 263 * If the Bean does not have a version property (or loaded version property) and 264 * the bean does not exist then this returns false indicating that nothing was 265 * deleted. Note that, if JDBC batch mode is used then this always returns true. 266 * </p> 267 * 268 * @see EbeanServer#delete(Object) 269 */ 270 public boolean delete() { 271 return db().delete(this); 272 } 273 274 /** 275 * Perform an update using this entity against the specified server. 276 */ 277 public void update(String server) { 278 db(server).update(this); 279 } 280 281 /** 282 * Perform an insert using this entity against the specified server. 283 */ 284 public void insert(String server) { 285 db(server).insert(this); 286 } 287 288 /** 289 * Perform a delete using this entity against the specified server. 290 */ 291 public boolean delete(String server) { 292 return db(server).delete(this); 293 } 294 295 /** 296 * Refreshes this entity from the database. 297 * 298 * @see EbeanServer#refresh(Object) 299 */ 300 public void refresh() { 301 db().refresh(this); 302 } 303 304 /** 305 * A concrete implementation of Find. 306 * <p> 307 * It should be preferred to use {@link Find} instead of Finder as that can use reflection to determine the class 308 * literal type of the entity bean. 309 * </p> 310 * @param <I> type of the Id property 311 * @param <T> type of the entity bean 312 */ 313 public static class Finder<I, T> extends Find<I, T> { 314 315 /** 316 * Create with the type of the entity bean. 317 * 318 * <pre>{@code 319 * 320 * @Entity 321 * public class Customer extends BaseModel { 322 * 323 * public static final Finder<Long,Customer> find = new Finder<Long,Customer>(Customer.class); 324 * ... 325 * 326 * }</pre> 327 * 328 * <p/> 329 * The preferred approach is to instead use <code>Find</code> as below. This approach is more DRY in that it does 330 * not require the class literal Customer.class to be passed into the constructor. 331 * 332 * <pre>{@code 333 * 334 * @Entity 335 * public class Customer extends BaseModel { 336 * 337 * public static final Find<Long,Customer> find = new Find<Long,Customer>(){}; 338 * ... 339 * 340 * }</pre> 341 */ 342 public Finder(Class<T> type) { 343 super(null, type); 344 } 345 346 /** 347 * Create with the type of the entity bean and specific server name. 348 */ 349 public Finder(String serverName, Class<T> type) { 350 super(serverName, type); 351 } 352 353 /** 354 * Please migrate to use {@link Find} or constructor <code>Finder(Class)</code> that 355 * does not have the idType parameter. 356 * <p/> 357 * Create with the type of the ID property and entity bean and specific server name. 358 * 359 * @deprecated 360 */ 361 public Finder(Class<I> idType, Class<T> type) { 362 super(null, type); 363 } 364 365 /** 366 * Please migrate to use the constructor <code>Finder(String, Class)</code> that 367 * does not have the idType parameter. 368 * <p/> 369 * Create with the type of the ID property and entity bean and specific server name. 370 * 371 * @deprecated 372 */ 373 public Finder(String serverName, Class<I> idType, Class<T> type) { 374 super(serverName, type); 375 } 376 } 377 378 /** 379 * Helper object for performing queries. 380 * 381 * <p> 382 * Typically a Find instance is defined as a public static field on an entity bean class to provide a 383 * nice way to write queries. 384 * 385 * <h3>Example use:</h3> 386 * 387 * <pre>{@code 388 * 389 * @Entity 390 * public class Customer extends BaseModel { 391 * 392 * public static final Find<Long,Customer> find = new Find<Long,Customer>(){}; 393 * 394 * ... 395 * 396 * }</pre> 397 * <p/> 398 * This enables you to write code like: 399 * <pre>{@code 400 * 401 * Customer customer = Customer.find.byId(42L); 402 * 403 * List<Customer> customers = 404 * Customer.find 405 * .select("name, dateOfBirth") 406 * .findList(); 407 * 408 * }</pre> 409 * 410 * <h3>Kotlin</h3> 411 * In Kotlin you would typically create Find as a companion object. 412 * <pre>{@code 413 * 414 * // kotlin 415 * companion object : Model.Find<Long, Product>() {} 416 * 417 * }</pre> 418 * @param <I> 419 * The Id type. This is most often a {@link Long} but is also often a {@link UUID} or 420 * {@link String}. 421 * 422 * @param <T> 423 * The entity bean type 424 */ 425 public static abstract class Find<I, T> { 426 427 /** 428 * The entity bean type. 429 */ 430 private final Class<T> type; 431 432 /** 433 * The name of the EbeanServer, null for the default server. 434 */ 435 private final String serverName; 436 437 /** 438 * Creates a finder for entity of type <code>T</code> with ID of type <code>I</code>. 439 * <p/> 440 * Typically you create Find as a public static field on each entity bean as the example below. 441 * 442 * <p/> 443 * Note that Find is an abstract class and hence <code>{}</code> is required. This is done so 444 * that the type (class literal) of the entity bean can be derived from the generics parameter. 445 * 446 * <pre>{@code 447 * 448 * @Entity 449 * public class Customer extends BaseModel { 450 * 451 * // Note the trailing {} as Find is an abstract class. 452 * // We do this so that we can derive the type literal Customer.class 453 * // via reflection 454 * public static final Find<Long,Customer> find = new Find<Long,Customer>(){}; 455 * ... 456 * 457 * }</pre> 458 * <p/> 459 * This enables you to write code like: 460 * <pre>{@code 461 * 462 * Customer customer = Customer.find.byId(42L); 463 * 464 * List<Customer> customers = 465 * Customer.find 466 * .select("name, email, dateOfBirth") 467 * .findList(); 468 * 469 * }</pre> 470 * 471 * <h3>Kotlin</h3> 472 * In Kotlin you would typically create it as a companion object. 473 * 474 * <pre>{@code 475 * 476 * // kotlin 477 * companion object : Model.Find<Long, Product>() {} 478 * 479 * }</pre> 480 */ 481 @SuppressWarnings("unchecked") 482 public Find() { 483 this.serverName = null; 484 this.type = (Class<T>)ClassUtil.getSecondArgumentType(getClass()); 485 } 486 487 /** 488 * Construct passing the class literal type of the entity type. 489 */ 490 protected Find(String serverName, Class<T> type) { 491 this.serverName = serverName; 492 this.type = type; 493 } 494 495 /** 496 * Return the underlying 'default' EbeanServer. 497 * 498 * <p> 499 * This provides full access to the API such as explicit transaction demarcation etc. 500 * 501 */ 502 public EbeanServer db() { 503 return Ebean.getServer(serverName); 504 } 505 506 /** 507 * Return typically a different EbeanServer to the default. 508 * <p> 509 * This is equivilent to {@link Ebean#getServer(String)} 510 * 511 * @param server 512 * The name of the EbeanServer. If this is null then the default EbeanServer is 513 * returned. 514 */ 515 public EbeanServer db(String server) { 516 return Ebean.getServer(server); 517 } 518 519 /** 520 * Creates a Finder for the named EbeanServer. 521 * 522 * <p> 523 * Create and return a new Finder for a different server. 524 */ 525 public Finder<I, T> on(String server) { 526 return new Finder<I, T>(server, type); 527 } 528 529 /** 530 * Delete a bean by Id. 531 * <p> 532 * Equivalent to {@link EbeanServer#delete(Class, Object)} 533 */ 534 public void deleteById(I id) { 535 db().delete(type, id); 536 } 537 538 /** 539 * Retrieves all entities of the given type. 540 * 541 * <p> 542 * This is the same as (synonym for) {@link #findList()} 543 */ 544 public List<T> all() { 545 return findList(); 546 } 547 548 /** 549 * Retrieves an entity by ID. 550 * 551 * <p> 552 * Equivalent to {@link EbeanServer#find(Class, Object)} 553 */ 554 @Nullable 555 public T byId(I id) { 556 return db().find(type, id); 557 } 558 559 /** 560 * Creates an entity reference for this ID. 561 * 562 * <p> 563 * Equivalent to {@link EbeanServer#getReference(Class, Object)} 564 */ 565 public T ref(I id) { 566 return db().getReference(type, id); 567 } 568 569 /** 570 * Creates a filter for sorting and filtering lists of entities locally without going back to 571 * the database. 572 * <p> 573 * Equivalent to {@link EbeanServer#filter(Class)} 574 */ 575 public Filter<T> filter() { 576 return db().filter(type); 577 } 578 579 /** 580 * Creates a query. 581 * <p> 582 * Equivalent to {@link EbeanServer#find(Class)} 583 */ 584 public Query<T> query() { 585 return db().find(type); 586 } 587 588 /** 589 * Creates a query applying the path properties to set the select and fetch clauses. 590 * <p> 591 * Equivalent to {@link Query#apply(com.avaje.ebean.text.PathProperties)} 592 */ 593 public Query<T> apply(PathProperties pathProperties) { 594 return db().find(type).apply(pathProperties); 595 } 596 597 /** 598 * Returns the next identity value. 599 * 600 * @see EbeanServer#nextId(Class) 601 */ 602 @SuppressWarnings("unchecked") 603 public I nextId() { 604 return (I) db().nextId(type); 605 } 606 607 /** 608 * Executes a query and returns the results as a list of IDs. 609 * <p> 610 * Equivalent to {@link Query#findIds()} 611 */ 612 public List<Object> findIds() { 613 return query().findIds(); 614 } 615 616 /** 617 * Execute the query consuming each bean one at a time. 618 * <p> 619 * This is generally used to process large queries where unlike findList 620 * you do not want to hold all the results in memory at once but instead 621 * process them one at a time (requiring far less memory). 622 * </p> 623 * Equivalent to {@link Query#findEach(QueryEachConsumer)} 624 */ 625 public void findEach(QueryEachConsumer<T> consumer) { 626 query().findEach(consumer); 627 } 628 629 /** 630 * Execute the query consuming each bean one at a time. 631 * <p> 632 * Equivalent to {@link Query#findEachWhile(QueryEachWhileConsumer)} 633 * <p> 634 * This is similar to #findEach except that you return boolean 635 * true to continue processing beans and return false to stop 636 * processing early. 637 * </p> 638 * <p> 639 * This is generally used to process large queries where unlike findList 640 * you do not want to hold all the results in memory at once but instead 641 * process them one at a time (requiring far less memory). 642 * </p> 643 * Equivalent to {@link Query#findEachWhile(QueryEachWhileConsumer)} 644 */ 645 public void findEachWhile(QueryEachWhileConsumer<T> consumer) { 646 query().findEachWhile(consumer); 647 } 648 649 /** 650 * Retrieves all entities of the given type. 651 * <p> 652 * The same as {@link #all()} 653 * <p> 654 * Equivalent to {@link Query#findList()} 655 */ 656 public List<T> findList() { 657 return query().findList(); 658 } 659 660 /** 661 * Returns all the entities of the given type as a set. 662 * <p> 663 * Equivalent to {@link Query#findSet()} 664 */ 665 public Set<T> findSet() { 666 return query().findSet(); 667 } 668 669 /** 670 * Retrieves all entities of the given type as a map of objects. 671 * <p> 672 * Equivalent to {@link Query#findMap()} 673 */ 674 public Map<?, T> findMap() { 675 return query().findMap(); 676 } 677 678 /** 679 * Executes the query and returns the results as a map of the objects specifying the map key 680 * property. 681 * <p> 682 * Equivalent to {@link Query#findMap(String, Class)} 683 */ 684 public <K> Map<K, T> findMap(String keyProperty, Class<K> keyType) { 685 return query().findMap(keyProperty, keyType); 686 } 687 688 /** 689 * Return a PagedList of all entities of the given type (use where() to specify predicates as 690 * needed). 691 * <p> 692 * Equivalent to {@link Query#findPagedList(int, int)} 693 */ 694 public PagedList<T> findPagedList(int pageIndex, int pageSize) { 695 return query().findPagedList(pageIndex, pageSize); 696 } 697 698 /** 699 * Executes a find row count query in a background thread. 700 * <p> 701 * Equivalent to {@link Query#findFutureRowCount()} 702 */ 703 public FutureRowCount<T> findFutureRowCount() { 704 return query().findFutureRowCount(); 705 } 706 707 /** 708 * Returns the total number of entities for this type. * 709 * <p> 710 * Equivalent to {@link Query#findRowCount()} 711 */ 712 public int findRowCount() { 713 return query().findRowCount(); 714 } 715 716 /** 717 * Returns the <code>ExpressionFactory</code> used by this query. 718 */ 719 public ExpressionFactory getExpressionFactory() { 720 return query().getExpressionFactory(); 721 } 722 723 /** 724 * Explicitly sets a comma delimited list of the properties to fetch on the 'main' entity bean, 725 * to load a partial object. 726 * <p> 727 * Equivalent to {@link Query#select(String)} 728 */ 729 public Query<T> select(String fetchProperties) { 730 return query().select(fetchProperties); 731 } 732 733 /** 734 * Specifies a path to load including all its properties. 735 * <p> 736 * Equivalent to {@link Query#fetch(String)} 737 */ 738 public Query<T> fetch(String path) { 739 return query().fetch(path); 740 } 741 742 /** 743 * Additionally specifies a <code>FetchConfig</code> to specify a 'query join' and/or define the 744 * lazy loading query. 745 * <p> 746 * Equivalent to {@link Query#fetch(String, FetchConfig)} 747 */ 748 public Query<T> fetch(String path, FetchConfig joinConfig) { 749 return query().fetch(path, joinConfig); 750 } 751 752 /** 753 * Specifies a path to fetch with a specific list properties to include, to load a partial 754 * object. 755 * <p> 756 * Equivalent to {@link Query#fetch(String, String)} 757 */ 758 public Query<T> fetch(String path, String fetchProperties) { 759 return query().fetch(path, fetchProperties); 760 } 761 762 /** 763 * Additionally specifies a <code>FetchConfig</code> to use a separate query or lazy loading to 764 * load this path. 765 * <p> 766 * Equivalent to {@link Query#fetch(String, String, FetchConfig)} 767 */ 768 public Query<T> fetch(String assocProperty, String fetchProperties, FetchConfig fetchConfig) { 769 return query().fetch(assocProperty, fetchProperties, fetchConfig); 770 } 771 772 /** 773 * Adds expressions to the <code>where</code> clause with the ability to chain on the 774 * <code>ExpressionList</code>. 775 * <p> 776 * Equivalent to {@link Query#where()} 777 */ 778 public ExpressionList<T> where() { 779 return query().where(); 780 } 781 782 /** 783 * Returns the <code>order by</code> clause so that you can append an ascending or descending 784 * property to the <code>order by</code> clause. 785 * <p> 786 * This is exactly the same as {@link #orderBy}. 787 * <p> 788 * Equivalent to {@link Query#order()} 789 */ 790 public OrderBy<T> order() { 791 return query().order(); 792 } 793 794 /** 795 * Sets the <code>order by</code> clause, replacing the existing <code>order by</code> clause if 796 * there is one. 797 * <p> 798 * This is exactly the same as {@link #orderBy(String)}. 799 */ 800 public Query<T> order(String orderByClause) { 801 return query().order(orderByClause); 802 } 803 804 /** 805 * Returns the <code>order by</code> clause so that you can append an ascending or descending 806 * property to the <code>order by</code> clause. 807 * <p> 808 * This is exactly the same as {@link #order}. 809 * <p> 810 * Equivalent to {@link Query#orderBy()} 811 */ 812 public OrderBy<T> orderBy() { 813 return query().orderBy(); 814 } 815 816 /** 817 * Set the <code>order by</code> clause replacing the existing <code>order by</code> clause if 818 * there is one. 819 * <p> 820 * This is exactly the same as {@link #order(String)}. 821 */ 822 public Query<T> orderBy(String orderByClause) { 823 return query().orderBy(orderByClause); 824 } 825 826 /** 827 * Sets the first row to return for this query. 828 * <p> 829 * Equivalent to {@link Query#setFirstRow(int)} 830 */ 831 public Query<T> setFirstRow(int firstRow) { 832 return query().setFirstRow(firstRow); 833 } 834 835 /** 836 * Sets the maximum number of rows to return in the query. 837 * <p> 838 * Equivalent to {@link Query#setMaxRows(int)} 839 */ 840 public Query<T> setMaxRows(int maxRows) { 841 return query().setMaxRows(maxRows); 842 } 843 844 /** 845 * Sets the ID value to query. 846 * 847 * <p> 848 * Use this to perform a find byId query but with additional control over the query such as 849 * using select and fetch to control what parts of the object graph are returned. 850 * <p> 851 * Equivalent to {@link Query#setId(Object)} 852 */ 853 public Query<T> setId(Object id) { 854 return query().setId(id); 855 } 856 857 /** 858 * Create and return a new query using the OQL. 859 * <p> 860 * Equivalent to {@link EbeanServer#createQuery(Class, String)} 861 */ 862 public Query<T> setQuery(String oql) { 863 return db().createQuery(type, oql); 864 } 865 866 /** 867 * Create and return a new query based on the <code>RawSql</code>. 868 * <p> 869 * Equivalent to {@link Query#setRawSql(RawSql)} 870 */ 871 public Query<T> setRawSql(RawSql rawSql) { 872 return query().setRawSql(rawSql); 873 } 874 875 /** 876 * Create a query with explicit 'AutoTune' use. 877 */ 878 public Query<T> setAutoTune(boolean autoTune) { 879 return query().setAutoTune(autoTune); 880 } 881 882 /** 883 * Create a query with the select with "for update" specified. 884 * 885 * <p> 886 * This will typically create row level database locks on the selected rows. 887 */ 888 public Query<T> setForUpdate(boolean forUpdate) { 889 return query().setForUpdate(forUpdate); 890 } 891 892 /** 893 * Create a query specifying whether the returned beans will be read-only. 894 */ 895 public Query<T> setReadOnly(boolean readOnly) { 896 return query().setReadOnly(readOnly); 897 } 898 899 /** 900 * Create a query specifying if the beans should be loaded into the L2 cache. 901 */ 902 public Query<T> setLoadBeanCache(boolean loadBeanCache) { 903 return query().setLoadBeanCache(loadBeanCache); 904 } 905 906 /** 907 * Create a query specifying if the L2 bean cache should be used. 908 */ 909 public Query<T> setUseCache(boolean useBeanCache) { 910 return query().setUseCache(useBeanCache); 911 } 912 913 /** 914 * Create a query specifying if the L2 query cache should be used. 915 */ 916 public Query<T> setUseQueryCache(boolean useQueryCache) { 917 return query().setUseQueryCache(useQueryCache); 918 } 919 920 } 921}