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