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