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