001package com.avaje.ebean; 002 003import java.util.Collection; 004import java.util.HashMap; 005import java.util.List; 006import java.util.Map; 007import java.util.concurrent.ConcurrentHashMap; 008 009import javax.persistence.OptimisticLockException; 010import javax.persistence.PersistenceException; 011 012import org.jetbrains.annotations.Nullable; 013import org.slf4j.Logger; 014import org.slf4j.LoggerFactory; 015 016import com.avaje.ebean.annotation.CacheStrategy; 017import com.avaje.ebean.cache.ServerCacheManager; 018import com.avaje.ebean.config.ServerConfig; 019import com.avaje.ebean.text.csv.CsvReader; 020import com.avaje.ebean.text.json.JsonContext; 021 022/** 023 * This Ebean object is effectively a singleton that holds a map of registered 024 * {@link EbeanServer}s. It additionally provides a convenient way to use the 025 * 'default' EbeanServer. 026 * <p> 027 * If you are using a Dependency Injection framework such as 028 * <strong>Spring</strong> or <strong>Guice</strong> you will probably 029 * <strong>NOT</strong> use this Ebean singleton object. Instead you will 030 * configure and construct EbeanServer instances using {@link ServerConfig} and 031 * {@link EbeanServerFactory} and inject those EbeanServer instances into your 032 * data access objects. 033 * </p> 034 * <p> 035 * In documentation "Ebean singleton" refers to this object. 036 * </p> 037 * <ul> 038 * <li>There is one EbeanServer per Database (javax.sql.DataSource).</li> 039 * <li>EbeanServers can be 'registered' with the Ebean singleton (put into its 040 * map). Registered EbeanServer's can later be retrieved via 041 * {@link #getServer(String)}.</li> 042 * <li>One EbeanServer can be referred to as the 'default' EbeanServer. For 043 * convenience, the Ebean singleton (this object) provides methods such as 044 * {@link #find(Class)} that proxy through to the 'default' EbeanServer. This 045 * can be useful for applications that use a single database.</li> 046 * </ul> 047 * 048 * <p> 049 * For developer convenience Ebean has static methods that proxy through to the 050 * methods on the <em>'default'</em> EbeanServer. These methods are provided for 051 * developers who are mostly using a single database. Many developers will be 052 * able to use the methods on Ebean rather than get a EbeanServer. 053 * </p> 054 * <p> 055 * EbeanServers can be created and used without ever needing or using the Ebean 056 * singleton. Refer to {@link ServerConfig#setRegister(boolean)}. 057 * </p> 058 * <p> 059 * You can either programmatically create/register EbeanServers via 060 * {@link EbeanServerFactory} or they can automatically be created and 061 * registered when you first use the Ebean singleton. When EbeanServers are 062 * created automatically they are configured using information in the 063 * ebean.properties file. 064 * </p> 065 * 066 * <pre>{@code 067 * 068 * // fetch shipped orders (and also their customer) 069 * List<Order> list = Ebean.find(Order.class) 070 * .fetch("customer") 071 * .where() 072 * .eq("status.code", Order.Status.SHIPPED) 073 * .findList(); 074 * 075 * // read/use the order list ... 076 * for (Order order : list) { 077 * Customer customer = order.getCustomer(); 078 * ... 079 * } 080 * 081 * }</pre> 082 * 083 * <pre>{@code 084 * 085 * // fetch order 10, modify and save 086 * Order order = Ebean.find(Order.class, 10); 087 * 088 * OrderStatus shipped = Ebean.getReference(OrderStatus.class,"SHIPPED"); 089 * order.setStatus(shipped); 090 * order.setShippedDate(shippedDate); 091 * ... 092 * 093 * // implicitly creates a transaction and commits 094 * Ebean.save(order); 095 * 096 * }</pre> 097 * 098 * <p> 099 * When you have multiple databases and need access to a specific one the 100 * {@link #getServer(String)} method provides access to the EbeanServer for that 101 * specific database. 102 * </p> 103 * 104 * <pre>{@code 105 * 106 * // Get access to the Human Resources EbeanServer/Database 107 * EbeanServer hrDb = Ebean.getServer("hr"); 108 * 109 * 110 * // fetch contact 3 from the HR database 111 * Contact contact = hrDb.find(Contact.class, 3); 112 * 113 * contact.setName("I'm going to change"); 114 * ... 115 * 116 * // save the contact back to the HR database 117 * hrDb.save(contact); 118 * 119 * }</pre> 120 */ 121public final class Ebean { 122 private static final Logger logger = LoggerFactory.getLogger(Ebean.class); 123 124 /** 125 * Manages creation and cache of EbeanServers. 126 */ 127 private static final Ebean.ServerManager serverMgr = new Ebean.ServerManager(); 128 129 /** 130 * Helper class for managing fast and safe access and creation of 131 * EbeanServers. 132 */ 133 private static final class ServerManager { 134 135 /** 136 * Cache for fast concurrent read access. 137 */ 138 private final ConcurrentHashMap<String, EbeanServer> concMap = new ConcurrentHashMap<String, EbeanServer>(); 139 140 /** 141 * Cache for synchronized read, creation and put. Protected by the monitor 142 * object. 143 */ 144 private final HashMap<String, EbeanServer> syncMap = new HashMap<String, EbeanServer>(); 145 146 private final Object monitor = new Object(); 147 148 /** 149 * The 'default' EbeanServer. 150 */ 151 private EbeanServer defaultServer; 152 153 private ServerManager() { 154 155 try { 156 // skipDefaultServer is set by EbeanServerFactory 157 // ... when it is creating the primaryServer 158 if (PrimaryServer.isSkip()) { 159 // primary server being created by EbeanServerFactory 160 // ... so we should not try and create it here 161 logger.debug("PrimaryServer.isSkip()"); 162 163 } else { 164 // look to see if there is a default server defined 165 String defaultName = PrimaryServer.getDefaultServerName(); 166 logger.debug("defaultName:" + defaultName); 167 if (defaultName != null && defaultName.trim().length() > 0) { 168 defaultServer = getWithCreate(defaultName.trim()); 169 } 170 } 171 } catch (Throwable e) { 172 logger.error("Error trying to create the default EbeanServer", e); 173 throw new RuntimeException(e); 174 } 175 } 176 177 private EbeanServer getDefaultServer() { 178 if (defaultServer == null) { 179 String msg = "The default EbeanServer has not been defined?"; 180 msg += " This is normally set via the ebean.datasource.default property."; 181 msg += " Otherwise it should be registered programmatically via registerServer()"; 182 throw new PersistenceException(msg); 183 } 184 return defaultServer; 185 } 186 187 private EbeanServer get(String name) { 188 if (name == null || name.length() == 0) { 189 return defaultServer; 190 } 191 // non-synchronized read 192 EbeanServer server = concMap.get(name); 193 if (server != null) { 194 return server; 195 } 196 // synchronized read, create and put 197 return getWithCreate(name); 198 } 199 200 /** 201 * Synchronized read, create and put of EbeanServers. 202 */ 203 private EbeanServer getWithCreate(String name) { 204 205 synchronized (monitor) { 206 207 EbeanServer server = syncMap.get(name); 208 if (server == null) { 209 // register when creating server this way 210 server = EbeanServerFactory.create(name); 211 register(server, false); 212 } 213 return server; 214 } 215 } 216 217 /** 218 * Register a server so we can get it by its name. 219 */ 220 private void register(EbeanServer server, boolean isDefaultServer) { 221 registerWithName(server.getName(), server, isDefaultServer); 222 } 223 224 private void registerWithName(String name, EbeanServer server, boolean isDefaultServer) { 225 synchronized (monitor) { 226 concMap.put(name, server); 227 syncMap.put(name, server); 228 if (isDefaultServer) { 229 defaultServer = server; 230 } 231 } 232 } 233 234 } 235 236 private Ebean() { 237 } 238 239 /** 240 * Get the EbeanServer for a given DataSource. If name is null this will 241 * return the 'default' EbeanServer. 242 * <p> 243 * This is provided to access EbeanServer for databases other than the 244 * 'default' database. EbeanServer also provides more control over 245 * transactions and the ability to use transactions created externally to 246 * Ebean. 247 * </p> 248 * 249 * <pre>{@code 250 * // use the "hr" database 251 * EbeanServer hrDatabase = Ebean.getServer("hr"); 252 * 253 * Person person = hrDatabase.find(Person.class, 10); 254 * }</pre> 255 * 256 * @param name 257 * the name of the server, can use null for the 'default server' 258 */ 259 public static EbeanServer getServer(String name) { 260 return serverMgr.get(name); 261 } 262 263 /** 264 * Returns the default EbeanServer. 265 * <p> 266 * This is equivalent to <code>Ebean.getServer(null);</code> 267 * </p> 268 */ 269 public static EbeanServer getDefaultServer() { 270 return serverMgr.getDefaultServer(); 271 } 272 273 /** 274 * Return the ExpressionFactory from the default server. 275 * <p> 276 * The ExpressionFactory is used internally by the query and ExpressionList to 277 * build the WHERE and HAVING clauses. Alternatively you can use the 278 * ExpressionFactory directly to create expressions to add to the query where 279 * clause. 280 * </p> 281 * <p> 282 * Alternatively you can use the {@link Expr} as a shortcut to the 283 * ExpressionFactory of the 'Default' EbeanServer. 284 * </p> 285 * <p> 286 * You generally need to the an ExpressionFactory (or {@link Expr}) to build 287 * an expression that uses OR like Expression e = Expr.or(..., ...); 288 * </p> 289 */ 290 public static ExpressionFactory getExpressionFactory() { 291 return serverMgr.getDefaultServer().getExpressionFactory(); 292 } 293 294 /** 295 * Register the server with this Ebean singleton. Specify if the registered 296 * server is the primary/default server. 297 */ 298 public static void register(EbeanServer server, boolean defaultServer) { 299 serverMgr.register(server, defaultServer); 300 } 301 302 /** 303 * Backdoor for registering a mock implementation of EbeanServer as the default server. 304 */ 305 protected static EbeanServer mock(String name, EbeanServer server, boolean defaultServer) { 306 EbeanServer originalPrimaryServer = serverMgr.defaultServer; 307 serverMgr.registerWithName(name, server, defaultServer); 308 return originalPrimaryServer; 309 } 310 311 /** 312 * Return the next identity value for a given bean type. 313 * <p> 314 * This will only work when a IdGenerator is on this bean type such as a DB 315 * sequence or UUID. 316 * </p> 317 * <p> 318 * For DB's supporting getGeneratedKeys and sequences such as Oracle10 you do 319 * not need to use this method generally. It is made available for more 320 * complex cases where it is useful to get an ID prior to some processing. 321 * </p> 322 */ 323 public static Object nextId(Class<?> beanType) { 324 return serverMgr.getDefaultServer().nextId(beanType); 325 } 326 327 /** 328 * Start a transaction with 'REQUIRED' semantics. 329 * <p> 330 * With REQUIRED semantics if an active transaction already exists that transaction will be used. 331 * </p> 332 * <p> 333 * The transaction is stored in a ThreadLocal variable and typically you only 334 * need to use the returned Transaction <em>IF</em> you wish to do things like 335 * use batch mode, change the transaction isolation level, use savepoints or 336 * log comments to the transaction log. 337 * </p> 338 * <p> 339 * Example of using a transaction to span multiple calls to find(), save() 340 * etc. 341 * </p> 342 * 343 * <pre>{@code 344 * 345 * // start a transaction (stored in a ThreadLocal) 346 * Ebean.beginTransaction(); 347 * try { 348 * Order order = Ebean.find(Order.class,10); ... 349 * 350 * Ebean.save(order); 351 * 352 * Ebean.commitTransaction(); 353 * 354 * } finally { 355 * // rollback if we didn't commit 356 * // i.e. an exception occurred before commitTransaction(). 357 * Ebean.endTransaction(); 358 * } 359 * 360 * }</pre> 361 * 362 * <p> 363 * If you want to externalise the transaction management then you should be 364 * able to do this via EbeanServer. Specifically with EbeanServer you can pass 365 * the transaction to the various find() and save() execute() methods. This 366 * gives you the ability to create the transactions yourself externally from 367 * Ebean and pass those transactions through to the various methods available 368 * on EbeanServer. 369 * </p> 370 */ 371 public static Transaction beginTransaction() { 372 return serverMgr.getDefaultServer().beginTransaction(); 373 } 374 375 /** 376 * Start a transaction additionally specifying the isolation level. 377 * 378 * @param isolation 379 * the Transaction isolation level 380 * 381 */ 382 public static Transaction beginTransaction(TxIsolation isolation) { 383 return serverMgr.getDefaultServer().beginTransaction(isolation); 384 } 385 386 /** 387 * Start a transaction typically specifying REQUIRES_NEW or REQUIRED semantics. 388 * 389 * <p> 390 * Note that this provides an try finally alternative to using {@link #execute(TxScope, TxCallable)} or 391 * {@link #execute(TxScope, TxRunnable)}. 392 * </p> 393 * 394 * <h3>REQUIRES_NEW example:</h3> 395 * <pre>{@code 396 * // Start a new transaction. If there is a current transaction 397 * // suspend it until this transaction ends 398 * Transaction txn = Ebean.beginTransaction(TxScope.requiresNew()); 399 * try { 400 * 401 * ... 402 * 403 * // commit the transaction 404 * txn.commit(); 405 * 406 * } finally { 407 * // end this transaction which: 408 * // A) will rollback transaction if it has not been committed already 409 * // B) will restore a previously suspended transaction 410 * txn.end(); 411 * } 412 * 413 * }</pre> 414 * 415 * <h3>REQUIRED example:</h3> 416 * <pre>{@code 417 * 418 * // start a new transaction if there is not a current transaction 419 * Transaction txn = Ebean.beginTransaction(TxScope.required()); 420 * try { 421 * 422 * ... 423 * 424 * // commit the transaction if it was created or 425 * // do nothing if there was already a current transaction 426 * txn.commit(); 427 * 428 * } finally { 429 * // end this transaction which will rollback the transaction 430 * // if it was created for this try finally scope and has not 431 * // already been committed 432 * txn.end(); 433 * } 434 * 435 * }</pre> 436 */ 437 public static Transaction beginTransaction(TxScope scope){ 438 return serverMgr.getDefaultServer().beginTransaction(scope); 439 } 440 441 /** 442 * Returns the current transaction or null if there is no current transaction 443 * in scope. 444 */ 445 public static Transaction currentTransaction() { 446 return serverMgr.getDefaultServer().currentTransaction(); 447 } 448 449 /** 450 * Register a TransactionCallback on the currently active transaction. 451 * <p/> 452 * If there is no currently active transaction then a PersistenceException is thrown. 453 * 454 * @param transactionCallback the transaction callback to be registered with the current transaction 455 * 456 * @throws PersistenceException if there is no currently active transaction 457 */ 458 public static void register(TransactionCallback transactionCallback) throws PersistenceException { 459 serverMgr.getDefaultServer().register(transactionCallback); 460 } 461 462 /** 463 * Commit the current transaction. 464 */ 465 public static void commitTransaction() { 466 serverMgr.getDefaultServer().commitTransaction(); 467 } 468 469 /** 470 * Rollback the current transaction. 471 */ 472 public static void rollbackTransaction() { 473 serverMgr.getDefaultServer().rollbackTransaction(); 474 } 475 476 /** 477 * If the current transaction has already been committed do nothing otherwise 478 * rollback the transaction. 479 * <p> 480 * Useful to put in a finally block to ensure the transaction is ended, rather 481 * than a rollbackTransaction() in each catch block. 482 * </p> 483 * <p> 484 * Code example: 485 * </p> 486 * 487 * <pre>{@code 488 * Ebean.beginTransaction(); 489 * try { 490 * // do some fetching and or persisting 491 * 492 * // commit at the end 493 * Ebean.commitTransaction(); 494 * 495 * } finally { 496 * // if commit didn't occur then rollback the transaction 497 * Ebean.endTransaction(); 498 * } 499 * }</pre> 500 */ 501 public static void endTransaction() { 502 serverMgr.getDefaultServer().endTransaction(); 503 } 504 505 /** 506 * Return a map of the differences between two objects of the same type. 507 * <p> 508 * When null is passed in for b, then the 'OldValues' of a is used for the 509 * difference comparison. 510 * </p> 511 */ 512 public static Map<String, ValuePair> diff(Object a, Object b) { 513 return serverMgr.getDefaultServer().diff(a, b); 514 } 515 516 /** 517 * Either Insert or Update the bean depending on its state. 518 * <p> 519 * If there is no current transaction one will be created and committed for 520 * you automatically. 521 * </p> 522 * <p> 523 * Save can cascade along relationships. For this to happen you need to 524 * specify a cascade of CascadeType.ALL or CascadeType.PERSIST on the 525 * OneToMany, OneToOne or ManyToMany annotation. 526 * </p> 527 * <p> 528 * In this example below the details property has a CascadeType.ALL set so 529 * saving an order will also save all its details. 530 * </p> 531 * 532 * <pre>{@code 533 * public class Order { ... 534 * 535 * @OneToMany(cascade=CascadeType.ALL, mappedBy="order") 536 * List<OrderDetail> details; 537 * ... 538 * } 539 * }</pre> 540 * 541 * <p> 542 * When a save cascades via a OneToMany or ManyToMany Ebean will automatically 543 * set the 'parent' object to the 'detail' object. In the example below in 544 * saving the order and cascade saving the order details the 'parent' order 545 * will be set against each order detail when it is saved. 546 * </p> 547 */ 548 public static void save(Object bean) throws OptimisticLockException { 549 serverMgr.getDefaultServer().save(bean); 550 } 551 552 /** 553 * Insert the bean. This is useful when you set the Id property on a bean and 554 * want to explicitly insert it. 555 */ 556 public static void insert(Object bean) { 557 serverMgr.getDefaultServer().insert(bean); 558 } 559 560 /** 561 * Insert a collection of beans. 562 */ 563 public static void insertAll(Collection<?> beans) { 564 serverMgr.getDefaultServer().insertAll(beans); 565 } 566 567 /** 568 * Marks the entity bean as dirty. 569 * <p> 570 * This is used so that when a bean that is otherwise unmodified is updated with the version 571 * property updated. 572 * <p> 573 * An unmodified bean that is saved or updated is normally skipped and this marks the bean as 574 * dirty so that it is not skipped. 575 * 576 * <pre>{@code 577 * 578 * Customer customer = Ebean.find(Customer, id); 579 * 580 * // mark the bean as dirty so that a save() or update() will 581 * // increment the version property 582 * Ebean.markAsDirty(customer); 583 * Ebean.save(customer); 584 * 585 * }</pre> 586 */ 587 public static void markAsDirty(Object bean) throws OptimisticLockException { 588 serverMgr.getDefaultServer().markAsDirty(bean); 589 } 590 591 /** 592 * Saves the bean using an update. If you know you are updating a bean then it is preferrable to 593 * use this update() method rather than save(). 594 * <p> 595 * <b>Stateless updates:</b> Note that the bean does not have to be previously fetched to call 596 * update().You can create a new instance and set some of its properties programmatically for via 597 * JSON/XML marshalling etc. This is described as a 'stateless update'. 598 * </p> 599 * <p> 600 * <b>Optimistic Locking: </b> Note that if the version property is not set when update() is 601 * called then no optimistic locking is performed (internally ConcurrencyMode.NONE is used). 602 * </p> 603 * <p> 604 * <b>{@link ServerConfig#setUpdatesDeleteMissingChildren(boolean)}: </b> When cascade saving to a 605 * OneToMany or ManyToMany the updatesDeleteMissingChildren setting controls if any other children 606 * that are in the database but are not in the collection are deleted. 607 * </p> 608 * <p> 609 * <b>{@link ServerConfig#setUpdateChangesOnly(boolean)}: </b> The updateChangesOnly setting 610 * controls if only the changed properties are included in the update or if all the loaded 611 * properties are included instead. 612 * </p> 613 * 614 * <pre>{@code 615 * 616 * // A 'stateless update' example 617 * Customer customer = new Customer(); 618 * customer.setId(7); 619 * customer.setName("ModifiedNameNoOCC"); 620 * ebeanServer.update(customer); 621 * 622 * }</pre> 623 * 624 * @see ServerConfig#setUpdatesDeleteMissingChildren(boolean) 625 * @see ServerConfig#setUpdateChangesOnly(boolean) 626 */ 627 public static void update(Object bean) throws OptimisticLockException { 628 serverMgr.getDefaultServer().update(bean); 629 } 630 631 /** 632 * Update the beans in the collection. 633 */ 634 public static void updateAll(Collection<?> beans) throws OptimisticLockException { 635 serverMgr.getDefaultServer().updateAll(beans); 636 } 637 638 /** 639 * Save all the beans from a Collection. 640 */ 641 public static int saveAll(Collection<?> beans) throws OptimisticLockException { 642 return serverMgr.getDefaultServer().saveAll(beans); 643 } 644 645 /** 646 * Delete the associations (from the intersection table) of a ManyToMany given 647 * the owner bean and the propertyName of the ManyToMany collection. 648 * <p> 649 * Typically these deletions occur automatically when persisting a ManyToMany 650 * collection and this provides a way to invoke those deletions directly. 651 * </p> 652 * 653 * @return the number of associations deleted (from the intersection table). 654 */ 655 public static int deleteManyToManyAssociations(Object ownerBean, String propertyName) { 656 return serverMgr.getDefaultServer().deleteManyToManyAssociations(ownerBean, propertyName); 657 } 658 659 /** 660 * Save the associations of a ManyToMany given the owner bean and the 661 * propertyName of the ManyToMany collection. 662 * <p> 663 * Typically the saving of these associations (inserting into the intersection 664 * table) occurs automatically when persisting a ManyToMany. This provides a 665 * way to invoke those insertions directly. 666 * </p> 667 * <p> 668 * You can use this when the collection is new and in this case all the 669 * entries in the collection are treated as additions are result in inserts 670 * into the intersection table. 671 * </p> 672 */ 673 public static void saveManyToManyAssociations(Object ownerBean, String propertyName) { 674 serverMgr.getDefaultServer().saveManyToManyAssociations(ownerBean, propertyName); 675 } 676 677 /** 678 * Save the associated collection or bean given the property name. 679 * <p> 680 * This is similar to performing a save cascade on a specific property 681 * manually/programmatically. 682 * </p> 683 * <p> 684 * Note that you can turn on/off cascading for a transaction via 685 * {@link Transaction#setPersistCascade(boolean)} 686 * </p> 687 * 688 * @param ownerBean 689 * the bean instance holding the property we want to save 690 * @param propertyName 691 * the property we want to save 692 */ 693 public static void saveAssociation(Object ownerBean, String propertyName) { 694 serverMgr.getDefaultServer().saveAssociation(ownerBean, propertyName); 695 } 696 697 /** 698 * Delete the bean. 699 * <p> 700 * This will return true if the bean was deleted successfully or JDBC batch is being used. 701 * </p> 702 * <p> 703 * If there is no current transaction one will be created and committed for 704 * you automatically. 705 * </p> 706 * <p> 707 * If the bean is configured with <code>@SoftDelete</code> then this will perform a soft 708 * delete rather than a hard/permanent delete. 709 * </p> 710 * <p> 711 * If the Bean does not have a version property (or loaded version property) and 712 * the bean does not exist then this returns false indicating that nothing was 713 * deleted. Note that, if JDBC batch mode is used then this always returns true. 714 * </p> 715 */ 716 public static boolean delete(Object bean) throws OptimisticLockException { 717 return serverMgr.getDefaultServer().delete(bean); 718 } 719 720 /** 721 * Delete the bean in permanent fashion (will not use soft delete). 722 */ 723 public static boolean deletePermanent(Object bean) throws OptimisticLockException { 724 return serverMgr.getDefaultServer().deletePermanent(bean); 725 } 726 727 /** 728 * Delete the bean given its type and id. 729 */ 730 public static int delete(Class<?> beanType, Object id) { 731 return serverMgr.getDefaultServer().delete(beanType, id); 732 } 733 734 /** 735 * Delete several beans given their type and id values. 736 */ 737 public static void deleteAll(Class<?> beanType, Collection<?> ids) { 738 serverMgr.getDefaultServer().deleteAll(beanType, ids); 739 } 740 741 /** 742 * Delete all the beans in the Collection. 743 */ 744 public static int deleteAll(Collection<?> beans) throws OptimisticLockException { 745 return serverMgr.getDefaultServer().deleteAll(beans); 746 } 747 748 /** 749 * Delete permanent all the beans in the Collection (will not use soft delete). 750 */ 751 public static int deleteAllPermanent(Collection<?> beans) throws OptimisticLockException { 752 return serverMgr.getDefaultServer().deleteAllPermanent(beans); 753 } 754 755 /** 756 * Refresh the values of a bean. 757 * <p> 758 * Note that this resets OneToMany and ManyToMany properties so that if they 759 * are accessed a lazy load will refresh the many property. 760 * </p> 761 */ 762 public static void refresh(Object bean) { 763 serverMgr.getDefaultServer().refresh(bean); 764 } 765 766 /** 767 * Refresh a 'many' property of a bean. 768 * 769 * <pre>{@code 770 * 771 * Order order = ...; 772 * ... 773 * // refresh the order details... 774 * Ebean.refreshMany(order, "details"); 775 * 776 * }</pre> 777 * 778 * @param bean 779 * the entity bean containing the List Set or Map to refresh. 780 * @param manyPropertyName 781 * the property name of the List Set or Map to refresh. 782 */ 783 public static void refreshMany(Object bean, String manyPropertyName) { 784 serverMgr.getDefaultServer().refreshMany(bean, manyPropertyName); 785 } 786 787 /** 788 * Get a reference object. 789 * <p> 790 * This is sometimes described as a proxy (with lazy loading). 791 * </p> 792 * 793 * <pre>{@code 794 * 795 * Product product = Ebean.getReference(Product.class, 1); 796 * 797 * // You can get the id without causing a fetch/lazy load 798 * Integer productId = product.getId(); 799 * 800 * // If you try to get any other property a fetch/lazy loading will occur 801 * // This will cause a query to execute... 802 * String name = product.getName(); 803 * 804 * }</pre> 805 * 806 * @param beanType 807 * the type of entity bean 808 * @param id 809 * the id value 810 */ 811 public static <T> T getReference(Class<T> beanType, Object id) { 812 return serverMgr.getDefaultServer().getReference(beanType, id); 813 } 814 815 /** 816 * Sort the list using the sortByClause which can contain a comma delimited 817 * list of property names and keywords asc, desc, nullsHigh and nullsLow. 818 * <ul> 819 * <li>asc - ascending order (which is the default)</li> 820 * <li>desc - Descending order</li> 821 * <li>nullsHigh - Treat null values as high/large values (which is the 822 * default)</li> 823 * <li>nullsLow- Treat null values as low/very small values</li> 824 * </ul> 825 * <p> 826 * If you leave off any keywords the defaults are ascending order and treating 827 * nulls as high values. 828 * </p> 829 * <p> 830 * Note that the sorting uses a Comparator and Collections.sort(); and does 831 * not invoke a DB query. 832 * </p> 833 * 834 * <pre>{@code 835 * 836 * // find orders and their customers 837 * List<Order> list = Ebean.find(Order.class) 838 * .fetch("customer") 839 * .orderBy("id") 840 * .findList(); 841 * 842 * // sort by customer name ascending, then by order shipDate 843 * // ... then by the order status descending 844 * Ebean.sort(list, "customer.name, shipDate, status desc"); 845 * 846 * // sort by customer name descending (with nulls low) 847 * // ... then by the order id 848 * Ebean.sort(list, "customer.name desc nullsLow, id"); 849 * 850 * }</pre> 851 * 852 * @param list 853 * the list of entity beans 854 * @param sortByClause 855 * the properties to sort the list by 856 */ 857 public static <T> void sort(List<T> list, String sortByClause) { 858 serverMgr.getDefaultServer().sort(list, sortByClause); 859 } 860 861 /** 862 * Find a bean using its unique id. This will not use caching. 863 * 864 * <pre>{@code 865 * // Fetch order 1 866 * Order order = Ebean.find(Order.class, 1); 867 * }</pre> 868 * 869 * <p> 870 * If you want more control over the query then you can use createQuery() and 871 * Query.findUnique(); 872 * </p> 873 * 874 * <pre>{@code 875 * // ... additionally fetching customer, customer shipping address, 876 * // order details, and the product associated with each order detail. 877 * // note: only product id and name is fetch (its a "partial object"). 878 * // note: all other objects use "*" and have all their properties fetched. 879 * 880 * Query<Order> query = Ebean.find(Order.class) 881 * .setId(1) 882 * .fetch("customer") 883 * .fetch("customer.shippingAddress") 884 * .fetch("details") 885 * .query(); 886 * 887 * // fetch associated products but only fetch their product id and name 888 * query.fetch("details.product", "name"); 889 * 890 * // traverse the object graph... 891 * 892 * Order order = query.findUnique(); 893 * Customer customer = order.getCustomer(); 894 * Address shippingAddress = customer.getShippingAddress(); 895 * List<OrderDetail> details = order.getDetails(); 896 * OrderDetail detail0 = details.get(0); 897 * Product product = detail0.getProduct(); 898 * String productName = product.getName(); 899 * 900 * }</pre> 901 * 902 * @param beanType 903 * the type of entity bean to fetch 904 * @param id 905 * the id value 906 */ 907 @Nullable 908 public static <T> T find(Class<T> beanType, Object id) { 909 return serverMgr.getDefaultServer().find(beanType, id); 910 } 911 912 /** 913 * Create a SqlQuery for executing native sql 914 * query statements. 915 * <p> 916 * Note that you can use raw SQL with entity beans, refer to the SqlSelect 917 * annotation for examples. 918 * </p> 919 */ 920 public static SqlQuery createSqlQuery(String sql) { 921 return serverMgr.getDefaultServer().createSqlQuery(sql); 922 } 923 924 /** 925 * Create a named sql query. 926 * <p> 927 * The query statement will be defined in a deployment orm xml file. 928 * </p> 929 * 930 * @param namedQuery 931 * the name of the query 932 */ 933 public static SqlQuery createNamedSqlQuery(String namedQuery) { 934 return serverMgr.getDefaultServer().createNamedSqlQuery(namedQuery); 935 } 936 937 /** 938 * Create a sql update for executing native dml statements. 939 * <p> 940 * Use this to execute a Insert Update or Delete statement. The statement will 941 * be native to the database and contain database table and column names. 942 * </p> 943 * <p> 944 * See {@link SqlUpdate} for example usage. 945 * </p> 946 * <p> 947 * Where possible it would be expected practice to put the statement in a orm 948 * xml file (named update) and use {@link #createNamedSqlUpdate(String)} . 949 * </p> 950 */ 951 public static SqlUpdate createSqlUpdate(String sql) { 952 return serverMgr.getDefaultServer().createSqlUpdate(sql); 953 } 954 955 /** 956 * Create a CallableSql to execute a given stored procedure. 957 * 958 * @see CallableSql 959 */ 960 public static CallableSql createCallableSql(String sql) { 961 return serverMgr.getDefaultServer().createCallableSql(sql); 962 } 963 964 /** 965 * Create a named sql update. 966 * <p> 967 * The statement (an Insert Update or Delete statement) will be defined in a 968 * deployment orm xml file. 969 * </p> 970 * 971 * <pre>{@code 972 * 973 * // Use a namedQuery 974 * UpdateSql update = Ebean.createNamedSqlUpdate("update.topic.count"); 975 * 976 * update.setParameter("count", 1); 977 * update.setParameter("topicId", 50); 978 * 979 * int modifiedCount = update.execute(); 980 * 981 * }</pre> 982 */ 983 public static SqlUpdate createNamedSqlUpdate(String namedQuery) { 984 return serverMgr.getDefaultServer().createNamedSqlUpdate(namedQuery); 985 } 986 987 /** 988 * Return a named Query that will have defined fetch paths, predicates etc. 989 * <p> 990 * The query is created from a statement that will be defined in a deployment 991 * orm xml file or NamedQuery annotations. The query will typically already 992 * define fetch paths, predicates, order by clauses etc so often you will just 993 * need to bind required parameters and then execute the query. 994 * </p> 995 * 996 * <pre>{@code 997 * 998 * // example 999 * Query<Order> query = Ebean.createNamedQuery(Order.class, "new.for.customer"); 1000 * query.setParameter("customerId", 23); 1001 * List<Order> newOrders = query.findList(); 1002 * 1003 * }</pre> 1004 * 1005 * @param beanType 1006 * the class of entity to be fetched 1007 * @param namedQuery 1008 * the name of the query 1009 */ 1010 public static <T> Query<T> createNamedQuery(Class<T> beanType, String namedQuery) { 1011 1012 return serverMgr.getDefaultServer().createNamedQuery(beanType, namedQuery); 1013 } 1014 1015 /** 1016 * Create a query using the query language. 1017 * <p> 1018 * Note that you are allowed to add additional clauses using where() as well 1019 * as use fetch() and setOrderBy() after the query has been created. 1020 * </p> 1021 * <p> 1022 * Note that this method signature used to map to named queries and that has 1023 * moved to {@link #createNamedQuery(Class, String)}. 1024 * </p> 1025 * 1026 * <pre>{@code 1027 * 1028 * String q = "find order fetch details where status = :st"; 1029 * 1030 * List<Order> newOrders = Ebean.>findOrder.class, q) 1031 * .setParameter("st", Order.Status.NEW) 1032 * .findList(); 1033 * 1034 * }</pre> 1035 * 1036 * @param query 1037 * the object query 1038 */ 1039 public static <T> Query<T> createQuery(Class<T> beanType, String query) { 1040 return serverMgr.getDefaultServer().createQuery(beanType, query); 1041 } 1042 1043 /** 1044 * Create a named orm update. The update statement is specified via the 1045 * NamedUpdate annotation. 1046 * <p> 1047 * The orm update differs from the SqlUpdate in that it uses the bean name and 1048 * bean property names rather than table and column names. 1049 * </p> 1050 * <p> 1051 * Note that named update statements can be specified in raw sql (with column 1052 * and table names) or using bean name and bean property names. This can be 1053 * specified with the isSql flag. 1054 * </p> 1055 * <p> 1056 * Example named updates: 1057 * </p> 1058 * 1059 * <pre>{@code 1060 * package app.data; 1061 * 1062 * import ... 1063 * 1064 * @NamedUpdates(value = { 1065 * @NamedUpdate( name = "setTitle", 1066 * isSql = false, 1067 * notifyCache = false, 1068 * update = "update topic set title = :title, postCount = :postCount where id = :id"), 1069 * @NamedUpdate( name = "setPostCount", 1070 * notifyCache = false, 1071 * update = "update f_topic set post_count = :postCount where id = :id"), 1072 * @NamedUpdate( name = "incrementPostCount", 1073 * notifyCache = false, 1074 * isSql = false, 1075 * update = "update Topic set postCount = postCount + 1 where id = :id") }) 1076 * @Entity 1077 * @Table(name = "f_topic") 1078 * public class Topic { ... 1079 * 1080 * }</pre> 1081 * 1082 * <p> 1083 * Example using a named update: 1084 * </p> 1085 * 1086 * <pre>{@code 1087 * 1088 * Update<Topic> update = Ebean.createNamedUpdate(Topic.class, "setPostCount"); 1089 * update.setParameter("postCount", 10); 1090 * update.setParameter("id", 3); 1091 * 1092 * int rows = update.execute(); 1093 * System.out.println("rows updated: " + rows); 1094 * 1095 * }</pre> 1096 */ 1097 public static <T> Update<T> createNamedUpdate(Class<T> beanType, String namedUpdate) { 1098 1099 return serverMgr.getDefaultServer().createNamedUpdate(beanType, namedUpdate); 1100 } 1101 1102 /** 1103 * Create a orm update where you will supply the insert/update or delete 1104 * statement (rather than using a named one that is already defined using the 1105 * @NamedUpdates annotation). 1106 * <p> 1107 * The orm update differs from the sql update in that it you can use the bean 1108 * name and bean property names rather than table and column names. 1109 * </p> 1110 * <p> 1111 * An example: 1112 * </p> 1113 * 1114 * <pre>{@code 1115 * 1116 * // The bean name and properties - "topic","postCount" and "id" 1117 * 1118 * // will be converted into their associated table and column names 1119 * String updStatement = "update topic set postCount = :pc where id = :id"; 1120 * 1121 * Update<Topic> update = Ebean.createUpdate(Topic.class, updStatement); 1122 * 1123 * update.set("pc", 9); 1124 * update.set("id", 3); 1125 * 1126 * int rows = update.execute(); 1127 * System.out.println("rows updated:" + rows); 1128 * 1129 * }</pre> 1130 */ 1131 public static <T> Update<T> createUpdate(Class<T> beanType, String ormUpdate) { 1132 1133 return serverMgr.getDefaultServer().createUpdate(beanType, ormUpdate); 1134 } 1135 1136 /** 1137 * Create a CsvReader for a given beanType. 1138 */ 1139 public static <T> CsvReader<T> createCsvReader(Class<T> beanType) { 1140 1141 return serverMgr.getDefaultServer().createCsvReader(beanType); 1142 } 1143 1144 /** 1145 * Create a query for a type of entity bean. 1146 * <p> 1147 * You can use the methods on the Query object to specify fetch paths, 1148 * predicates, order by, limits etc. 1149 * </p> 1150 * <p> 1151 * You then use findList(), findSet(), findMap() and findUnique() to execute 1152 * the query and return the collection or bean. 1153 * </p> 1154 * <p> 1155 * Note that a query executed by {@link Query#findList()} 1156 * {@link Query#findSet()} etc will execute against the same EbeanServer from 1157 * which is was created. 1158 * </p> 1159 * 1160 * <pre>{@code 1161 * // Find order 2 additionally fetching the customer, details and details.product 1162 * // name. 1163 * 1164 * Order order = Ebean.find(Order.class) 1165 * .fetch("customer") 1166 * .fetch("details") 1167 * .fetch("detail.product", "name") 1168 * .setId(2) 1169 * .findUnique(); 1170 * 1171 * // Find order 2 additionally fetching the customer, details and details.product 1172 * // name. 1173 * // Note: same query as above but using the query language 1174 * // Note: using a named query would be preferred practice 1175 * 1176 * String oql = "find order fetch customer fetch details fetch details.product (name) where id = :orderId "; 1177 * 1178 * Query<Order> query = Ebean.find(Order.class); 1179 * query.setQuery(oql); 1180 * query.setParameter("orderId", 2); 1181 * 1182 * Order order = query.findUnique(); 1183 * 1184 * // Using a named query 1185 * Query<Order> query = Ebean.find(Order.class, "with.details"); 1186 * query.setParameter("orderId", 2); 1187 * 1188 * Order order = query.findUnique(); 1189 * 1190 * }</pre> 1191 * 1192 * @param beanType 1193 * the class of entity to be fetched 1194 * @return A ORM Query object for this beanType 1195 */ 1196 public static <T> Query<T> createQuery(Class<T> beanType) { 1197 1198 return serverMgr.getDefaultServer().createQuery(beanType); 1199 } 1200 1201 /** 1202 * Create a query for a type of entity bean. 1203 * <p> 1204 * This is actually the same as {@link #createQuery(Class)}. The reason it 1205 * exists is that people used to JPA will probably be looking for a 1206 * createQuery method (the same as entityManager). 1207 * </p> 1208 * 1209 * @param beanType 1210 * the type of entity bean to find 1211 * @return A ORM Query object for this beanType 1212 */ 1213 public static <T> Query<T> find(Class<T> beanType) { 1214 1215 return serverMgr.getDefaultServer().find(beanType); 1216 } 1217 1218 /** 1219 * Create a filter for sorting and filtering lists of entities locally without 1220 * going back to the database. 1221 * <p> 1222 * This produces and returns a new list with the sort and filters applied. 1223 * </p> 1224 * <p> 1225 * Refer to {@link Filter} for an example of its use. 1226 * </p> 1227 */ 1228 public static <T> Filter<T> filter(Class<T> beanType) { 1229 return serverMgr.getDefaultServer().filter(beanType); 1230 } 1231 1232 /** 1233 * Execute a Sql Update Delete or Insert statement. This returns the number of 1234 * rows that where updated, deleted or inserted. If is executed in batch then 1235 * this returns -1. You can get the actual rowCount after commit() from 1236 * updateSql.getRowCount(). 1237 * <p> 1238 * If you wish to execute a Sql Select natively then you should use the 1239 * FindByNativeSql object. 1240 * </p> 1241 * <p> 1242 * Note that the table modification information is automatically deduced and 1243 * you do not need to call the Ebean.externalModification() method when you 1244 * use this method. 1245 * </p> 1246 * <p> 1247 * Example: 1248 * </p> 1249 * 1250 * <pre>{@code 1251 * 1252 * // example that uses 'named' parameters 1253 * String s = "UPDATE f_topic set post_count = :count where id = :id" 1254 * 1255 * SqlUpdate update = Ebean.createSqlUpdate(s); 1256 * 1257 * update.setParameter("id", 1); 1258 * update.setParameter("count", 50); 1259 * 1260 * int modifiedCount = Ebean.execute(update); 1261 * 1262 * String msg = "There where " + modifiedCount + "rows updated"; 1263 * 1264 * }</pre> 1265 * 1266 * @param sqlUpdate 1267 * the update sql potentially with bind values 1268 * 1269 * @return the number of rows updated or deleted. -1 if executed in batch. 1270 * 1271 * @see SqlUpdate 1272 * @see CallableSql 1273 * @see Ebean#execute(CallableSql) 1274 */ 1275 public static int execute(SqlUpdate sqlUpdate) { 1276 return serverMgr.getDefaultServer().execute(sqlUpdate); 1277 } 1278 1279 /** 1280 * For making calls to stored procedures. 1281 * <p> 1282 * Example: 1283 * </p> 1284 * 1285 * <pre>{@code 1286 * 1287 * String sql = "{call sp_order_modify(?,?,?)}"; 1288 * 1289 * CallableSql cs = Ebean.createCallableSql(sql); 1290 * cs.setParameter(1, 27); 1291 * cs.setParameter(2, "SHIPPED"); 1292 * cs.registerOut(3, Types.INTEGER); 1293 * 1294 * Ebean.execute(cs); 1295 * 1296 * // read the out parameter 1297 * Integer returnValue = (Integer) cs.getObject(3); 1298 * 1299 * }</pre> 1300 * 1301 * @see CallableSql 1302 * @see Ebean#execute(SqlUpdate) 1303 */ 1304 public static int execute(CallableSql callableSql) { 1305 return serverMgr.getDefaultServer().execute(callableSql); 1306 } 1307 1308 /** 1309 * Execute a TxRunnable in a Transaction with an explicit scope. 1310 * <p> 1311 * The scope can control the transaction type, isolation and rollback 1312 * semantics. 1313 * </p> 1314 * 1315 * <pre>{@code 1316 * 1317 * // set specific transactional scope settings 1318 * TxScope scope = TxScope.requiresNew().setIsolation(TxIsolation.SERIALIZABLE); 1319 * 1320 * Ebean.execute(scope, new TxRunnable() { 1321 * public void run() { 1322 * User u1 = Ebean.find(User.class, 1); 1323 * ... 1324 * } 1325 * }); 1326 * 1327 * }</pre> 1328 */ 1329 public static void execute(TxScope scope, TxRunnable r) { 1330 serverMgr.getDefaultServer().execute(scope, r); 1331 } 1332 1333 /** 1334 * Execute a TxRunnable in a Transaction with the default scope. 1335 * <p> 1336 * The default scope runs with REQUIRED and by default will rollback on any 1337 * exception (checked or runtime). 1338 * </p> 1339 * 1340 * <pre>{@code 1341 * 1342 * Ebean.execute(new TxRunnable() { 1343 * public void run() { 1344 * User u1 = Ebean.find(User.class, 1); 1345 * User u2 = Ebean.find(User.class, 2); 1346 * 1347 * u1.setName("u1 mod"); 1348 * u2.setName("u2 mod"); 1349 * 1350 * Ebean.save(u1); 1351 * Ebean.save(u2); 1352 * } 1353 * }); 1354 * 1355 * }</pre> 1356 */ 1357 public static void execute(TxRunnable r) { 1358 serverMgr.getDefaultServer().execute(r); 1359 } 1360 1361 /** 1362 * Execute a TxCallable in a Transaction with an explicit scope. 1363 * <p> 1364 * The scope can control the transaction type, isolation and rollback 1365 * semantics. 1366 * </p> 1367 * 1368 * <pre>{@code 1369 * 1370 * // set specific transactional scope settings 1371 * TxScope scope = TxScope.requiresNew().setIsolation(TxIsolation.SERIALIZABLE); 1372 * 1373 * Ebean.execute(scope, new TxCallable<String>() { 1374 * public String call() { 1375 * User u1 = Ebean.find(User.class, 1); 1376 * ... 1377 * return u1.getEmail(); 1378 * } 1379 * }); 1380 * 1381 * }</pre> 1382 * 1383 */ 1384 public static <T> T execute(TxScope scope, TxCallable<T> c) { 1385 return serverMgr.getDefaultServer().execute(scope, c); 1386 } 1387 1388 /** 1389 * Execute a TxCallable in a Transaction with the default scope. 1390 * <p> 1391 * The default scope runs with REQUIRED and by default will rollback on any 1392 * exception (checked or runtime). 1393 * </p> 1394 * <p> 1395 * This is basically the same as TxRunnable except that it returns an Object 1396 * (and you specify the return type via generics). 1397 * </p> 1398 * 1399 * <pre>{@code 1400 * 1401 * Ebean.execute(new TxCallable<String>() { 1402 * public String call() { 1403 * User u1 = Ebean.find(User.class, 1); 1404 * User u2 = Ebean.find(User.class, 2); 1405 * 1406 * u1.setName("u1 mod"); 1407 * u2.setName("u2 mod"); 1408 * 1409 * Ebean.save(u1); 1410 * Ebean.save(u2); 1411 * 1412 * return u1.getEmail(); 1413 * } 1414 * }); 1415 * 1416 * }</pre> 1417 */ 1418 public static <T> T execute(TxCallable<T> c) { 1419 return serverMgr.getDefaultServer().execute(c); 1420 } 1421 1422 /** 1423 * Inform Ebean that tables have been modified externally. These could be the 1424 * result of from calling a stored procedure, other JDBC calls or external 1425 * programs including other frameworks. 1426 * <p> 1427 * If you use Ebean.execute(UpdateSql) then the table modification information 1428 * is automatically deduced and you do not need to call this method yourself. 1429 * </p> 1430 * <p> 1431 * This information is used to invalidate objects out of the cache and 1432 * potentially text indexes. This information is also automatically broadcast 1433 * across the cluster. 1434 * </p> 1435 * <p> 1436 * If there is a transaction then this information is placed into the current 1437 * transactions event information. When the transaction is committed this 1438 * information is registered (with the transaction manager). If this 1439 * transaction is rolled back then none of the transaction event information 1440 * registers including the information you put in via this method. 1441 * </p> 1442 * <p> 1443 * If there is NO current transaction when you call this method then this 1444 * information is registered immediately (with the transaction manager). 1445 * </p> 1446 * 1447 * @param tableName 1448 * the name of the table that was modified 1449 * @param inserts 1450 * true if rows where inserted into the table 1451 * @param updates 1452 * true if rows on the table where updated 1453 * @param deletes 1454 * true if rows on the table where deleted 1455 */ 1456 public static void externalModification(String tableName, boolean inserts, boolean updates, boolean deletes) { 1457 1458 serverMgr.getDefaultServer().externalModification(tableName, inserts, updates, deletes); 1459 } 1460 1461 /** 1462 * Return the BeanState for a given entity bean. 1463 * <p> 1464 * This will return null if the bean is not an enhanced entity bean. 1465 * </p> 1466 */ 1467 public static BeanState getBeanState(Object bean) { 1468 return serverMgr.getDefaultServer().getBeanState(bean); 1469 } 1470 1471 /** 1472 * Return the manager of the server cache ("L2" cache). 1473 * 1474 */ 1475 public static ServerCacheManager getServerCacheManager() { 1476 return serverMgr.getDefaultServer().getServerCacheManager(); 1477 } 1478 1479 /** 1480 * Return the BackgroundExecutor service for asynchronous processing of 1481 * queries. 1482 */ 1483 public static BackgroundExecutor getBackgroundExecutor() { 1484 return serverMgr.getDefaultServer().getBackgroundExecutor(); 1485 } 1486 1487 /** 1488 * Run the cache warming queries on all bean types that have one defined for 1489 * the default/primary EbeanServer. 1490 * <p> 1491 * A cache warming query can be defined via {@link CacheStrategy}. 1492 * </p> 1493 */ 1494 public static void runCacheWarming() { 1495 serverMgr.getDefaultServer().runCacheWarming(); 1496 } 1497 1498 /** 1499 * Run the cache warming query for a specific bean type for the 1500 * default/primary EbeanServer. 1501 * <p> 1502 * A cache warming query can be defined via {@link CacheStrategy}. 1503 * </p> 1504 */ 1505 public static void runCacheWarming(Class<?> beanType) { 1506 1507 serverMgr.getDefaultServer().runCacheWarming(beanType); 1508 } 1509 1510 /** 1511 * Return the JsonContext for reading/writing JSON. 1512 */ 1513 public static JsonContext json() { 1514 return serverMgr.getDefaultServer().json(); 1515 } 1516 1517}