001package io.ebean; 002 003import io.avaje.lang.NonNullApi; 004import io.avaje.lang.Nullable; 005import io.ebean.annotation.Platform; 006import io.ebean.annotation.TxIsolation; 007import io.ebean.cache.ServerCacheManager; 008import io.ebean.config.DatabaseConfig; 009import io.ebean.meta.MetaInfoManager; 010import io.ebean.plugin.Property; 011import io.ebean.plugin.SpiServer; 012import io.ebean.text.csv.CsvReader; 013import io.ebean.text.json.JsonContext; 014 015import javax.persistence.OptimisticLockException; 016import javax.persistence.PersistenceException; 017import javax.sql.DataSource; 018import java.util.Collection; 019import java.util.List; 020import java.util.Map; 021import java.util.Set; 022import java.util.concurrent.Callable; 023 024/** 025 * Provides the API for fetching and saving beans to a particular database. 026 * 027 * <h5>Registration with the DB singleton</h5> 028 * <p> 029 * When a Database instance is created it can be registered with the DB 030 * singleton (see {@link DatabaseConfig#setRegister(boolean)}). The DB 031 * singleton is essentially a map of Database's that have been registered 032 * with it. 033 * </p> 034 * <p> 035 * The Database can then be retrieved later via {@link DB#byName(String)}. 036 * </p> 037 * 038 * <h5>The 'default' Database</h5> 039 * <p> 040 * One Database can be designated as the 'default' or 'primary' Database 041 * (see {@link DatabaseConfig#setDefaultServer(boolean)}. Many methods on DB 042 * such as {@link DB#find(Class)} etc are actually just a convenient way to 043 * call methods on the 'default/primary' Database. 044 * </p> 045 * 046 * <h5>Constructing a Database</h5> 047 * <p> 048 * Database's are constructed by the DatabaseFactory. They can be created 049 * programmatically via {@link DatabaseFactory#create(DatabaseConfig)} or they 050 * can be automatically constructed on demand using configuration information in 051 * the application.properties file. 052 * </p> 053 * 054 * <h5>Example: Get a Database</h5> 055 * <p> 056 * <pre>{@code 057 * 058 * // Get access to the Human Resources Database 059 * Database hrDatabase = DB.byName("hr"); 060 * 061 * 062 * // fetch contact 3 from the HR database 063 * Contact contact = hrDatabase.find(Contact.class, new Integer(3)); 064 * 065 * contact.setStatus("INACTIVE"); ... 066 * 067 * // save the contact back to the HR database 068 * hrDatabase.save(contact); 069 * 070 * }</pre> 071 * 072 * <h5>Database vs DB API</h5> 073 * <p> 074 * Database provides additional API compared with DB. For example it 075 * provides more control over the use of Transactions that is not available in 076 * the DB API. 077 * </p> 078 * 079 * <p> 080 * <em>External Transactions:</em> If you wanted to use transactions created 081 * externally to Ebean then Database provides additional methods where you 082 * can explicitly pass a transaction (that can be created externally). 083 * </p> 084 * 085 * <p> 086 * <em>Bypass ThreadLocal Mechanism:</em> If you want to bypass the built in 087 * ThreadLocal transaction management you can use the createTransaction() 088 * method. Example: a single thread requires more than one transaction. 089 * </p> 090 * 091 * @see DB 092 * @see DatabaseFactory 093 * @see DatabaseConfig 094 */ 095@NonNullApi 096public interface Database { 097 098 /** 099 * Shutdown the Database instance. 100 */ 101 void shutdown(); 102 103 /** 104 * Shutdown the Database instance programmatically. 105 * <p> 106 * This method is not normally required. Ebean registers a shutdown hook and shuts down cleanly. 107 * </p> 108 * <p> 109 * If the under underlying DataSource is the Ebean implementation then you 110 * also have the option of shutting down the DataSource and deregistering the 111 * JDBC driver. 112 * </p> 113 * 114 * @param shutdownDataSource if true then shutdown the underlying DataSource if it is the Ebean 115 * DataSource implementation. 116 * @param deregisterDriver if true then deregister the JDBC driver if it is the Ebean 117 * DataSource implementation. 118 */ 119 void shutdown(boolean shutdownDataSource, boolean deregisterDriver); 120 121 /** 122 * Return AutoTune which is used to control the AutoTune service at runtime. 123 */ 124 AutoTune autoTune(); 125 126 /** 127 * Deprecated migrate to autoTune(). 128 */ 129 @Deprecated 130 default AutoTune getAutoTune() { 131 return autoTune(); 132 } 133 134 /** 135 * Return the associated DataSource for this Database instance. 136 */ 137 DataSource dataSource(); 138 139 /** 140 * Deprecated migrate to dataSource(). 141 */ 142 @Deprecated 143 default DataSource getDataSource() { 144 return dataSource(); 145 } 146 147 /** 148 * Return the associated read only DataSource for this Database instance (can be null). 149 */ 150 DataSource readOnlyDataSource(); 151 152 /** 153 * Deprecated migrate to readOnlyDataSource(). 154 */ 155 @Deprecated 156 default DataSource getReadOnlyDataSource() { 157 return readOnlyDataSource(); 158 } 159 160 /** 161 * Return the name. This is used with {@link DB#byName(String)} to get a 162 * Database that was registered with the DB singleton. 163 */ 164 String name(); 165 166 /** 167 * Deprecated migrate to name(). 168 */ 169 @Deprecated 170 default String getName() { 171 return name(); 172 } 173 174 /** 175 * Return the ExpressionFactory for this database. 176 */ 177 ExpressionFactory expressionFactory(); 178 179 /** 180 * Deprecated migrate to expressionFactory(). 181 */ 182 @Deprecated 183 default ExpressionFactory getExpressionFactory() { 184 return expressionFactory(); 185 } 186 187 /** 188 * Return the MetaInfoManager which is used to get meta data from the Database 189 * such as query execution statistics. 190 */ 191 MetaInfoManager metaInfo(); 192 193 /** 194 * Deprecated migrate to metaInfo(). 195 */ 196 @Deprecated 197 default MetaInfoManager getMetaInfoManager() { 198 return metaInfo(); 199 } 200 201 /** 202 * Return the platform used for this database instance. 203 * <p> 204 * Note many platforms have multiple specific platform types so often we want to 205 * get the base platform via {@link Platform#base()}. 206 * </p> 207 * <pre>{@code 208 * 209 * Platform platform = database.getPlatform().base(); 210 * if (platform == Platform.MYSQL) { 211 * // do MySql specific function 212 * } 213 * 214 * }</pre> 215 * 216 * @return platform for this database instance 217 */ 218 Platform platform(); 219 220 /** 221 * Deprecated migrate to platform(). 222 */ 223 @Deprecated 224 default Platform getPlatform() { 225 return platform(); 226 } 227 228 /** 229 * Return the extended API intended for use by plugins. 230 */ 231 SpiServer pluginApi(); 232 233 /** 234 * Deprecated migrate to pluginApi(). 235 */ 236 @Deprecated 237 default SpiServer getPluginApi() { 238 return pluginApi(); 239 } 240 241 /** 242 * Return the BeanState for a given entity bean. 243 * <p> 244 * This will return null if the bean is not an enhanced entity bean. 245 * </p> 246 */ 247 BeanState beanState(Object bean); 248 249 /** 250 * Deprecated migrate to beanState(). 251 */ 252 @Deprecated 253 default BeanState getBeanState(Object bean) { 254 return beanState(bean); 255 } 256 257 /** 258 * Return the value of the Id property for a given bean. 259 */ 260 Object beanId(Object bean); 261 262 /** 263 * Deprecated migrate to beanId(). 264 */ 265 @Deprecated 266 default Object getBeanId(Object bean) { 267 return beanId(bean); 268 } 269 270 /** 271 * Set the Id value onto the bean converting the type of the id value if necessary. 272 * <p> 273 * For example, if the id value passed in is a String but ought to be a Long or UUID etc 274 * then it will automatically be converted. 275 * </p> 276 * 277 * @param bean The entity bean to set the id value on. 278 * @param id The id value to set. 279 */ 280 Object beanId(Object bean, Object id); 281 282 /** 283 * Deprecated migrate to beanId(). 284 */ 285 @Deprecated 286 default Object setBeanId(Object bean, Object id) { 287 return beanId(bean, id); 288 } 289 290 /** 291 * Return a map of the differences between two objects of the same type. 292 * <p> 293 * When null is passed in for b, then the 'OldValues' of a is used for the 294 * difference comparison. 295 * </p> 296 */ 297 Map<String, ValuePair> diff(Object newBean, Object oldBean); 298 299 /** 300 * Create a new instance of T that is an EntityBean. 301 * <p> 302 * Useful if you use BeanPostConstructListeners or @PostConstruct Annotations. 303 * In this case you should not use "new Bean...()". Making all bean construtors protected 304 * could be a good idea here. 305 * </p> 306 */ 307 <T> T createEntityBean(Class<T> type); 308 309 /** 310 * Create a CsvReader for a given beanType. 311 */ 312 <T> CsvReader<T> createCsvReader(Class<T> beanType); 313 314 /** 315 * Create an Update query to perform a bulk update. 316 * <p> 317 * <pre>{@code 318 * 319 * int rows = database 320 * .update(Customer.class) 321 * .set("status", Customer.Status.ACTIVE) 322 * .set("updtime", new Timestamp(System.currentTimeMillis())) 323 * .where() 324 * .gt("id", 1000) 325 * .update(); 326 * 327 * }</pre> 328 * 329 * @param beanType The type of entity bean to update 330 * @param <T> The type of entity bean 331 * @return The update query to use 332 */ 333 <T> UpdateQuery<T> update(Class<T> beanType); 334 335 /** 336 * Create a named query. 337 * <p> 338 * For RawSql the named query is expected to be in ebean.xml. 339 * </p> 340 * 341 * @param beanType The type of entity bean 342 * @param namedQuery The name of the query 343 * @param <T> The type of entity bean 344 * @return The query 345 */ 346 <T> Query<T> createNamedQuery(Class<T> beanType, String namedQuery); 347 348 /** 349 * Create a query for an entity bean and synonym for {@link #find(Class)}. 350 * 351 * @see #find(Class) 352 */ 353 <T> Query<T> createQuery(Class<T> beanType); 354 355 /** 356 * Parse the Ebean query language statement returning the query which can then 357 * be modified (add expressions, change order by clause, change maxRows, change 358 * fetch and select paths etc). 359 * <p> 360 * <h3>Example</h3> 361 * <pre>{@code 362 * 363 * // Find order additionally fetching the customer, details and details.product name. 364 * 365 * String ormQuery = "fetch customer fetch details fetch details.product (name) where id = :orderId "; 366 * 367 * Query<Order> query = DB.createQuery(Order.class, ormQuery); 368 * query.setParameter("orderId", 2); 369 * 370 * Order order = query.findOne(); 371 * 372 * // This is the same as: 373 * 374 * Order order = DB.find(Order.class) 375 * .fetch("customer") 376 * .fetch("details") 377 * .fetch("detail.product", "name") 378 * .setId(2) 379 * .findOne(); 380 * 381 * }</pre> 382 * 383 * @param beanType The type of bean to fetch 384 * @param ormQuery The Ebean ORM query 385 * @param <T> The type of the entity bean 386 * @return The query with expressions defined as per the parsed query statement 387 */ 388 <T> Query<T> createQuery(Class<T> beanType, String ormQuery); 389 390 /** 391 * Create a query for a type of entity bean. 392 * <p> 393 * You can use the methods on the Query object to specify fetch paths, 394 * predicates, order by, limits etc. 395 * </p> 396 * <p> 397 * You then use findList(), findSet(), findMap() and findOne() to execute 398 * the query and return the collection or bean. 399 * </p> 400 * <p> 401 * Note that a query executed by {@link Query#findList()} 402 * {@link Query#findSet()} etc will execute against the same Database from 403 * which is was created. 404 * </p> 405 * <p> 406 * <pre>{@code 407 * 408 * // Find order 2 specifying explicitly the parts of the object graph to 409 * // eagerly fetch. In this case eagerly fetch the associated customer, 410 * // details and details.product.name 411 * 412 * Order order = database.find(Order.class) 413 * .fetch("customer") 414 * .fetch("details") 415 * .fetch("detail.product", "name") 416 * .setId(2) 417 * .findOne(); 418 * 419 * // find some new orders ... with firstRow/maxRows 420 * List<Order> orders = 421 * database.find(Order.class) 422 * .where().eq("status", Order.Status.NEW) 423 * .setFirstRow(20) 424 * .setMaxRows(10) 425 * .findList(); 426 * 427 * }</pre> 428 */ 429 <T> Query<T> find(Class<T> beanType); 430 431 /** 432 * Create a query using native SQL. 433 * <p> 434 * The native SQL can contain named parameters or positioned parameters. 435 * </p> 436 * <pre>{@code 437 * 438 * String sql = "select c.id, c.name from customer c where c.name like ? order by c.name"; 439 * 440 * Query<Customer> query = database.findNative(Customer.class, sql); 441 * query.setParameter(1, "Rob%"); 442 * 443 * List<Customer> customers = query.findList(); 444 * 445 * }</pre> 446 * 447 * @param beanType The type of entity bean to fetch 448 * @param nativeSql The SQL that can contain named or positioned parameters 449 * @return The query to set parameters and execute 450 */ 451 <T> Query<T> findNative(Class<T> beanType, String nativeSql); 452 453 /** 454 * Return the next unique identity value for a given bean type. 455 * <p> 456 * This will only work when a IdGenerator is on the bean such as for beans 457 * that use a DB sequence or UUID. 458 * </p> 459 * <p> 460 * For DB's supporting getGeneratedKeys and sequences such as Oracle10 you do 461 * not need to use this method generally. It is made available for more 462 * complex cases where it is useful to get an ID prior to some processing. 463 * </p> 464 */ 465 Object nextId(Class<?> beanType); 466 467 /** 468 * Create a filter for sorting and filtering lists of entities locally without 469 * going back to the database. 470 * <p> 471 * This produces and returns a new list with the sort and filters applied. 472 * </p> 473 * <p> 474 * Refer to {@link Filter} for an example of its use. 475 * </p> 476 */ 477 <T> Filter<T> filter(Class<T> beanType); 478 479 /** 480 * Sort the list in memory using the sortByClause which can contain a comma delimited 481 * list of property names and keywords asc, desc, nullsHigh and nullsLow. 482 * <ul> 483 * <li>asc - ascending order (which is the default)</li> 484 * <li>desc - Descending order</li> 485 * <li>nullsHigh - Treat null values as high/large values (which is the 486 * default)</li> 487 * <li>nullsLow- Treat null values as low/very small values</li> 488 * </ul> 489 * <p> 490 * If you leave off any keywords the defaults are ascending order and treating 491 * nulls as high values. 492 * </p> 493 * <p> 494 * Note that the sorting uses a Comparator and Collections.sort(); and does 495 * not invoke a DB query. 496 * </p> 497 * <p> 498 * <pre>{@code 499 * 500 * // find orders and their customers 501 * List<Order> list = database.find(Order.class) 502 * .fetch("customer") 503 * .order("id") 504 * .findList(); 505 * 506 * // sort by customer name ascending, then by order shipDate 507 * // ... then by the order status descending 508 * database.sort(list, "customer.name, shipDate, status desc"); 509 * 510 * // sort by customer name descending (with nulls low) 511 * // ... then by the order id 512 * database.sort(list, "customer.name desc nullsLow, id"); 513 * 514 * }</pre> 515 * 516 * @param list the list of entity beans 517 * @param sortByClause the properties to sort the list by 518 */ 519 <T> void sort(List<T> list, String sortByClause); 520 521 /** 522 * Create a orm update where you will supply the insert/update or delete 523 * statement (rather than using a named one that is already defined using the 524 * @NamedUpdates annotation). 525 * <p> 526 * The orm update differs from the sql update in that it you can use the bean 527 * name and bean property names rather than table and column names. 528 * </p> 529 * <p> 530 * An example: 531 * </p> 532 * <p> 533 * <pre>{@code 534 * 535 * // The bean name and properties - "topic","postCount" and "id" 536 * 537 * // will be converted into their associated table and column names 538 * String updStatement = "update topic set postCount = :pc where id = :id"; 539 * 540 * Update<Topic> update = database.createUpdate(Topic.class, updStatement); 541 * 542 * update.set("pc", 9); 543 * update.set("id", 3); 544 * 545 * int rows = update.execute(); 546 * System.out.println("rows updated:" + rows); 547 * 548 * }</pre> 549 */ 550 <T> Update<T> createUpdate(Class<T> beanType, String ormUpdate); 551 552 /** 553 * Create a Query for DTO beans. 554 * <p> 555 * DTO beans are just normal bean like classes with public constructor(s) and setters. 556 * They do not need to be registered with DB before use. 557 * </p> 558 * 559 * @param dtoType The type of the DTO bean the rows will be mapped into. 560 * @param sql The SQL query to execute. 561 * @param <T> The type of the DTO bean. 562 */ 563 <T> DtoQuery<T> findDto(Class<T> dtoType, String sql); 564 565 /** 566 * Create a named Query for DTO beans. 567 * <p> 568 * DTO beans are just normal bean like classes with public constructor(s) and setters. 569 * They do not need to be registered with DB before use. 570 * </p> 571 * 572 * @param dtoType The type of the DTO bean the rows will be mapped into. 573 * @param namedQuery The name of the query 574 * @param <T> The type of the DTO bean. 575 */ 576 <T> DtoQuery<T> createNamedDtoQuery(Class<T> dtoType, String namedQuery); 577 578 /** 579 * Look to execute a native sql query that does not return beans but instead 580 * returns SqlRow or direct access to ResultSet. 581 * 582 * <p> 583 * Refer to {@link DtoQuery} for native sql queries returning DTO beans. 584 * </p> 585 * <p> 586 * Refer to {@link #findNative(Class, String)} for native sql queries returning entity beans. 587 * </p> 588 */ 589 SqlQuery sqlQuery(String sql); 590 591 /** 592 * Deprecated - migrate to sqlQuery(). 593 * <p> 594 * This is an alias for {@link #sqlQuery(String)}. 595 */ 596 @Deprecated 597 SqlQuery createSqlQuery(String sql); 598 599 /** 600 * Look to execute a native sql insert update or delete statement. 601 * <p> 602 * Use this to execute a Insert Update or Delete statement. The statement will 603 * be native to the database and contain database table and column names. 604 * </p> 605 * 606 * <p> 607 * See {@link SqlUpdate} for example usage. 608 * </p> 609 * 610 * @return The SqlUpdate instance to set parameters and execute 611 */ 612 SqlUpdate sqlUpdate(String sql); 613 614 /** 615 * Deprecated - migrate to sqlUpdate(). 616 * <p> 617 * This is an alias for {@link #sqlUpdate(String)}. 618 */ 619 @Deprecated 620 SqlUpdate createSqlUpdate(String sql); 621 622 /** 623 * Create a CallableSql to execute a given stored procedure. 624 */ 625 CallableSql createCallableSql(String callableSql); 626 627 /** 628 * Register a TransactionCallback on the currently active transaction. 629 * <p/> 630 * If there is no currently active transaction then a PersistenceException is thrown. 631 * 632 * @param transactionCallback The transaction callback to be registered with the current transaction. 633 * @throws PersistenceException If there is no currently active transaction 634 */ 635 void register(TransactionCallback transactionCallback) throws PersistenceException; 636 637 /** 638 * Create a new transaction that is not held in TransactionThreadLocal. 639 * <p> 640 * You will want to do this if you want multiple Transactions in a single 641 * thread or generally use transactions outside of the TransactionThreadLocal 642 * management. 643 * </p> 644 */ 645 Transaction createTransaction(); 646 647 /** 648 * Create a new transaction additionally specifying the isolation level. 649 * <p> 650 * Note that this transaction is NOT stored in a thread local. 651 * </p> 652 */ 653 Transaction createTransaction(TxIsolation isolation); 654 655 /** 656 * Start a transaction with 'REQUIRED' semantics. 657 * <p> 658 * With REQUIRED semantics if an active transaction already exists that transaction will be used. 659 * </p> 660 * <p> 661 * The transaction is stored in a ThreadLocal variable and typically you only 662 * need to use the returned Transaction <em>IF</em> you wish to do things like 663 * use batch mode, change the transaction isolation level, use savepoints or 664 * log comments to the transaction log. 665 * </p> 666 * <p> 667 * Example of using a transaction to span multiple calls to find(), save() 668 * etc. 669 * </p> 670 * <p> 671 * <h3>Using try with resources</h3> 672 * <pre>{@code 673 * 674 * // start a transaction (stored in a ThreadLocal) 675 * 676 * try (Transaction txn = database.beginTransaction()) { 677 * 678 * Order order = database.find(Order.class, 10); 679 * ... 680 * database.save(order); 681 * 682 * txn.commit(); 683 * } 684 * 685 * }</pre> 686 * <p> 687 * <h3>Using try finally block</h3> 688 * <pre>{@code 689 * 690 * // start a transaction (stored in a ThreadLocal) 691 * Transaction txn = database.beginTransaction(); 692 * try { 693 * Order order = database.find(Order.class,10); 694 * 695 * database.save(order); 696 * 697 * txn.commit(); 698 * 699 * } finally { 700 * txn.end(); 701 * } 702 * 703 * }</pre> 704 * <p> 705 * <h3>Transaction options</h3> 706 * <pre>{@code 707 * 708 * try (Transaction txn = database.beginTransaction()) { 709 * 710 * // explicitly turn on/off JDBC batch use 711 * txn.setBatchMode(true); 712 * txn.setBatchSize(50); 713 * 714 * // control flushing when mixing save and queries 715 * txn.setBatchFlushOnQuery(false); 716 * 717 * // turn off persist cascade if needed 718 * txn.setPersistCascade(false); 719 * 720 * // for large batch insert processing when we do not 721 * // ... need the generatedKeys, don't get them 722 * txn.setBatchGetGeneratedKeys(false); 723 * 724 * // explicitly flush the JDBC batch buffer 725 * txn.flush(); 726 * 727 * ... 728 * 729 * txn.commit(); 730 * } 731 * 732 * }</pre> 733 * <p> 734 * <p> 735 * If you want to externalise the transaction management then you use 736 * createTransaction() and pass the transaction around to the various methods on 737 * Database yourself. 738 * </p> 739 */ 740 Transaction beginTransaction(); 741 742 /** 743 * Start a transaction additionally specifying the isolation level. 744 */ 745 Transaction beginTransaction(TxIsolation isolation); 746 747 /** 748 * Start a transaction typically specifying REQUIRES_NEW or REQUIRED semantics. 749 * <p> 750 * <p> 751 * Note that this provides an try finally alternative to using {@link #executeCall(TxScope, Callable)} or 752 * {@link #execute(TxScope, Runnable)}. 753 * </p> 754 * <p> 755 * <h3>REQUIRES_NEW example:</h3> 756 * <pre>{@code 757 * // Start a new transaction. If there is a current transaction 758 * // suspend it until this transaction ends 759 * try (Transaction txn = database.beginTransaction(TxScope.requiresNew())) { 760 * 761 * ... 762 * 763 * // commit the transaction 764 * txn.commit(); 765 * 766 * // At end this transaction will: 767 * // A) will rollback transaction if it has not been committed 768 * // B) will restore a previously suspended transaction 769 * } 770 * 771 * }</pre> 772 * <p> 773 * <h3>REQUIRED example:</h3> 774 * <pre>{@code 775 * 776 * // start a new transaction if there is not a current transaction 777 * try (Transaction txn = database.beginTransaction(TxScope.required())) { 778 * 779 * ... 780 * 781 * // commit the transaction if it was created or 782 * // do nothing if there was already a current transaction 783 * txn.commit(); 784 * } 785 * 786 * }</pre> 787 */ 788 Transaction beginTransaction(TxScope scope); 789 790 /** 791 * Returns the current transaction or null if there is no current transaction in scope. 792 */ 793 Transaction currentTransaction(); 794 795 /** 796 * Flush the JDBC batch on the current transaction. 797 * <p> 798 * This only is useful when JDBC batch is used. Flush occurs automatically when the 799 * transaction commits or batch size is reached. This manually flushes the JDBC batch 800 * buffer. 801 * </p> 802 * <p> 803 * This is the same as <code>currentTransaction().flush()</code>. 804 * </p> 805 */ 806 void flush(); 807 808 /** 809 * Commit the current transaction. 810 */ 811 void commitTransaction(); 812 813 /** 814 * Rollback the current transaction. 815 */ 816 void rollbackTransaction(); 817 818 /** 819 * If the current transaction has already been committed do nothing otherwise 820 * rollback the transaction. 821 * <p> 822 * Useful to put in a finally block to ensure the transaction is ended, rather 823 * than a rollbackTransaction() in each catch block. 824 * </p> 825 * <p> 826 * Code example: 827 * <p> 828 * <pre>{@code 829 * 830 * database.beginTransaction(); 831 * try { 832 * // do some fetching and or persisting ... 833 * 834 * // commit at the end 835 * database.commitTransaction(); 836 * 837 * } finally { 838 * // if commit didn't occur then rollback the transaction 839 * database.endTransaction(); 840 * } 841 * 842 * }</pre> 843 */ 844 void endTransaction(); 845 846 /** 847 * Refresh the values of a bean. 848 * <p> 849 * Note that this resets OneToMany and ManyToMany properties so that if they 850 * are accessed a lazy load will refresh the many property. 851 * </p> 852 */ 853 void refresh(Object bean); 854 855 /** 856 * Refresh a many property of an entity bean. 857 * 858 * @param bean the entity bean containing the 'many' property 859 * @param propertyName the 'many' property to be refreshed 860 */ 861 void refreshMany(Object bean, String propertyName); 862 863 /** 864 * Find a bean using its unique id. 865 * <p> 866 * <pre>{@code 867 * // Fetch order 1 868 * Order order = database.find(Order.class, 1); 869 * }</pre> 870 * <p> 871 * <p> 872 * If you want more control over the query then you can use createQuery() and 873 * Query.findOne(); 874 * </p> 875 * <p> 876 * <pre>{@code 877 * // ... additionally fetching customer, customer shipping address, 878 * // order details, and the product associated with each order detail. 879 * // note: only product id and name is fetch (its a "partial object"). 880 * // note: all other objects use "*" and have all their properties fetched. 881 * 882 * Query<Order> query = database.find(Order.class) 883 * .setId(1) 884 * .fetch("customer") 885 * .fetch("customer.shippingAddress") 886 * .fetch("details") 887 * .query(); 888 * 889 * // fetch associated products but only fetch their product id and name 890 * query.fetch("details.product", "name"); 891 * 892 * 893 * Order order = query.findOne(); 894 * 895 * // traverse the object graph... 896 * 897 * Customer customer = order.getCustomer(); 898 * Address shippingAddress = customer.getShippingAddress(); 899 * List<OrderDetail> details = order.getDetails(); 900 * OrderDetail detail0 = details.get(0); 901 * Product product = detail0.getProduct(); 902 * String productName = product.getName(); 903 * 904 * }</pre> 905 * 906 * @param beanType the type of entity bean to fetch 907 * @param id the id value 908 */ 909 @Nullable 910 <T> T find(Class<T> beanType, Object id); 911 912 /** 913 * Get a reference object. 914 * <p> 915 * This will not perform a query against the database unless some property other 916 * that the id property is accessed. 917 * </p> 918 * <p> 919 * It is most commonly used to set a 'foreign key' on another bean like: 920 * </p> 921 * <pre>{@code 922 * 923 * Product product = database.getReference(Product.class, 1); 924 * 925 * OrderDetail orderDetail = new OrderDetail(); 926 * // set the product 'foreign key' 927 * orderDetail.setProduct(product); 928 * orderDetail.setQuantity(42); 929 * ... 930 * 931 * database.save(orderDetail); 932 * 933 * 934 * }</pre> 935 * <p> 936 * <h3>Lazy loading characteristics</h3> 937 * <pre>{@code 938 * 939 * Product product = database.getReference(Product.class, 1); 940 * 941 * // You can get the id without causing a fetch/lazy load 942 * Long productId = product.getId(); 943 * 944 * // If you try to get any other property a fetch/lazy loading will occur 945 * // This will cause a query to execute... 946 * String name = product.getName(); 947 * 948 * }</pre> 949 * 950 * @param beanType the type of entity bean 951 * @param id the id value 952 */ 953 <T> T reference(Class<T> beanType, Object id); 954 955 /** 956 * Deprecated migrate to reference(). 957 */ 958 @Deprecated 959 default <T> T getReference(Class<T> beanType, Object id) { 960 return reference(beanType, id); 961 } 962 963 /** 964 * Return the extended API for Database. 965 * <p> 966 * The extended API has the options for executing queries that take an explicit 967 * transaction as an argument. 968 * </p> 969 * <p> 970 * Typically we only need to use the extended API when we do NOT want to use the 971 * usual ThreadLocal based mechanism to obtain the current transaction but instead 972 * supply the transaction explicitly. 973 * </p> 974 */ 975 ExtendedServer extended(); 976 977 /** 978 * Either Insert or Update the bean depending on its state. 979 * <p> 980 * If there is no current transaction one will be created and committed for 981 * you automatically. 982 * </p> 983 * <p> 984 * Save can cascade along relationships. For this to happen you need to 985 * specify a cascade of CascadeType.ALL or CascadeType.PERSIST on the 986 * OneToMany, OneToOne or ManyToMany annotation. 987 * </p> 988 * <p> 989 * In this example below the details property has a CascadeType.ALL set so 990 * saving an order will also save all its details. 991 * </p> 992 * <p> 993 * <pre>{@code 994 * public class Order { ... 995 * 996 * @OneToMany(cascade=CascadeType.ALL, mappedBy="order") 997 * List<OrderDetail> details; 998 * ... 999 * } 1000 * }</pre> 1001 * <p> 1002 * <p> 1003 * When a save cascades via a OneToMany or ManyToMany Ebean will automatically 1004 * set the 'parent' object to the 'detail' object. In the example below in 1005 * saving the order and cascade saving the order details the 'parent' order 1006 * will be set against each order detail when it is saved. 1007 * </p> 1008 */ 1009 void save(Object bean) throws OptimisticLockException; 1010 1011 /** 1012 * Save all the beans in the collection. 1013 */ 1014 int saveAll(Collection<?> beans) throws OptimisticLockException; 1015 1016 /** 1017 * Save all the beans. 1018 */ 1019 int saveAll(Object... beans) throws OptimisticLockException; 1020 1021 /** 1022 * Delete the bean. 1023 * <p> 1024 * This will return true if the bean was deleted successfully or JDBC batch is being used. 1025 * </p> 1026 * <p> 1027 * If there is no current transaction one will be created and committed for 1028 * you automatically. 1029 * </p> 1030 * <p> 1031 * If the Bean does not have a version property (or loaded version property) and 1032 * the bean does not exist then this returns false indicating that nothing was 1033 * deleted. Note that, if JDBC batch mode is used then this always returns true. 1034 * </p> 1035 */ 1036 boolean delete(Object bean) throws OptimisticLockException; 1037 1038 /** 1039 * Delete the bean with an explicit transaction. 1040 * <p> 1041 * This will return true if the bean was deleted successfully or JDBC batch is being used. 1042 * </p> 1043 * <p> 1044 * If the Bean does not have a version property (or loaded version property) and 1045 * the bean does not exist then this returns false indicating that nothing was 1046 * deleted. However, if JDBC batch mode is used then this always returns true. 1047 * </p> 1048 */ 1049 boolean delete(Object bean, Transaction transaction) throws OptimisticLockException; 1050 1051 /** 1052 * Delete a bean permanently without soft delete. 1053 */ 1054 boolean deletePermanent(Object bean) throws OptimisticLockException; 1055 1056 /** 1057 * Delete a bean permanently without soft delete using an explicit transaction. 1058 */ 1059 boolean deletePermanent(Object bean, Transaction transaction) throws OptimisticLockException; 1060 1061 /** 1062 * Delete all the beans in the collection permanently without soft delete. 1063 */ 1064 int deleteAllPermanent(Collection<?> beans) throws OptimisticLockException; 1065 1066 /** 1067 * Delete all the beans in the collection permanently without soft delete using an explicit transaction. 1068 */ 1069 int deleteAllPermanent(Collection<?> beans, Transaction transaction) throws OptimisticLockException; 1070 1071 /** 1072 * Delete the bean given its type and id. 1073 */ 1074 int delete(Class<?> beanType, Object id); 1075 1076 /** 1077 * Delete the bean given its type and id with an explicit transaction. 1078 */ 1079 int delete(Class<?> beanType, Object id, Transaction transaction); 1080 1081 /** 1082 * Delete permanent given the bean type and id. 1083 */ 1084 int deletePermanent(Class<?> beanType, Object id); 1085 1086 /** 1087 * Delete permanent given the bean type and id with an explicit transaction. 1088 */ 1089 int deletePermanent(Class<?> beanType, Object id, Transaction transaction); 1090 1091 /** 1092 * Delete all the beans in the collection. 1093 */ 1094 int deleteAll(Collection<?> beans) throws OptimisticLockException; 1095 1096 /** 1097 * Delete all the beans in the collection using an explicit transaction. 1098 */ 1099 int deleteAll(Collection<?> beans, Transaction transaction) throws OptimisticLockException; 1100 1101 /** 1102 * Delete several beans given their type and id values. 1103 */ 1104 int deleteAll(Class<?> beanType, Collection<?> ids); 1105 1106 /** 1107 * Delete several beans given their type and id values with an explicit transaction. 1108 */ 1109 int deleteAll(Class<?> beanType, Collection<?> ids, Transaction transaction); 1110 1111 /** 1112 * Delete permanent for several beans given their type and id values. 1113 */ 1114 int deleteAllPermanent(Class<?> beanType, Collection<?> ids); 1115 1116 /** 1117 * Delete permanent for several beans given their type and id values with an explicit transaction. 1118 */ 1119 int deleteAllPermanent(Class<?> beanType, Collection<?> ids, Transaction transaction); 1120 1121 /** 1122 * Execute a Sql Update Delete or Insert statement. This returns the number of 1123 * rows that where updated, deleted or inserted. If is executed in batch then 1124 * this returns -1. You can get the actual rowCount after commit() from 1125 * updateSql.getRowCount(). 1126 * <p> 1127 * If you wish to execute a Sql Select natively then you should use the 1128 * SqlQuery object or DtoQuery. 1129 * </p> 1130 * <p> 1131 * Note that the table modification information is automatically deduced and 1132 * you do not need to call the DB.externalModification() method when you 1133 * use this method. 1134 * </p> 1135 * <p> 1136 * Example: 1137 * </p> 1138 * <p> 1139 * <pre>{@code 1140 * 1141 * // example that uses 'named' parameters 1142 * String s = "UPDATE f_topic set post_count = :count where id = :id" 1143 * 1144 * SqlUpdate update = database.createSqlUpdate(s); 1145 * 1146 * update.setParameter("id", 1); 1147 * update.setParameter("count", 50); 1148 * 1149 * int modifiedCount = database.execute(update); 1150 * 1151 * String msg = "There where " + modifiedCount + "rows updated"; 1152 * 1153 * }</pre> 1154 * 1155 * @param sqlUpdate the update sql potentially with bind values 1156 * @return the number of rows updated or deleted. -1 if executed in batch. 1157 * @see CallableSql 1158 */ 1159 int execute(SqlUpdate sqlUpdate); 1160 1161 /** 1162 * Execute a ORM insert update or delete statement using the current 1163 * transaction. 1164 * <p> 1165 * This returns the number of rows that where inserted, updated or deleted. 1166 * </p> 1167 */ 1168 int execute(Update<?> update); 1169 1170 /** 1171 * Execute a ORM insert update or delete statement with an explicit 1172 * transaction. 1173 */ 1174 int execute(Update<?> update, Transaction transaction); 1175 1176 /** 1177 * For making calls to stored procedures. 1178 * <p> 1179 * Example: 1180 * </p> 1181 * <p> 1182 * <pre>{@code 1183 * 1184 * String sql = "{call sp_order_modify(?,?,?)}"; 1185 * 1186 * CallableSql cs = database.createCallableSql(sql); 1187 * cs.setParameter(1, 27); 1188 * cs.setParameter(2, "SHIPPED"); 1189 * cs.registerOut(3, Types.INTEGER); 1190 * cs.execute(); 1191 * 1192 * // read the out parameter 1193 * Integer returnValue = (Integer) cs.getObject(3); 1194 * 1195 * }</pre> 1196 */ 1197 int execute(CallableSql callableSql); 1198 1199 /** 1200 * Inform Ebean that tables have been modified externally. These could be the 1201 * result of from calling a stored procedure, other JDBC calls or external 1202 * programs including other frameworks. 1203 * <p> 1204 * If you use database.execute(UpdateSql) then the table modification information 1205 * is automatically deduced and you do not need to call this method yourself. 1206 * </p> 1207 * <p> 1208 * This information is used to invalidate objects out of the cache and 1209 * potentially text indexes. This information is also automatically broadcast 1210 * across the cluster. 1211 * </p> 1212 * <p> 1213 * If there is a transaction then this information is placed into the current 1214 * transactions event information. When the transaction is committed this 1215 * information is registered (with the transaction manager). If this 1216 * transaction is rolled back then none of the transaction event information 1217 * registers including the information you put in via this method. 1218 * </p> 1219 * <p> 1220 * If there is NO current transaction when you call this method then this 1221 * information is registered immediately (with the transaction manager). 1222 * </p> 1223 * 1224 * @param tableName the name of the table that was modified 1225 * @param inserted true if rows where inserted into the table 1226 * @param updated true if rows on the table where updated 1227 * @param deleted true if rows on the table where deleted 1228 */ 1229 void externalModification(String tableName, boolean inserted, boolean updated, boolean deleted); 1230 1231 /** 1232 * Find a entity bean with an explicit transaction. 1233 * 1234 * @param <T> the type of entity bean to find 1235 * @param beanType the type of entity bean to find 1236 * @param id the bean id value 1237 * @param transaction the transaction to use (can be null) 1238 */ 1239 @Nullable 1240 <T> T find(Class<T> beanType, Object id, Transaction transaction); 1241 1242 /** 1243 * Insert or update a bean with an explicit transaction. 1244 */ 1245 void save(Object bean, Transaction transaction) throws OptimisticLockException; 1246 1247 /** 1248 * Save all the beans in the collection with an explicit transaction. 1249 */ 1250 int saveAll(Collection<?> beans, Transaction transaction) throws OptimisticLockException; 1251 1252 /** 1253 * This method checks the uniqueness of a bean. I.e. if the save will work. It will return the 1254 * properties that violates an unique / primary key. This may be done in an UI save action to 1255 * validate if the user has entered correct values. 1256 * <p> 1257 * Note: This method queries the DB for uniqueness of all indices, so do not use it in a batch update. 1258 * <p> 1259 * Note: This checks only the root bean! 1260 * <p> 1261 * <pre>{@code 1262 * 1263 * // there is a unique constraint on title 1264 * 1265 * Document doc = new Document(); 1266 * doc.setTitle("One flew over the cuckoo's nest"); 1267 * doc.setBody("clashes with doc1"); 1268 * 1269 * Set<Property> properties = DB.checkUniqueness(doc); 1270 * 1271 * if (properties.isEmpty()) { 1272 * // it is unique ... carry on 1273 * 1274 * } else { 1275 * // build a user friendly message 1276 * // to return message back to user 1277 * 1278 * String uniqueProperties = properties.toString(); 1279 * 1280 * StringBuilder msg = new StringBuilder(); 1281 * 1282 * properties.forEach((it)-> { 1283 * Object propertyValue = it.getVal(doc); 1284 * String propertyName = it.getName(); 1285 * msg.append(" property["+propertyName+"] value["+propertyValue+"]"); 1286 * }); 1287 * 1288 * // uniqueProperties > [title] 1289 * // custom msg > property[title] value[One flew over the cuckoo's nest] 1290 * 1291 * } 1292 * 1293 * }</pre> 1294 * 1295 * @param bean The entity bean to check uniqueness on 1296 * @return a set of Properties if constraint validation was detected or empty list. 1297 */ 1298 Set<Property> checkUniqueness(Object bean); 1299 1300 /** 1301 * Same as {@link #checkUniqueness(Object)}. but with given transaction. 1302 */ 1303 Set<Property> checkUniqueness(Object bean, Transaction transaction); 1304 1305 /** 1306 * Marks the entity bean as dirty. 1307 * <p> 1308 * This is used so that when a bean that is otherwise unmodified is updated the version 1309 * property is updated. 1310 * <p> 1311 * An unmodified bean that is saved or updated is normally skipped and this marks the bean as 1312 * dirty so that it is not skipped. 1313 * <p> 1314 * <pre>{@code 1315 * 1316 * Customer customer = database.find(Customer, id); 1317 * 1318 * // mark the bean as dirty so that a save() or update() will 1319 * // increment the version property 1320 * database.markAsDirty(customer); 1321 * database.save(customer); 1322 * 1323 * }</pre> 1324 */ 1325 void markAsDirty(Object bean); 1326 1327 /** 1328 * Saves the bean using an update. If you know you are updating a bean then it is preferable to 1329 * use this update() method rather than save(). 1330 * <p> 1331 * <b>Stateless updates:</b> Note that the bean does not have to be previously fetched to call 1332 * update().You can create a new instance and set some of its properties programmatically for via 1333 * JSON/XML marshalling etc. This is described as a 'stateless update'. 1334 * </p> 1335 * <p> 1336 * <b>Optimistic Locking: </b> Note that if the version property is not set when update() is 1337 * called then no optimistic locking is performed (internally ConcurrencyMode.NONE is used). 1338 * </p> 1339 * <pre>{@code 1340 * 1341 * // A 'stateless update' example 1342 * Customer customer = new Customer(); 1343 * customer.setId(7); 1344 * customer.setName("ModifiedNameNoOCC"); 1345 * database.update(customer); 1346 * 1347 * }</pre> 1348 */ 1349 void update(Object bean) throws OptimisticLockException; 1350 1351 /** 1352 * Update a bean additionally specifying a transaction. 1353 */ 1354 void update(Object bean, Transaction transaction) throws OptimisticLockException; 1355 1356 /** 1357 * Update a collection of beans. If there is no current transaction one is created and used to 1358 * update all the beans in the collection. 1359 */ 1360 void updateAll(Collection<?> beans) throws OptimisticLockException; 1361 1362 /** 1363 * Update a collection of beans with an explicit transaction. 1364 */ 1365 void updateAll(Collection<?> beans, Transaction transaction) throws OptimisticLockException; 1366 1367 /** 1368 * Merge the bean using the default merge options (no paths specified, default delete). 1369 * 1370 * @param bean The bean to merge 1371 */ 1372 void merge(Object bean); 1373 1374 /** 1375 * Merge the bean using the given merge options. 1376 * 1377 * @param bean The bean to merge 1378 * @param options The options to control the merge 1379 */ 1380 void merge(Object bean, MergeOptions options); 1381 1382 /** 1383 * Merge the bean using the given merge options and a transaction. 1384 * 1385 * @param bean The bean to merge 1386 * @param options The options to control the merge 1387 */ 1388 void merge(Object bean, MergeOptions options, Transaction transaction); 1389 1390 /** 1391 * Insert the bean. 1392 * <p> 1393 * Compared to save() this forces bean to perform an insert rather than trying to decide 1394 * based on the bean state. As such this is useful when you fetch beans from one database 1395 * and want to insert them into another database (and you want to explicitly insert them). 1396 * </p> 1397 */ 1398 void insert(Object bean); 1399 1400 /** 1401 * Insert the bean with a transaction. 1402 */ 1403 void insert(Object bean, Transaction transaction); 1404 1405 /** 1406 * Insert a collection of beans. If there is no current transaction one is created and used to 1407 * insert all the beans in the collection. 1408 */ 1409 void insertAll(Collection<?> beans); 1410 1411 /** 1412 * Insert a collection of beans with an explicit transaction. 1413 */ 1414 void insertAll(Collection<?> beans, Transaction transaction); 1415 1416 /** 1417 * Execute explicitly passing a transaction. 1418 */ 1419 int execute(SqlUpdate updSql, Transaction transaction); 1420 1421 /** 1422 * Execute explicitly passing a transaction. 1423 */ 1424 int execute(CallableSql callableSql, Transaction transaction); 1425 1426 /** 1427 * Execute a Runnable in a Transaction with an explicit scope. 1428 * <p> 1429 * The scope can control the transaction type, isolation and rollback 1430 * semantics. 1431 * </p> 1432 * <p> 1433 * <pre>{@code 1434 * 1435 * // set specific transactional scope settings 1436 * TxScope scope = TxScope.requiresNew().setIsolation(TxIsolation.SERIALIZABLE); 1437 * 1438 * database.execute(scope, new Runnable() { 1439 * public void run() { 1440 * User u1 = database.find(User.class, 1); 1441 * ... 1442 * } 1443 * }); 1444 * 1445 * }</pre> 1446 */ 1447 void execute(TxScope scope, Runnable runnable); 1448 1449 /** 1450 * Execute a Runnable in a Transaction with the default scope. 1451 * <p> 1452 * The default scope runs with REQUIRED and by default will rollback on any 1453 * exception (checked or runtime). 1454 * </p> 1455 * <p> 1456 * <pre>{@code 1457 * 1458 * database.execute(() -> { 1459 * 1460 * User u1 = database.find(User.class, 1); 1461 * User u2 = database.find(User.class, 2); 1462 * 1463 * u1.setName("u1 mod"); 1464 * u2.setName("u2 mod"); 1465 * 1466 * u1.save(); 1467 * u2.save(); 1468 * }); 1469 * 1470 * }</pre> 1471 */ 1472 void execute(Runnable runnable); 1473 1474 /** 1475 * Execute a TxCallable in a Transaction with an explicit scope. 1476 * <p> 1477 * The scope can control the transaction type, isolation and rollback 1478 * semantics. 1479 * </p> 1480 * <p> 1481 * <pre>{@code 1482 * 1483 * // set specific transactional scope settings 1484 * TxScope scope = TxScope.requiresNew().setIsolation(TxIsolation.SERIALIZABLE); 1485 * 1486 * database.executeCall(scope, new Callable<String>() { 1487 * public String call() { 1488 * User u1 = database.find(User.class, 1); 1489 * ... 1490 * return u1.getEmail(); 1491 * } 1492 * }); 1493 * 1494 * }</pre> 1495 */ 1496 <T> T executeCall(TxScope scope, Callable<T> callable); 1497 1498 /** 1499 * Execute a TxCallable in a Transaction with the default scope. 1500 * <p> 1501 * The default scope runs with REQUIRED and by default will rollback on any 1502 * exception (checked or runtime). 1503 * </p> 1504 * <p> 1505 * <pre>{@code 1506 * 1507 * database.executeCall(new Callable<String>() { 1508 * public String call() { 1509 * User u1 = database.find(User.class, 1); 1510 * User u2 = database.find(User.class, 2); 1511 * 1512 * u1.setName("u1 mod"); 1513 * u2.setName("u2 mod"); 1514 * 1515 * database.save(u1); 1516 * database.save(u2); 1517 * 1518 * return u1.getEmail(); 1519 * } 1520 * }); 1521 * 1522 * }</pre> 1523 */ 1524 <T> T executeCall(Callable<T> callable); 1525 1526 /** 1527 * Return the manager of the server cache ("L2" cache). 1528 */ 1529 ServerCacheManager cacheManager(); 1530 1531 /** 1532 * Deprecated migrate to cacheManager(). 1533 */ 1534 @Deprecated 1535 default ServerCacheManager getServerCacheManager() { 1536 return cacheManager(); 1537 } 1538 1539 /** 1540 * Return the BackgroundExecutor service for asynchronous processing of 1541 * queries. 1542 */ 1543 BackgroundExecutor backgroundExecutor(); 1544 1545 /** 1546 * Deprecated migrate to backgroundExecutor(). 1547 */ 1548 @Deprecated 1549 default BackgroundExecutor getBackgroundExecutor() { 1550 return backgroundExecutor(); 1551 } 1552 1553 /** 1554 * Return the JsonContext for reading/writing JSON. 1555 * <p> 1556 * This instance is safe to be used concurrently by multiple threads and this 1557 * method is cheap to call. 1558 * </p> 1559 * <p> 1560 * <h3>Simple example:</h3> 1561 * <pre>{@code 1562 * 1563 * JsonContext json = database.json(); 1564 * String jsonOutput = json.toJson(list); 1565 * System.out.println(jsonOutput); 1566 * 1567 * }</pre> 1568 * <p> 1569 * <h3>Using PathProperties:</h3> 1570 * <pre>{@code 1571 * 1572 * // specify just the properties we want 1573 * PathProperties paths = PathProperties.parse("name, status, anniversary"); 1574 * 1575 * List<Customer> customers = 1576 * database.find(Customer.class) 1577 * // apply those paths to the query (only fetch what we need) 1578 * .apply(paths) 1579 * .where().ilike("name", "rob%") 1580 * .findList(); 1581 * 1582 * // ... get the json 1583 * JsonContext jsonContext = database.json(); 1584 * String json = jsonContext.toJson(customers, paths); 1585 * 1586 * }</pre> 1587 * 1588 * @see FetchPath 1589 * @see Query#apply(FetchPath) 1590 */ 1591 JsonContext json(); 1592 1593 /** 1594 * Return a ScriptRunner for running SQL or DDL scripts. 1595 * <p/> 1596 * Intended to use mostly in testing to run seed SQL scripts or truncate table scripts etc. 1597 */ 1598 ScriptRunner script(); 1599 1600 /** 1601 * Return the Document store. 1602 */ 1603 DocumentStore docStore(); 1604 1605 /** 1606 * Publish a single bean given its type and id returning the resulting live bean. 1607 * <p> 1608 * The values are published from the draft to the live bean. 1609 * </p> 1610 * 1611 * @param <T> the type of the entity bean 1612 * @param beanType the type of the entity bean 1613 * @param id the id of the entity bean 1614 * @param transaction the transaction the publish process should use (can be null) 1615 */ 1616 @Nullable 1617 <T> T publish(Class<T> beanType, Object id, Transaction transaction); 1618 1619 /** 1620 * Publish a single bean given its type and id returning the resulting live bean. 1621 * This will use the current transaction or create one if required. 1622 * <p> 1623 * The values are published from the draft to the live bean. 1624 * </p> 1625 * 1626 * @param <T> the type of the entity bean 1627 * @param beanType the type of the entity bean 1628 * @param id the id of the entity bean 1629 */ 1630 @Nullable 1631 <T> T publish(Class<T> beanType, Object id); 1632 1633 /** 1634 * Publish the beans that match the query returning the resulting published beans. 1635 * <p> 1636 * The values are published from the draft beans to the live beans. 1637 * </p> 1638 * 1639 * @param <T> the type of the entity bean 1640 * @param query the query used to select the draft beans to publish 1641 * @param transaction the transaction the publish process should use (can be null) 1642 */ 1643 <T> List<T> publish(Query<T> query, Transaction transaction); 1644 1645 /** 1646 * Publish the beans that match the query returning the resulting published beans. 1647 * This will use the current transaction or create one if required. 1648 * <p> 1649 * The values are published from the draft beans to the live beans. 1650 * </p> 1651 * 1652 * @param <T> the type of the entity bean 1653 * @param query the query used to select the draft beans to publish 1654 */ 1655 <T> List<T> publish(Query<T> query); 1656 1657 /** 1658 * Restore the draft bean back to the live state. 1659 * <p> 1660 * The values from the live beans are set back to the draft bean and the 1661 * <code>@DraftDirty</code> and <code>@DraftReset</code> properties are reset. 1662 * </p> 1663 * 1664 * @param <T> the type of the entity bean 1665 * @param beanType the type of the entity bean 1666 * @param id the id of the entity bean to restore 1667 * @param transaction the transaction the restore process should use (can be null) 1668 */ 1669 @Nullable 1670 <T> T draftRestore(Class<T> beanType, Object id, Transaction transaction); 1671 1672 /** 1673 * Restore the draft bean back to the live state. 1674 * <p> 1675 * The values from the live beans are set back to the draft bean and the 1676 * <code>@DraftDirty</code> and <code>@DraftReset</code> properties are reset. 1677 * </p> 1678 * 1679 * @param <T> the type of the entity bean 1680 * @param beanType the type of the entity bean 1681 * @param id the id of the entity bean to restore 1682 */ 1683 @Nullable 1684 <T> T draftRestore(Class<T> beanType, Object id); 1685 1686 /** 1687 * Restore the draft beans matching the query back to the live state. 1688 * <p> 1689 * The values from the live beans are set back to the draft bean and the 1690 * <code>@DraftDirty</code> and <code>@DraftReset</code> properties are reset. 1691 * </p> 1692 * 1693 * @param <T> the type of the entity bean 1694 * @param query the query used to select the draft beans to restore 1695 * @param transaction the transaction the restore process should use (can be null) 1696 */ 1697 <T> List<T> draftRestore(Query<T> query, Transaction transaction); 1698 1699 /** 1700 * Restore the draft beans matching the query back to the live state. 1701 * <p> 1702 * The values from the live beans are set back to the draft bean and the 1703 * <code>@DraftDirty</code> and <code>@DraftReset</code> properties are reset. 1704 * </p> 1705 * 1706 * @param <T> the type of the entity bean 1707 * @param query the query used to select the draft beans to restore 1708 */ 1709 <T> List<T> draftRestore(Query<T> query); 1710 1711 /** 1712 * Returns the set of properties/paths that are unknown (do not map to known properties or paths). 1713 * <p> 1714 * Validate the query checking the where and orderBy expression paths to confirm if 1715 * they represent valid properties/path for the given bean type. 1716 * </p> 1717 */ 1718 <T> Set<String> validateQuery(Query<T> query); 1719 1720 /** 1721 * Load and lock the bean using {@code select for update}. 1722 * <p> 1723 * This should be executed inside a transaction and results in the bean being loaded or 1724 * refreshed from the database and a database row lock held via {@code select for update}. 1725 * <p> 1726 * The bean needs to have an ID property set and can be a reference bean (only has ID) 1727 * or partially or fully populated bean. This will load all the properties of the bean 1728 * from the database using {@code select for update} obtaining a database row lock (using WAIT). 1729 * 1730 * @param bean The entity bean that we wish to obtain a database lock on. 1731 */ 1732 void lock(Object bean); 1733 1734 /** 1735 * Truncate all the given tables. 1736 */ 1737 void truncate(String... tables); 1738 1739 /** 1740 * Truncate the base tables for the given bean types. 1741 */ 1742 void truncate(Class<?>... tables); 1743 1744}