c);
@@ -1153,8 +1697,40 @@ public interface EbeanServer {
/**
* Return the JsonContext for reading/writing JSON.
*
- * This instance is safe to be used concurrently by multiple threads and this method is cheap to call.
+ * This instance is safe to be used concurrently by multiple threads and this
+ * method is cheap to call.
*
+ *
+ * Simple example:
+ * {@code
+ *
+ * JsonContext json = ebeanServer.json();
+ * String jsonOutput = json.toJson(list);
+ * System.out.println(jsonOutput);
+ *
+ * }
+ *
+ * Using PathProperties:
+ * {@code
+ *
+ * // specify just the properties we want
+ * PathProperties paths = PathProperties.parse("name, status, anniversary");
+ *
+ * List customers =
+ * ebeanServer.find(Customer.class)
+ * // apply those paths to the query (only fetch what we need)
+ * .apply(paths)
+ * .where().ilike("name", "rob%")
+ * .findList();
+ *
+ * // ... get the json
+ * JsonContext jsonContext = ebeanServer.json();
+ * String json = jsonContext.toJson(customers, paths);
+ *
+ * }
+ *
+ * @see com.avaje.ebean.text.PathProperties
+ * @see Query#apply(com.avaje.ebean.text.PathProperties)
*/
public JsonContext json();
diff --git a/src/main/java/com/avaje/ebean/Model.java b/src/main/java/com/avaje/ebean/Model.java
index 73e291a4f..a09a98cf1 100644
--- a/src/main/java/com/avaje/ebean/Model.java
+++ b/src/main/java/com/avaje/ebean/Model.java
@@ -24,11 +24,94 @@ import javax.persistence.MappedSuperclass;
*
* You may choose not use this Model mapped superclass if you don't like the 'Active Record' style
* or if you believe it 'pollutes' your entity beans.
- *
+ *
+ *
+ * You can use Dependency Injection like Guice or Spring to construct and wire a EbeanServer instance
+ * and have that same instance used with this Model and Finder. The way that works is that when the
+ * DI container creates the EbeanServer instance it can be registered with the Ebean singleton. In this
+ * way the EbeanServer instance can be injected as per normal Guice / Spring dependency injection and
+ * that same instance also used to support the Model and Finder active record style.
+ *
*
* If you choose to use the Model mapped superclass you will probably also chose to additionally add
* a {@link Finder} as a public static field to complete the active record pattern and provide a
* relatively nice clean way to write queries.
+ *
+ *
Typical common @MappedSuperclass
+ * {@code
+ *
+ * // Typically there is a common base model that has some
+ * // common properties like the ones below
+ *
+ * @MappedSuperclass
+ * public class BaseModel extends Model {
+ *
+ * @Id Long id;
+ *
+ * @Version Long version;
+ *
+ * @CreatedTimestamp Timestamp whenCreated;
+ *
+ * @UpdatedTimestamp Timestamp whenUpdated;
+ *
+ * ...
+ *
+ * }
+ *
+ * Extend the Model
+ * {@code
+ *
+ * // Extend the mappedSuperclass
+ *
+ * @Entity @Table(name="oto_account")
+ * public class Account extends BaseModel {
+ *
+ * // add a static Finder
+ * // ... with Long being the type of our ID property ...
+ *
+ * public static final Finder find =
+ * new Finder(Long.class, Account.class);
+ *
+ * String name;
+ *
+ * @OneToOne(mappedBy = "account",optional = true)
+ * User user;
+ *
+ * ...
+ * }
+ *
+ * }
+ *
+ * Modal: save()
+ * {@code
+ *
+ * // Active record style ... save(), delete() etc
+ * Account account = new Account();
+ * account.setName("AC234");
+ *
+ * // save() method inherited from Model
+ * account.save();
+ *
+ * }
+ *
+ * Finder: find byId
+ * {@code
+ *
+ * // find byId
+ * Account account = Account.find.byId(42);
+ *
+ * }
+ *
+ * Finder: find where
+ * {@code
+ *
+ * // find where ...
+ * List accounts =
+ * Account.find
+ * .where().gt("startDate", lastMonth)
+ * .findList();
+ *
+ * }
*/
@MappedSuperclass
public abstract class Model {
@@ -105,7 +188,9 @@ public abstract class Model {
* customer.markAsDirty();
* customer.save();
*
- *
+ *
+ *
+ * @see EbeanServer#markAsDirty(Object)
*/
public void markAsDirty() {
db().markAsDirty(this);
@@ -117,6 +202,8 @@ public abstract class Model {
*
* Ebean will detect if this is a new bean or a previously fetched bean and perform either an
* insert or an update based on that.
+ *
+ * @see EbeanServer#save(Object)
*/
public void save() {
db().save(this);
@@ -124,6 +211,8 @@ public abstract class Model {
/**
* Update this entity.
+ *
+ * @see EbeanServer#update(Object)
*/
public void update() {
db().update(this);
@@ -131,6 +220,8 @@ public abstract class Model {
/**
* Insert this entity.
+ *
+ * @see EbeanServer#insert(Object)
*/
public void insert() {
db().insert(this);
@@ -138,6 +229,8 @@ public abstract class Model {
/**
* Delete this entity.
+ *
+ * @see EbeanServer#delete(Object)
*/
public void delete() {
db().delete(this);
@@ -166,6 +259,8 @@ public abstract class Model {
/**
* Refreshes this entity from the database.
+ *
+ * @see EbeanServer#refresh(Object)
*/
public void refresh() {
db().refresh(this);
@@ -250,6 +345,8 @@ public abstract class Model {
/**
* Delete a bean by Id.
+ *
+ * Equivalent to {@link EbeanServer#delete(Class, Object)}
*/
public void deleteById(I id) {
db().delete(type, id);
@@ -306,6 +403,8 @@ public abstract class Model {
/**
* Creates a query applying the path properties to set the select and fetch clauses.
+ *
+ * Equivalent to {@link Query#apply(com.avaje.ebean.text.PathProperties)}
*/
public Query apply(PathProperties pathProperties) {
return db().find(type).apply(pathProperties);
@@ -346,6 +445,8 @@ public abstract class Model {
/**
* Execute the query consuming each bean one at a time.
*
+ * Equivalent to {@link Query#findEachWhile(QueryEachWhileConsumer)}
+ *
* This is similar to #findEach except that you return boolean
* true to continue processing beans and return false to stop
* processing early.
diff --git a/src/main/java/com/avaje/ebean/Page.java b/src/main/java/com/avaje/ebean/Page.java
deleted file mode 100644
index 626e29dd9..000000000
--- a/src/main/java/com/avaje/ebean/Page.java
+++ /dev/null
@@ -1,74 +0,0 @@
-package com.avaje.ebean;
-
-import java.util.List;
-
-/**
- * Represents a Page of results that is part of a PagingList.
- *
- * Typically a Page represents the data that is shown to the user at a single
- * time - and the user 'pages' through a large list.
- *
- *
- * @author rbygrave
- *
- * @param
- * the entity bean type
- *
- * @see Query#findPagingList(int)
- * @see PagingList
- */
-public interface Page {
-
- /**
- * Return the list of entities for this page.
- */
- public List getList();
-
- /**
- * Return the total row count for all pages.
- */
- public int getTotalRowCount();
-
- /**
- * Return the total number of pages.
- */
- public int getTotalPageCount();
-
- /**
- * Return the index position of this page.
- */
- public int getPageIndex();
-
- /**
- * Return true if there is a next page.
- */
- public boolean hasNext();
-
- /**
- * Return true if there is a previous page.
- */
- public boolean hasPrev();
-
- /**
- * Return the next page.
- */
- public Page next();
-
- /**
- * Return the previous page.
- */
- public Page prev();
-
- /**
- * Helper method to return a "X to Y of Z" string for this page where X is the
- * first row, Y the last row and Z the total row count.
- *
- * @param to
- * String to put between the first and last row
- * @param of
- * String to put between the last row and the total row count
- *
- * @return String of the format XtoYofZ.
- */
- public String getDisplayXtoYofZ(String to, String of);
-}
diff --git a/src/main/java/com/avaje/ebean/Query.java b/src/main/java/com/avaje/ebean/Query.java
index f817fb67f..5ab23a0e9 100644
--- a/src/main/java/com/avaje/ebean/Query.java
+++ b/src/main/java/com/avaje/ebean/Query.java
@@ -13,54 +13,57 @@ import java.util.Set;
* Example: Create the query using the API.
*
*
- *
- * List<Order> orderList =
- * Ebean.find(Order.class)
- * .fetch("customer")
- * .fetch("details")
+ * {@code
+ *
+ * List orderList =
+ * ebeanServer.find(Order.class)
+ * .fetch("customer")
+ * .fetch("details")
* .where()
- * .like("customer.name","rob%")
- * .gt("orderDate",lastWeek)
- * .orderBy("customer.id, id desc")
+ * .like("customer.name","rob%")
+ * .gt("orderDate",lastWeek)
+ * .orderBy("customer.id, id desc")
* .setMaxRows(50)
* .findList();
*
* ...
- *
+ * }
*
*
* Example: The same query using the query language
*
*
- *
+ * {@code
+ *
* String oql =
- * " find order "
- * +" fetch customer "
- * +" fetch details "
- * +" where customer.name like :custName and orderDate > :minOrderDate "
- * +" order by customer.id, id desc "
- * +" limit 50 ";
+ * " find order "
+ * +" fetch customer "
+ * +" fetch details "
+ * +" where customer.name like :custName and orderDate > :minOrderDate "
+ * +" order by customer.id, id desc "
+ * +" limit 50 ";
*
- * Query<Order> query = Ebean.createQuery(Order.class, oql);
- * query.setParameter("custName", "Rob%");
- * query.setParameter("minOrderDate", lastWeek);
+ * Query query = ebeanServer.createQuery(Order.class, oql);
+ * query.setParameter("custName", "Rob%");
+ * query.setParameter("minOrderDate", lastWeek);
*
- * List<Order> orderList = query.findList();
+ * List orderList = query.findList();
* ...
- *
+ * }
*
*
* Example: Using a named query called "with.cust.and.details"
*
*
- *
- * Query<Order> query = Ebean.createNamedQuery(Order.class,"with.cust.and.details");
- * query.setParameter("custName", "Rob%");
- * query.setParameter("minOrderDate", lastWeek);
+ * {@code
+ *
+ * Query query = ebeanServer.createNamedQuery(Order.class,"with.cust.and.details");
+ * query.setParameter("custName", "Rob%");
+ * query.setParameter("minOrderDate", lastWeek);
*
- * List<Order> orderList = query.findList();
+ * List orderList = query.findList();
* ...
- *
+ * }
*
* Autofetch
*
@@ -98,13 +101,13 @@ import java.util.Set;
* Refer to "ALL Properties/Columns" mode of Optimistic Concurrency checking.
*
*
- *
+ * {@code
* [ find {bean type} [ ( * | {fetch properties} ) ] ]
* [ fetch {associated bean} [ ( * | {fetch properties} ) ] ]
* [ where {predicates} ]
* [ order by {order by properties} ]
* [ limit {max rows} [ offset {first row} ] ]
- *
+ * }
*
*
* FIND {bean type} [ ( * | {fetch properties} ) ]
@@ -160,17 +163,17 @@ import java.util.Set;
* Find orders fetching all its properties
*
*
- *
+ * {@code
* find order
- *
+ * }
*
*
* Find orders fetching all its properties
*
*
- *
+ * {@code
* find order (*)
- *
+ * }
*
*
* Find orders fetching its id, shipDate and status properties. Note that the id
@@ -178,30 +181,30 @@ import java.util.Set;
* properties.
*
*
- *
+ * {@code
* find order (shipDate, status)
- *
+ * }
*
*
* Find orders with a named bind variable (that will need to be bound via
* {@link Query#setParameter(String, Object)}).
*
*
- *
+ * {@code
* find order
* where customer.name like :custLike
- *
+ * }
*
*
* Find orders and also fetch the customer with a named bind parameter. This
* will fetch and populate both the order and customer objects.
*
*
- *
+ * {@code
* find order
* fetch customer
* where customer.id = :custId
- *
+ * }
*
*
* Find orders and also fetch the customer, customer shippingAddress, order
@@ -212,13 +215,13 @@ import java.util.Set;
* populated.
*
*
- *
+ * {@code
* find order
* fetch customer (name)
* fetch customer.shippingAddress
* fetch details
* fetch details.product (sku, name)
- *
+ * }
*
* Early parsing of the Query
*
@@ -352,19 +355,24 @@ public interface Query extends Serializable {
/**
* Explicitly set a comma delimited list of the properties to fetch on the
- * 'main' entity bean (aka partial object). Note that '*' means all
+ * 'main' root level entity bean (aka partial object). Note that '*' means all
* properties.
+ *
+ * You use {@link #fetch(String, String)} to specify specific properties to fetch
+ * on other non-root level paths of the object graph.
+ *
*
- *
- * Query<Customer> query = Ebean.createQuery(Customer.class);
+ * {@code
*
- * // Only fetch the customer id, name and status.
- * // This is described as a "Partial Object"
- * query.select("name, status");
- * query.where("lower(name) like :custname").setParameter("custname", "rob%");
+ * List customers =
+ * ebeanServer.find(Customer.class)
+ * // Only fetch the customer id, name and status.
+ * // This is described as a "Partial Object"
+ * .select("name, status")
+ * .where.ilike("name", "rob%")
+ * .findList();
*
- * List<Customer> customerList = query.findList();
- *
+ * }
*
* @param fetchProperties
* the properties to fetch for this bean (* = all properties).
@@ -383,31 +391,35 @@ public interface Query extends Serializable {
* "Partial Object" - a bean that only has some of its properties populated.
*
*
- *
+ * {@code
+ *
* // query orders...
- * Query<Order> query = Ebean.createQuery(Order.class);
+ * List orders =
+ * ebeanserver.find(Order.class)
+ * // fetch the customer...
+ * // ... getting the customers name and phone number
+ * .fetch("customer", "name, phoneNumber")
*
- * // fetch the customer...
- * // ... getting the customer's name and phone number
- * query.fetch("customer", "name, phNumber");
- *
- * // ... also fetch the customers billing address (* = all properties)
- * query.fetch("customer.billingAddress", "*");
- *
+ * // ... also fetch the customers billing address (* = all properties)
+ * .fetch("customer.billingAddress", "*")
+ * .findList();
+ * }
*
*
* If columns is null or "*" then all columns/properties for that path are
* fetched.
*
*
- *
+ * {@code
+ *
* // fetch customers (their id, name and status)
- * Query<Customer> query = Ebean.createQuery(Customer.class);
- *
- * // only fetch some of the properties of the customers
- * query.select("name, status");
- * List<Customer> list = query.findList();
- *
+ * List customers =
+ * ebeanServer.find(Customer.class)
+ * .select("name, status")
+ * .fetch("contacts", "firstName,lastName,email")
+ * .findList();
+ *
+ * }
*
* @param path
* the path of an associated (1-1,1-M,M-1,M-M) bean.
@@ -420,6 +432,17 @@ public interface Query extends Serializable {
/**
* Additionally specify a FetchConfig to use a separate query or lazy loading
* to load this path.
+ *
+ * {@code
+ *
+ * // fetch customers (their id, name and status)
+ * List customers =
+ * ebeanServer.find(Customer.class)
+ * .select("name, status")
+ * .fetch("contacts", "firstName,lastName,email", new FetchConfig().lazy(10))
+ * .findList();
+ *
+ * }
*/
public Query fetch(String assocProperty, String fetchProperties, FetchConfig fetchConfig);
@@ -428,7 +451,17 @@ public interface Query extends Serializable {
*
* The same as {@link #fetch(String, String)} with the fetchProperties as "*".
*
- *
+ * {@code
+ *
+ * // fetch customers (their id, name and status)
+ * List customers =
+ * ebeanServer.find(Customer.class)
+ * // eager fetch the contacts
+ * .fetch("contacts")
+ * .findList();
+ *
+ * }
+ *
* @param path
* the property of an associated (1-1,1-M,M-1,M-M) bean.
*/
@@ -437,6 +470,18 @@ public interface Query extends Serializable {
/**
* Additionally specify a JoinConfig to specify a "query join" and or define
* the lazy loading query.
+ *
+ *
+ * {@code
+ *
+ * // fetch customers (their id, name and status)
+ * List customers =
+ * ebeanServer.find(Customer.class)
+ * // lazy fetch contacts with a batch size of 100
+ * .fetch("contacts", new FetchConfig().lazy(100))
+ * .findList();
+ *
+ * }
*/
public Query fetch(String path, FetchConfig joinConfig);
@@ -466,6 +511,10 @@ public interface Query extends Serializable {
* (typically in a finally block).
*
*
+ * findEach() and findEachWhile() are preferred to findIterate() as they ensure
+ * the jdbc statement and resultSet are closed at the end of the iteration.
+ *
+ *
* This query will execute against the EbeanServer that was used to create it.
*
*/
@@ -493,6 +542,12 @@ public interface Query extends Serializable {
* (unlike #findList #findSet etc)
*
*
+ * Note that internally Ebean can inform the JDBC driver that it is expecting larger
+ * resultSet and specifically for MySQL this hint is required to stop it's JDBC driver
+ * from buffering the entire resultSet. As such, for smaller resultSets findList() is
+ * generally preferable.
+ *
+ *
* Compared with #findEachWhile this will always process all the beans where as
* #findEachWhile provides a way to stop processing the query result early before
* all the beans have been read.
@@ -503,19 +558,18 @@ public interface Query extends Serializable {
* with Java8 closures.
*
*
- *
+ * {@code
*
- * Query<Customer> query = server.find(Customer.class)
- * .where().gt("id", 0)
- * .orderBy("id")
- * .setMaxRows(2);
+ * ebeanServer.find(Customer.class)
+ * .where().eq("status", Status.NEW)
+ * .order().asc("id")
+ * .findEach((Customer customer) -> {
*
- * query.findVisit((Customer customer) -> {
+ * // do something with customer
+ * System.out.println("-- visit " + customer);
+ * });
*
- * // do something with customer
- * System.out.println("-- visit " + customer);
- * });
- *
+ * }
*
* @param consumer
* the consumer used to process the queried beans.
@@ -532,23 +586,23 @@ public interface Query extends Serializable {
*
*
- *
+ * {@code
*
- * Query<Customer> query = server.find(Customer.class)
- * .fetch("contacts", new FetchConfig().query(2))
- * .where().gt("id", 0)
- * .orderBy("id")
- * .setMaxRows(2);
+ * ebeanServer.find(Customer.class)
+ * .fetch("contacts", new FetchConfig().query(2))
+ * .where().eq("status", Status.NEW)
+ * .order().asc("id")
+ * .setMaxRows(2000)
+ * .findEachWhile((Customer customer) -> {
*
- * query.findEachWhile((Customer customer) -> {
+ * // do something with customer
+ * System.out.println("-- visit " + customer);
*
- * // do something with customer
- * System.out.println("-- visit " + customer);
+ * // return true to continue processing or false to stop
+ * return (customer.getId() < 40);
+ * });
*
- * // return true to continue processing or false to stop
- * return (customer.getId() < 40);
- * });
- *
+ * }
*
* @param consumer
* the consumer used to process the queried beans.
@@ -560,7 +614,16 @@ public interface Query extends Serializable {
*
* This query will execute against the EbeanServer that was used to create it.
*
- *
+ *
+ * {@code
+ *
+ * List customers =
+ * ebeanServer.find(Customer.class)
+ * .where().ilike("name", "rob%")
+ * .findList();
+ *
+ * }
+ *
* @see EbeanServer#findList(Query, Transaction)
*/
public List findList();
@@ -570,7 +633,16 @@ public interface Query extends Serializable {
*
* This query will execute against the EbeanServer that was used to create it.
*
- *
+ *
+ * {@code
+ *
+ * Set customers =
+ * ebeanServer.find(Customer.class)
+ * .where().ilike("name", "rob%")
+ * .findSet();
+ *
+ * }
+ *
* @see EbeanServer#findSet(Query, Transaction)
*/
public Set findSet();
@@ -585,11 +657,14 @@ public interface Query extends Serializable {
* on the map. If one is not specified then the id property is used.
*
*
- *
- * Query<Product> query = Ebean.createQuery(Product.class);
- * query.setMapKey("sku");
- * Map<?, Product> map = query.findMap();
- *
+ * {@code
+ *
+ * Map, Product> map =
+ * ebeanServer.find(Product.class)
+ * .setMapKey("sku")
+ * .findMap();
+ *
+ * }
*
* @see EbeanServer#findMap(Query, Transaction)
*/
@@ -612,32 +687,34 @@ public interface Query extends Serializable {
* return 0 or 1 results.
*
*
- *
+ * {@code
+ *
* // assuming the sku of products is unique...
* Product product =
- * Ebean.find(Product.class)
- * .where("sku = ?")
- * .set(1, "aa113")
+ * ebeanServer.find(Product.class)
+ * .where().eq("sku", "aa113")
* .findUnique();
* ...
- *
+ * }
*
*
* It is also useful with finding objects by their id when you want to specify
* further join information.
*
*
- *
+ * {@code
+ *
* // Fetch order 1 and additionally fetch join its order details...
* Order order =
- * Ebean.find(Order.class)
+ * ebeanServer.find(Order.class)
* .setId(1)
- * .fetch("details")
+ * .fetch("details")
* .findUnique();
- *
- * List<OrderDetail> details = order.getDetails();
+ *
+ * // the order details were eagerly loaded
+ * List details = order.getDetails();
* ...
- *
+ * }
*/
public T findUnique();
@@ -696,7 +773,32 @@ public interface Query extends Serializable {
* the query. This translates into SQL that uses limit offset, rownum or row_number function to
* limit the result set.
*
- *
+ *
+ * Example: typical use including total row count
+ * {@code
+ *
+ * // We want to find the first 100 new orders
+ * // ... 0 means first page
+ * // ... page size is 100
+ *
+ * PagedList pagedList
+ * = ebeanServer.find(Order.class)
+ * .where().eq("status", Order.Status.NEW)
+ * .order().asc("id")
+ * .findPagedList(0, 100);
+ *
+ * // Optional: initiate the loading of the total
+ * // row count in a background thread
+ * pagedList.loadRowCount();
+ *
+ * // fetch and return the list in the foreground thread
+ * List orders = pagedList.getList();
+ *
+ * // get the total row count (from the future)
+ * int totalRowCount = pagedList.getTotalRowCount();
+ *
+ * }
+ *
* @param pageIndex
* The zero based index of the page.
* @param pageSize
@@ -706,19 +808,20 @@ public interface Query extends Serializable {
public PagedList findPagedList(int pageIndex, int pageSize);
/**
- * Set a named bind parameter. Named parameters have a colon to prefix the
- * name.
+ * Set a named bind parameter. Named parameters have a colon to prefix the name.
*
- *
+ * {@code
+ *
* // a query with a named parameter
- * String oql = "find order where status = :orderStatus";
+ * String oql = "find order where status = :orderStatus";
*
- * Query<Order> query = Ebean.createQuery(Order.class, oql);
+ * Query query = ebeanServer.find(Order.class, oql);
*
* // bind the named parameter
- * query.bind("orderStatus", OrderStatus.NEW);
- * List<Order> list = query.findList();
- *
+ * query.bind("orderStatus", OrderStatus.NEW);
+ * List list = query.findList();
+ *
+ * }
*
* @param name
* the parameter name
@@ -732,17 +835,19 @@ public interface Query extends Serializable {
* position starts at 1 to be consistent with JDBC PreparedStatement. You need
* to set a parameter value for each ? you have in the query.
*
- *
+ * {@code
+ *
* // a query with a positioned parameter
- * String oql = "where status = ? order by id desc";
+ * String oql = "where status = ? order by id desc";
*
- * Query<Order> query = Ebean.createQuery(Order.class, oql);
+ * Query query = ebeanServer.createQuery(Order.class, oql);
*
* // bind the parameter
* query.setParameter(1, OrderStatus.NEW);
*
- * List<Order> list = query.findList();
- *
+ * List list = query.findList();
+ *
+ * }
*
* @param position
* the parameter bind position starting from 1 (not 0)
@@ -758,12 +863,18 @@ public interface Query extends Serializable {
* fetch joins.
*
*
- *
- * Query<Order> query = Ebean.createQuery(Order.class);
- * Order order = query.setId(1).join("details").findUnique();
- * List<OrderDetail> details = order.getDetails();
- * ...
- *
+ * {@code
+ *
+ * Order order =
+ * ebeanServer.find(Order.class)
+ * .setId(1)
+ * .fetch("details")
+ * .findUnique();
+ *
+ * // the order details were eagerly fetched
+ * List details = order.getDetails();
+ *
+ * }
*/
public Query setId(Object id);
@@ -774,15 +885,17 @@ public interface Query extends Serializable {
* {@link #setParameter(String, Object)}.
*
*
- *
- * Query<Order> query = Ebean.createQuery(Order.class, "top");
+ * {@code
+ *
+ * Query query = ebeanServer.createQuery(Order.class, "top");
* ...
* if (...) {
- * query.where("status = :status and lower(customer.name) like :custName");
- * query.setParameter("status", Order.NEW);
- * query.setParameter("custName", "rob%");
+ * query.where("status = :status and lower(customer.name) like :custName");
+ * query.setParameter("status", Order.NEW);
+ * query.setParameter("custName", "rob%");
* }
- *
+ *
+ * }
*
*
* Internally the addToWhereClause string is processed by removing named
@@ -802,13 +915,15 @@ public interface Query extends Serializable {
/**
* Add a single Expression to the where clause returning the query.
*
- *
- * List<Order> newOrders =
- * Ebean.find(Order.class)
- * .where().eq("status", Order.NEW)
+ * {@code
+ *
+ * List newOrders =
+ * ebeanServer.find(Order.class)
+ * .where().eq("status", Order.NEW)
* .findList();
* ...
- *
+ *
+ * }
*/
public Query where(Expression expression);
@@ -817,15 +932,16 @@ public interface Query extends Serializable {
* ExpressionList. You can use this for adding multiple expressions to the
* where clause.
*
- *
- * Query<Order> query = Ebean.createQuery(Order.class, "top");
- * ...
- * if (...) {
- * query.where()
- * .eq("status", Order.NEW)
- * .ilike("customer.name","rob%");
- * }
- *
+ * {@code
+ *
+ * List orders =
+ * ebeanServer.find(Order.class)
+ * .where()
+ * .eq("status", Order.NEW)
+ * .ilike("customer.name","rob%")
+ * .findList();
+ *
+ * }
*
* @see Expr
* @return The ExpressionList for adding expressions to.
@@ -843,17 +959,18 @@ public interface Query extends Serializable {
* week. In this case you can use filterMany() to filter the orders.
*
*
- *
+ * {@code
*
- * List<Customer> list = Ebean
- * .find(Customer.class)
- * // .fetch("orders", new FetchConfig().lazy())
- * // .fetch("orders", new FetchConfig().query())
- * .fetch("orders").where().ilike("name", "rob%").filterMany("orders")
- * .eq("status", Order.Status.NEW).gt(
- * "orderDate", lastWeek).findList();
+ * List list =
+ * ebeanServer.find(Customer.class)
+ * // .fetch("orders", new FetchConfig().lazy())
+ * // .fetch("orders", new FetchConfig().query())
+ * .fetch("orders")
+ * .where().ilike("name", "rob%")
+ * .filterMany("orders").eq("status", Order.Status.NEW).gt("orderDate", lastWeek)
+ * .findList();
*
- *
+ * }
*
*
* Please note you have to be careful that you add expressions to the correct
@@ -891,14 +1008,14 @@ public interface Query extends Serializable {
* {@link #setParameter(String, Object)}.
*
*
- *
- * Query<ReportOrder> query = Ebean.createQuery(ReportOrder.class);
- * ...
- * if (...) {
- * query.having("score > :min");
- * query.setParameter("min", 1);
- * }
- *
+ * {@code
+ *
+ * List query =
+ * ebeanServer.find(ReportOrder.class)
+ * .having("score > :min").setParameter("min", 1)
+ * .findList();
+ *
+ * }
*
* @param addToHavingClause
* the clause to append to the having clause which typically contains
@@ -1030,17 +1147,17 @@ public interface Query extends Serializable {
* If no property is set then the id property is used.
*
*
- *
+ * {@code
+ *
* // Assuming sku is unique for products...
*
- * Query<Product> query = Ebean.createQuery(Product.class);
- *
- * // use sku for keys...
- * query.setMapKey("sku");
- *
- * Map<?,Product> productMap = query.findMap();
- * ...
- *
+ * Map,Product> productMap =
+ * ebeanServer.find(Product.class)
+ * // use sku for keys...
+ * .setMapKey("sku")
+ * .findMap();
+ *
+ * }
*
* @param mapKey
* the property to use as keys for a map.
diff --git a/src/main/java/com/avaje/ebean/QueryEachConsumer.java b/src/main/java/com/avaje/ebean/QueryEachConsumer.java
index 7e9761426..3d015456c 100644
--- a/src/main/java/com/avaje/ebean/QueryEachConsumer.java
+++ b/src/main/java/com/avaje/ebean/QueryEachConsumer.java
@@ -12,19 +12,19 @@ package com.avaje.ebean;
* QueryResultVisitor useful for processing large queries.
*
*
- *
+ * {@code
*
- * Query<Customer> query = server.find(Customer.class)
- * .where().gt("id", 0)
- * .orderBy("id")
- * .setMaxRows(2);
+ * Query query = server.find(Customer.class)
+ * .where().eq("status", Status.NEW)
+ * .order().asc("id");
*
- * query.findVisit((Customer customer) -> {
+ * query.findEach((Customer customer) -> {
*
* // do something with customer
- * System.out.println("-- visit " + customer);
+ * System.out.println("-- visit " + customer);
* });
- *
+ *
+ * }
*
* @param
* the type of entity bean being queried.
diff --git a/src/main/java/com/avaje/ebean/annotation/Formula.java b/src/main/java/com/avaje/ebean/annotation/Formula.java
index f33ca8e34..915cf0deb 100644
--- a/src/main/java/com/avaje/ebean/annotation/Formula.java
+++ b/src/main/java/com/avaje/ebean/annotation/Formula.java
@@ -20,7 +20,7 @@ import com.avaje.ebean.Query;
* You may also put use the Transient annotation with the Formula annotation.
* The effect of the Transient annotation in this case is that the formula will
* NOT be included in queries by default - you have to explicitly include
- * it via {@link Query#select(String)} or {@link Query#join(String, String)}.
+ * it via {@link Query#select(String)} or {@link Query#fetch(String, String, com.avaje.ebean.FetchConfig)}.
* You may want to do this if the Formula is relatively expensive and only want
* it included in the query when you explicitly state it.
*
diff --git a/src/main/java/com/avaje/ebean/event/BeanPersistListener.java b/src/main/java/com/avaje/ebean/event/BeanPersistListener.java
index 9b453f6dd..50b3c098f 100644
--- a/src/main/java/com/avaje/ebean/event/BeanPersistListener.java
+++ b/src/main/java/com/avaje/ebean/event/BeanPersistListener.java
@@ -33,7 +33,7 @@ import com.avaje.ebean.config.ServerConfig;
*
*
* A BeanPersistListener is either found automatically via class path search or
- * can be added programmatically via {@link ServerConfig#add(BeanPersistListener>)}}.
+ * can be added programmatically via {@link ServerConfig#add(BeanPersistListener)}}.
*
* @see ServerConfig#add(BeanPersistListener)
*/
diff --git a/src/main/java/com/avaje/ebean/overview.html b/src/main/java/com/avaje/ebean/overview.html
index 85d597896..4ce74e843 100644
--- a/src/main/java/com/avaje/ebean/overview.html
+++ b/src/main/java/com/avaje/ebean/overview.html
@@ -3,8 +3,8 @@
Ebean API
-Ebean Object Relational Mapping (start at Ebean
-or EbeanServer).
+Ebean Object Relational Mapping (start at
+EbeanServer or Ebean).
Ebean
@@ -21,15 +21,15 @@ For a full description of the query language refer to
+{@code
// fetch order 10
Order order = Ebean.find(Order.class, 10);
-
+}
EXAMPLE 2: Fetch an Object with associations
-
+{@code
// fetch Customer 7 including their billing and shipping addresses
Customer customer = Ebean.find(Customer.class)
.fetch("billingAddress");
@@ -40,19 +40,19 @@ Customer customer = Ebean.find(Customer.class)
Address billAddr = customer.getBillingAddress();
Address shipAddr = customer.getShippingAddress();
-
+}
EXAMPLE 3: Fetch a list of Objects with associations
-
+{@code
// Note: This example shows a "Partial Object".
// For the product objects associated with the
// order details only the product id and name is
// fetched (the product objects are partially populated).
// fetch orders for customer.id = 2
-List<Order> orderList = Ebean.find(Order.class);
+List orderList = Ebean.find(Order.class);
.fetch("customer")
.fetch("customer.shippingAddress")
.fetch("details")
@@ -72,17 +72,17 @@ Order order = orderList.get(0);
Customer customer = order.getCustomer();
Address shipAddr = customer.getShippingAddress();
-List<OrderDetail> details = order.getDetails();
+List details = order.getDetails();
OrderDetail detail = details.get(0);
Product product = detail.getProduct();
String productName = product.getName();
-
+}
EXAMPLE 4: Create and save an Order
-
+{@code
// get a Customer reference so we don't hit the database
Customer custRef = Ebean.getReference(Customer.class, 7);
@@ -107,14 +107,14 @@ orderLines.add(line);
// NB: assumes CascadeType.PERSIST is set on the order lines association
Ebean.save(newOrder);
-
+}
EXAMPLE 5: Use another database
-
+{@code
// Get access to the Human Resources EbeanServer/Database
-EbeanServer hrServer = Ebean.getServer("HR");
+EbeanServer hrServer = Ebean.getServer("HR");
// fetch contact 3 from the HR database
@@ -125,7 +125,7 @@ contact.setStatus(Contact.Status.INACTIVE);
// save the contact back to the HR database
hrServer.save(contact);
-
+}
diff --git a/src/main/java/com/avaje/ebeaninternal/server/text/json/WriteJson.java b/src/main/java/com/avaje/ebeaninternal/server/text/json/WriteJson.java
index 8b1336bcf..3c3dc9914 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/text/json/WriteJson.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/text/json/WriteJson.java
@@ -73,7 +73,7 @@ public class WriteJson {
return new WriteBean(desc, explicitAllProps, currentIncludeProps, bean);
}
- public class WriteBean {
+ public static class WriteBean {
final boolean explicitAllProps;
final Set currentIncludeProps;
diff --git a/src/test/java/com/avaje/ebean/elasticsearch/TestBasicPush.java b/src/test/java/com/avaje/ebean/elasticsearch/TestBasicPush.java
index 97efdb90b..fff74ba0b 100644
--- a/src/test/java/com/avaje/ebean/elasticsearch/TestBasicPush.java
+++ b/src/test/java/com/avaje/ebean/elasticsearch/TestBasicPush.java
@@ -1,7 +1,118 @@
package com.avaje.ebean.elasticsearch;
-/**
- * Created by rob on 2/12/14.
- */
-public class TestBasicPush {
+import com.avaje.ebean.BaseTestCase;
+import com.avaje.ebean.Ebean;
+import com.avaje.ebean.EbeanServer;
+import com.avaje.ebean.text.PathProperties;
+import com.avaje.ebean.text.json.JsonContext;
+import com.avaje.tests.model.basic.Customer;
+import com.avaje.tests.model.basic.ResetBasicData;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.squareup.okhttp.*;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.List;
+
+public class TestBasicPush extends BaseTestCase {
+
+ public static final MediaType JSON
+ = MediaType.parse("application/json; charset=utf-8");
+
+ OkHttpClient client = new OkHttpClient();
+
+ @Ignore
+ @Test
+ public void testBulkUpdate() throws IOException {
+
+ ResetBasicData.reset();
+
+ EbeanServer server = Ebean.getServer(null);
+ JsonContext jsonContext = server.json();
+
+ StringWriter writer = new StringWriter();
+ JsonGenerator generator = jsonContext.createGenerator(writer);
+
+ List customers = Ebean.find(Customer.class).findList();
+
+ for (Customer customer : customers) {
+
+ customer.setName(customer.getName()+"esMod");
+ PathProperties updateProps = PathProperties.parse("name");
+
+ generator.writeStartObject();
+ generator.writeFieldName("update");
+ generator.writeStartObject();
+ generator.writeStringField("_id", customer.getId().toString());
+ generator.writeStringField("_type", "customer");
+ generator.writeStringField("_index", "customer");
+ generator.writeEndObject();
+ generator.writeEndObject();
+ generator.writeRaw("\n");
+
+ generator.writeStartObject();
+ generator.writeFieldName("doc");
+ jsonContext.toJson(customer, generator, updateProps);
+ generator.writeEndObject();
+ generator.writeRaw("\n");
+ }
+
+ generator.close();
+ String json = writer.toString();
+ System.out.println(json);
+
+ String response = post("http://localhost:9200/_bulk", json);
+
+ System.out.println(response);
+
+ //curl -s -XPOST localhost:9200/_bulk
+
+// { "update" : {"_id" : "1", "_type" : "type1", "_index" : "index1"} }
+// { "doc" : {"field2" : "value2"} }
+
+
+ }
+
+ @Ignore
+ @Test
+ public void test() throws IOException {
+
+ ResetBasicData.reset();
+
+ EbeanServer server = Ebean.getServer(null);
+ JsonContext jsonContext = server.json();
+
+ List customers = Ebean.find(Customer.class).findList();
+
+ PathProperties paths = PathProperties.parse("name, status, anniversary");
+ for (Customer customer : customers) {
+
+ String json = jsonContext.toJson(customer, paths);
+ put("http://localhost:9200/customer/customer/"+customer.getId(), json);
+ }
+
+ }
+
+ String post(String url, String json) throws IOException {
+ RequestBody body = RequestBody.create(JSON, json);
+ Request request = new Request.Builder()
+ .url(url)
+ .put(body)
+ .build();
+ Response response = client.newCall(request).execute();
+ return response.body().string();
+ }
+
+ String put(String url, String json) throws IOException {
+ RequestBody body = RequestBody.create(JSON, json);
+ Request request = new Request.Builder()
+ .url(url)
+ .put(body)
+ .build();
+ Response response = client.newCall(request).execute();
+ return response.body().string();
+ }
+
}