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