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