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 * If there is no current transaction one will be created and committed for 701 * you automatically. 702 * </p> 703 */ 704 public static void delete(Object bean) throws OptimisticLockException { 705 serverMgr.getDefaultServer().delete(bean); 706 } 707 708 /** 709 * Delete the bean given its type and id. 710 */ 711 public static int delete(Class<?> beanType, Object id) { 712 return serverMgr.getDefaultServer().delete(beanType, id); 713 } 714 715 /** 716 * Delete several beans given their type and id values. 717 */ 718 public static void deleteAll(Class<?> beanType, Collection<?> ids) { 719 serverMgr.getDefaultServer().deleteAll(beanType, ids); 720 } 721 722 /** 723 * Delete all the beans in the Collection. 724 */ 725 public static int deleteAll(Collection<?> beans) throws OptimisticLockException { 726 return serverMgr.getDefaultServer().deleteAll(beans); 727 } 728 729 /** 730 * Refresh the values of a bean. 731 * <p> 732 * Note that this resets OneToMany and ManyToMany properties so that if they 733 * are accessed a lazy load will refresh the many property. 734 * </p> 735 */ 736 public static void refresh(Object bean) { 737 serverMgr.getDefaultServer().refresh(bean); 738 } 739 740 /** 741 * Refresh a 'many' property of a bean. 742 * 743 * <pre>{@code 744 * 745 * Order order = ...; 746 * ... 747 * // refresh the order details... 748 * Ebean.refreshMany(order, "details"); 749 * 750 * }</pre> 751 * 752 * @param bean 753 * the entity bean containing the List Set or Map to refresh. 754 * @param manyPropertyName 755 * the property name of the List Set or Map to refresh. 756 */ 757 public static void refreshMany(Object bean, String manyPropertyName) { 758 serverMgr.getDefaultServer().refreshMany(bean, manyPropertyName); 759 } 760 761 /** 762 * Get a reference object. 763 * <p> 764 * This is sometimes described as a proxy (with lazy loading). 765 * </p> 766 * 767 * <pre>{@code 768 * 769 * Product product = Ebean.getReference(Product.class, 1); 770 * 771 * // You can get the id without causing a fetch/lazy load 772 * Integer productId = product.getId(); 773 * 774 * // If you try to get any other property a fetch/lazy loading will occur 775 * // This will cause a query to execute... 776 * String name = product.getName(); 777 * 778 * }</pre> 779 * 780 * @param beanType 781 * the type of entity bean 782 * @param id 783 * the id value 784 */ 785 public static <T> T getReference(Class<T> beanType, Object id) { 786 return serverMgr.getDefaultServer().getReference(beanType, id); 787 } 788 789 /** 790 * Sort the list using the sortByClause which can contain a comma delimited 791 * list of property names and keywords asc, desc, nullsHigh and nullsLow. 792 * <ul> 793 * <li>asc - ascending order (which is the default)</li> 794 * <li>desc - Descending order</li> 795 * <li>nullsHigh - Treat null values as high/large values (which is the 796 * default)</li> 797 * <li>nullsLow- Treat null values as low/very small values</li> 798 * </ul> 799 * <p> 800 * If you leave off any keywords the defaults are ascending order and treating 801 * nulls as high values. 802 * </p> 803 * <p> 804 * Note that the sorting uses a Comparator and Collections.sort(); and does 805 * not invoke a DB query. 806 * </p> 807 * 808 * <pre>{@code 809 * 810 * // find orders and their customers 811 * List<Order> list = Ebean.find(Order.class) 812 * .fetch("customer") 813 * .orderBy("id") 814 * .findList(); 815 * 816 * // sort by customer name ascending, then by order shipDate 817 * // ... then by the order status descending 818 * Ebean.sort(list, "customer.name, shipDate, status desc"); 819 * 820 * // sort by customer name descending (with nulls low) 821 * // ... then by the order id 822 * Ebean.sort(list, "customer.name desc nullsLow, id"); 823 * 824 * }</pre> 825 * 826 * @param list 827 * the list of entity beans 828 * @param sortByClause 829 * the properties to sort the list by 830 */ 831 public static <T> void sort(List<T> list, String sortByClause) { 832 serverMgr.getDefaultServer().sort(list, sortByClause); 833 } 834 835 /** 836 * Find a bean using its unique id. This will not use caching. 837 * 838 * <pre>{@code 839 * // Fetch order 1 840 * Order order = Ebean.find(Order.class, 1); 841 * }</pre> 842 * 843 * <p> 844 * If you want more control over the query then you can use createQuery() and 845 * Query.findUnique(); 846 * </p> 847 * 848 * <pre>{@code 849 * // ... additionally fetching customer, customer shipping address, 850 * // order details, and the product associated with each order detail. 851 * // note: only product id and name is fetch (its a "partial object"). 852 * // note: all other objects use "*" and have all their properties fetched. 853 * 854 * Query<Order> query = Ebean.find(Order.class) 855 * .setId(1) 856 * .fetch("customer") 857 * .fetch("customer.shippingAddress") 858 * .fetch("details") 859 * .query(); 860 * 861 * // fetch associated products but only fetch their product id and name 862 * query.fetch("details.product", "name"); 863 * 864 * // traverse the object graph... 865 * 866 * Order order = query.findUnique(); 867 * Customer customer = order.getCustomer(); 868 * Address shippingAddress = customer.getShippingAddress(); 869 * List<OrderDetail> details = order.getDetails(); 870 * OrderDetail detail0 = details.get(0); 871 * Product product = detail0.getProduct(); 872 * String productName = product.getName(); 873 * 874 * }</pre> 875 * 876 * @param beanType 877 * the type of entity bean to fetch 878 * @param id 879 * the id value 880 */ 881 @Nullable 882 public static <T> T find(Class<T> beanType, Object id) { 883 return serverMgr.getDefaultServer().find(beanType, id); 884 } 885 886 /** 887 * Create a SqlQuery for executing native sql 888 * query statements. 889 * <p> 890 * Note that you can use raw SQL with entity beans, refer to the SqlSelect 891 * annotation for examples. 892 * </p> 893 */ 894 public static SqlQuery createSqlQuery(String sql) { 895 return serverMgr.getDefaultServer().createSqlQuery(sql); 896 } 897 898 /** 899 * Create a named sql query. 900 * <p> 901 * The query statement will be defined in a deployment orm xml file. 902 * </p> 903 * 904 * @param namedQuery 905 * the name of the query 906 */ 907 public static SqlQuery createNamedSqlQuery(String namedQuery) { 908 return serverMgr.getDefaultServer().createNamedSqlQuery(namedQuery); 909 } 910 911 /** 912 * Create a sql update for executing native dml statements. 913 * <p> 914 * Use this to execute a Insert Update or Delete statement. The statement will 915 * be native to the database and contain database table and column names. 916 * </p> 917 * <p> 918 * See {@link SqlUpdate} for example usage. 919 * </p> 920 * <p> 921 * Where possible it would be expected practice to put the statement in a orm 922 * xml file (named update) and use {@link #createNamedSqlUpdate(String)} . 923 * </p> 924 */ 925 public static SqlUpdate createSqlUpdate(String sql) { 926 return serverMgr.getDefaultServer().createSqlUpdate(sql); 927 } 928 929 /** 930 * Create a CallableSql to execute a given stored procedure. 931 * 932 * @see CallableSql 933 */ 934 public static CallableSql createCallableSql(String sql) { 935 return serverMgr.getDefaultServer().createCallableSql(sql); 936 } 937 938 /** 939 * Create a named sql update. 940 * <p> 941 * The statement (an Insert Update or Delete statement) will be defined in a 942 * deployment orm xml file. 943 * </p> 944 * 945 * <pre>{@code 946 * 947 * // Use a namedQuery 948 * UpdateSql update = Ebean.createNamedSqlUpdate("update.topic.count"); 949 * 950 * update.setParameter("count", 1); 951 * update.setParameter("topicId", 50); 952 * 953 * int modifiedCount = update.execute(); 954 * 955 * }</pre> 956 */ 957 public static SqlUpdate createNamedSqlUpdate(String namedQuery) { 958 return serverMgr.getDefaultServer().createNamedSqlUpdate(namedQuery); 959 } 960 961 /** 962 * Return a named Query that will have defined fetch paths, predicates etc. 963 * <p> 964 * The query is created from a statement that will be defined in a deployment 965 * orm xml file or NamedQuery annotations. The query will typically already 966 * define fetch paths, predicates, order by clauses etc so often you will just 967 * need to bind required parameters and then execute the query. 968 * </p> 969 * 970 * <pre>{@code 971 * 972 * // example 973 * Query<Order> query = Ebean.createNamedQuery(Order.class, "new.for.customer"); 974 * query.setParameter("customerId", 23); 975 * List<Order> newOrders = query.findList(); 976 * 977 * }</pre> 978 * 979 * @param beanType 980 * the class of entity to be fetched 981 * @param namedQuery 982 * the name of the query 983 */ 984 public static <T> Query<T> createNamedQuery(Class<T> beanType, String namedQuery) { 985 986 return serverMgr.getDefaultServer().createNamedQuery(beanType, namedQuery); 987 } 988 989 /** 990 * Create a query using the query language. 991 * <p> 992 * Note that you are allowed to add additional clauses using where() as well 993 * as use fetch() and setOrderBy() after the query has been created. 994 * </p> 995 * <p> 996 * Note that this method signature used to map to named queries and that has 997 * moved to {@link #createNamedQuery(Class, String)}. 998 * </p> 999 * 1000 * <pre>{@code 1001 * 1002 * String q = "find order fetch details where status = :st"; 1003 * 1004 * List<Order> newOrders = Ebean.>findOrder.class, q) 1005 * .setParameter("st", Order.Status.NEW) 1006 * .findList(); 1007 * 1008 * }</pre> 1009 * 1010 * @param query 1011 * the object query 1012 */ 1013 public static <T> Query<T> createQuery(Class<T> beanType, String query) { 1014 return serverMgr.getDefaultServer().createQuery(beanType, query); 1015 } 1016 1017 /** 1018 * Create a named orm update. The update statement is specified via the 1019 * NamedUpdate annotation. 1020 * <p> 1021 * The orm update differs from the SqlUpdate in that it uses the bean name and 1022 * bean property names rather than table and column names. 1023 * </p> 1024 * <p> 1025 * Note that named update statements can be specified in raw sql (with column 1026 * and table names) or using bean name and bean property names. This can be 1027 * specified with the isSql flag. 1028 * </p> 1029 * <p> 1030 * Example named updates: 1031 * </p> 1032 * 1033 * <pre>{@code 1034 * package app.data; 1035 * 1036 * import ... 1037 * 1038 * @NamedUpdates(value = { 1039 * @NamedUpdate( name = "setTitle", 1040 * isSql = false, 1041 * notifyCache = false, 1042 * update = "update topic set title = :title, postCount = :postCount where id = :id"), 1043 * @NamedUpdate( name = "setPostCount", 1044 * notifyCache = false, 1045 * update = "update f_topic set post_count = :postCount where id = :id"), 1046 * @NamedUpdate( name = "incrementPostCount", 1047 * notifyCache = false, 1048 * isSql = false, 1049 * update = "update Topic set postCount = postCount + 1 where id = :id") }) 1050 * @Entity 1051 * @Table(name = "f_topic") 1052 * public class Topic { ... 1053 * 1054 * }</pre> 1055 * 1056 * <p> 1057 * Example using a named update: 1058 * </p> 1059 * 1060 * <pre>{@code 1061 * 1062 * Update<Topic> update = Ebean.createNamedUpdate(Topic.class, "setPostCount"); 1063 * update.setParameter("postCount", 10); 1064 * update.setParameter("id", 3); 1065 * 1066 * int rows = update.execute(); 1067 * System.out.println("rows updated: " + rows); 1068 * 1069 * }</pre> 1070 */ 1071 public static <T> Update<T> createNamedUpdate(Class<T> beanType, String namedUpdate) { 1072 1073 return serverMgr.getDefaultServer().createNamedUpdate(beanType, namedUpdate); 1074 } 1075 1076 /** 1077 * Create a orm update where you will supply the insert/update or delete 1078 * statement (rather than using a named one that is already defined using the 1079 * @NamedUpdates annotation). 1080 * <p> 1081 * The orm update differs from the sql update in that it you can use the bean 1082 * name and bean property names rather than table and column names. 1083 * </p> 1084 * <p> 1085 * An example: 1086 * </p> 1087 * 1088 * <pre>{@code 1089 * 1090 * // The bean name and properties - "topic","postCount" and "id" 1091 * 1092 * // will be converted into their associated table and column names 1093 * String updStatement = "update topic set postCount = :pc where id = :id"; 1094 * 1095 * Update<Topic> update = Ebean.createUpdate(Topic.class, updStatement); 1096 * 1097 * update.set("pc", 9); 1098 * update.set("id", 3); 1099 * 1100 * int rows = update.execute(); 1101 * System.out.println("rows updated:" + rows); 1102 * 1103 * }</pre> 1104 */ 1105 public static <T> Update<T> createUpdate(Class<T> beanType, String ormUpdate) { 1106 1107 return serverMgr.getDefaultServer().createUpdate(beanType, ormUpdate); 1108 } 1109 1110 /** 1111 * Create a CsvReader for a given beanType. 1112 */ 1113 public static <T> CsvReader<T> createCsvReader(Class<T> beanType) { 1114 1115 return serverMgr.getDefaultServer().createCsvReader(beanType); 1116 } 1117 1118 /** 1119 * Create a query for a type of entity bean. 1120 * <p> 1121 * You can use the methods on the Query object to specify fetch paths, 1122 * predicates, order by, limits etc. 1123 * </p> 1124 * <p> 1125 * You then use findList(), findSet(), findMap() and findUnique() to execute 1126 * the query and return the collection or bean. 1127 * </p> 1128 * <p> 1129 * Note that a query executed by {@link Query#findList()} 1130 * {@link Query#findSet()} etc will execute against the same EbeanServer from 1131 * which is was created. 1132 * </p> 1133 * 1134 * <pre>{@code 1135 * // Find order 2 additionally fetching the customer, details and details.product 1136 * // name. 1137 * 1138 * Order order = Ebean.find(Order.class) 1139 * .fetch("customer") 1140 * .fetch("details") 1141 * .fetch("detail.product", "name") 1142 * .setId(2) 1143 * .findUnique(); 1144 * 1145 * // Find order 2 additionally fetching the customer, details and details.product 1146 * // name. 1147 * // Note: same query as above but using the query language 1148 * // Note: using a named query would be preferred practice 1149 * 1150 * String oql = "find order fetch customer fetch details fetch details.product (name) where id = :orderId "; 1151 * 1152 * Query<Order> query = Ebean.find(Order.class); 1153 * query.setQuery(oql); 1154 * query.setParameter("orderId", 2); 1155 * 1156 * Order order = query.findUnique(); 1157 * 1158 * // Using a named query 1159 * Query<Order> query = Ebean.find(Order.class, "with.details"); 1160 * query.setParameter("orderId", 2); 1161 * 1162 * Order order = query.findUnique(); 1163 * 1164 * }</pre> 1165 * 1166 * @param beanType 1167 * the class of entity to be fetched 1168 * @return A ORM Query object for this beanType 1169 */ 1170 public static <T> Query<T> createQuery(Class<T> beanType) { 1171 1172 return serverMgr.getDefaultServer().createQuery(beanType); 1173 } 1174 1175 /** 1176 * Create a query for a type of entity bean. 1177 * <p> 1178 * This is actually the same as {@link #createQuery(Class)}. The reason it 1179 * exists is that people used to JPA will probably be looking for a 1180 * createQuery method (the same as entityManager). 1181 * </p> 1182 * 1183 * @param beanType 1184 * the type of entity bean to find 1185 * @return A ORM Query object for this beanType 1186 */ 1187 public static <T> Query<T> find(Class<T> beanType) { 1188 1189 return serverMgr.getDefaultServer().find(beanType); 1190 } 1191 1192 /** 1193 * Create a filter for sorting and filtering lists of entities locally without 1194 * going back to the database. 1195 * <p> 1196 * This produces and returns a new list with the sort and filters applied. 1197 * </p> 1198 * <p> 1199 * Refer to {@link Filter} for an example of its use. 1200 * </p> 1201 */ 1202 public static <T> Filter<T> filter(Class<T> beanType) { 1203 return serverMgr.getDefaultServer().filter(beanType); 1204 } 1205 1206 /** 1207 * Execute a Sql Update Delete or Insert statement. This returns the number of 1208 * rows that where updated, deleted or inserted. If is executed in batch then 1209 * this returns -1. You can get the actual rowCount after commit() from 1210 * updateSql.getRowCount(). 1211 * <p> 1212 * If you wish to execute a Sql Select natively then you should use the 1213 * FindByNativeSql object. 1214 * </p> 1215 * <p> 1216 * Note that the table modification information is automatically deduced and 1217 * you do not need to call the Ebean.externalModification() method when you 1218 * use this method. 1219 * </p> 1220 * <p> 1221 * Example: 1222 * </p> 1223 * 1224 * <pre>{@code 1225 * 1226 * // example that uses 'named' parameters 1227 * String s = "UPDATE f_topic set post_count = :count where id = :id" 1228 * 1229 * SqlUpdate update = Ebean.createSqlUpdate(s); 1230 * 1231 * update.setParameter("id", 1); 1232 * update.setParameter("count", 50); 1233 * 1234 * int modifiedCount = Ebean.execute(update); 1235 * 1236 * String msg = "There where " + modifiedCount + "rows updated"; 1237 * 1238 * }</pre> 1239 * 1240 * @param sqlUpdate 1241 * the update sql potentially with bind values 1242 * 1243 * @return the number of rows updated or deleted. -1 if executed in batch. 1244 * 1245 * @see SqlUpdate 1246 * @see CallableSql 1247 * @see Ebean#execute(CallableSql) 1248 */ 1249 public static int execute(SqlUpdate sqlUpdate) { 1250 return serverMgr.getDefaultServer().execute(sqlUpdate); 1251 } 1252 1253 /** 1254 * For making calls to stored procedures. 1255 * <p> 1256 * Example: 1257 * </p> 1258 * 1259 * <pre>{@code 1260 * 1261 * String sql = "{call sp_order_modify(?,?,?)}"; 1262 * 1263 * CallableSql cs = Ebean.createCallableSql(sql); 1264 * cs.setParameter(1, 27); 1265 * cs.setParameter(2, "SHIPPED"); 1266 * cs.registerOut(3, Types.INTEGER); 1267 * 1268 * Ebean.execute(cs); 1269 * 1270 * // read the out parameter 1271 * Integer returnValue = (Integer) cs.getObject(3); 1272 * 1273 * }</pre> 1274 * 1275 * @see CallableSql 1276 * @see Ebean#execute(SqlUpdate) 1277 */ 1278 public static int execute(CallableSql callableSql) { 1279 return serverMgr.getDefaultServer().execute(callableSql); 1280 } 1281 1282 /** 1283 * Execute a TxRunnable in a Transaction with an explicit scope. 1284 * <p> 1285 * The scope can control the transaction type, isolation and rollback 1286 * semantics. 1287 * </p> 1288 * 1289 * <pre>{@code 1290 * 1291 * // set specific transactional scope settings 1292 * TxScope scope = TxScope.requiresNew().setIsolation(TxIsolation.SERIALIZABLE); 1293 * 1294 * Ebean.execute(scope, new TxRunnable() { 1295 * public void run() { 1296 * User u1 = Ebean.find(User.class, 1); 1297 * ... 1298 * } 1299 * }); 1300 * 1301 * }</pre> 1302 */ 1303 public static void execute(TxScope scope, TxRunnable r) { 1304 serverMgr.getDefaultServer().execute(scope, r); 1305 } 1306 1307 /** 1308 * Execute a TxRunnable in a Transaction with the default scope. 1309 * <p> 1310 * The default scope runs with REQUIRED and by default will rollback on any 1311 * exception (checked or runtime). 1312 * </p> 1313 * 1314 * <pre>{@code 1315 * 1316 * Ebean.execute(new TxRunnable() { 1317 * public void run() { 1318 * User u1 = Ebean.find(User.class, 1); 1319 * User u2 = Ebean.find(User.class, 2); 1320 * 1321 * u1.setName("u1 mod"); 1322 * u2.setName("u2 mod"); 1323 * 1324 * Ebean.save(u1); 1325 * Ebean.save(u2); 1326 * } 1327 * }); 1328 * 1329 * }</pre> 1330 */ 1331 public static void execute(TxRunnable r) { 1332 serverMgr.getDefaultServer().execute(r); 1333 } 1334 1335 /** 1336 * Execute a TxCallable in a Transaction with an explicit scope. 1337 * <p> 1338 * The scope can control the transaction type, isolation and rollback 1339 * semantics. 1340 * </p> 1341 * 1342 * <pre>{@code 1343 * 1344 * // set specific transactional scope settings 1345 * TxScope scope = TxScope.requiresNew().setIsolation(TxIsolation.SERIALIZABLE); 1346 * 1347 * Ebean.execute(scope, new TxCallable<String>() { 1348 * public String call() { 1349 * User u1 = Ebean.find(User.class, 1); 1350 * ... 1351 * return u1.getEmail(); 1352 * } 1353 * }); 1354 * 1355 * }</pre> 1356 * 1357 */ 1358 public static <T> T execute(TxScope scope, TxCallable<T> c) { 1359 return serverMgr.getDefaultServer().execute(scope, c); 1360 } 1361 1362 /** 1363 * Execute a TxCallable in a Transaction with the default scope. 1364 * <p> 1365 * The default scope runs with REQUIRED and by default will rollback on any 1366 * exception (checked or runtime). 1367 * </p> 1368 * <p> 1369 * This is basically the same as TxRunnable except that it returns an Object 1370 * (and you specify the return type via generics). 1371 * </p> 1372 * 1373 * <pre>{@code 1374 * 1375 * Ebean.execute(new TxCallable<String>() { 1376 * public String call() { 1377 * User u1 = Ebean.find(User.class, 1); 1378 * User u2 = Ebean.find(User.class, 2); 1379 * 1380 * u1.setName("u1 mod"); 1381 * u2.setName("u2 mod"); 1382 * 1383 * Ebean.save(u1); 1384 * Ebean.save(u2); 1385 * 1386 * return u1.getEmail(); 1387 * } 1388 * }); 1389 * 1390 * }</pre> 1391 */ 1392 public static <T> T execute(TxCallable<T> c) { 1393 return serverMgr.getDefaultServer().execute(c); 1394 } 1395 1396 /** 1397 * Inform Ebean that tables have been modified externally. These could be the 1398 * result of from calling a stored procedure, other JDBC calls or external 1399 * programs including other frameworks. 1400 * <p> 1401 * If you use Ebean.execute(UpdateSql) then the table modification information 1402 * is automatically deduced and you do not need to call this method yourself. 1403 * </p> 1404 * <p> 1405 * This information is used to invalidate objects out of the cache and 1406 * potentially text indexes. This information is also automatically broadcast 1407 * across the cluster. 1408 * </p> 1409 * <p> 1410 * If there is a transaction then this information is placed into the current 1411 * transactions event information. When the transaction is committed this 1412 * information is registered (with the transaction manager). If this 1413 * transaction is rolled back then none of the transaction event information 1414 * registers including the information you put in via this method. 1415 * </p> 1416 * <p> 1417 * If there is NO current transaction when you call this method then this 1418 * information is registered immediately (with the transaction manager). 1419 * </p> 1420 * 1421 * @param tableName 1422 * the name of the table that was modified 1423 * @param inserts 1424 * true if rows where inserted into the table 1425 * @param updates 1426 * true if rows on the table where updated 1427 * @param deletes 1428 * true if rows on the table where deleted 1429 */ 1430 public static void externalModification(String tableName, boolean inserts, boolean updates, boolean deletes) { 1431 1432 serverMgr.getDefaultServer().externalModification(tableName, inserts, updates, deletes); 1433 } 1434 1435 /** 1436 * Return the BeanState for a given entity bean. 1437 * <p> 1438 * This will return null if the bean is not an enhanced entity bean. 1439 * </p> 1440 */ 1441 public static BeanState getBeanState(Object bean) { 1442 return serverMgr.getDefaultServer().getBeanState(bean); 1443 } 1444 1445 /** 1446 * Return the manager of the server cache ("L2" cache). 1447 * 1448 */ 1449 public static ServerCacheManager getServerCacheManager() { 1450 return serverMgr.getDefaultServer().getServerCacheManager(); 1451 } 1452 1453 /** 1454 * Return the BackgroundExecutor service for asynchronous processing of 1455 * queries. 1456 */ 1457 public static BackgroundExecutor getBackgroundExecutor() { 1458 return serverMgr.getDefaultServer().getBackgroundExecutor(); 1459 } 1460 1461 /** 1462 * Run the cache warming queries on all bean types that have one defined for 1463 * the default/primary EbeanServer. 1464 * <p> 1465 * A cache warming query can be defined via {@link CacheStrategy}. 1466 * </p> 1467 */ 1468 public static void runCacheWarming() { 1469 serverMgr.getDefaultServer().runCacheWarming(); 1470 } 1471 1472 /** 1473 * Run the cache warming query for a specific bean type for the 1474 * default/primary EbeanServer. 1475 * <p> 1476 * A cache warming query can be defined via {@link CacheStrategy}. 1477 * </p> 1478 */ 1479 public static void runCacheWarming(Class<?> beanType) { 1480 1481 serverMgr.getDefaultServer().runCacheWarming(beanType); 1482 } 1483 1484 /** 1485 * Return the JsonContext for reading/writing JSON. 1486 */ 1487 public static JsonContext json() { 1488 return serverMgr.getDefaultServer().json(); 1489 } 1490 1491}