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