Axelor Doc

Methods "finder"

For simple searches the syntax described below is generally satisfactory:

Contact c = Contact.all().filter("self.email = ?1", ...).fetchOne();
// or
List<Contact> all = Contact.all().filter("self.title.code = ?1", "mr").fetch();

Methods "Finder" allow you to use a more concise syntax. What are static Java methods generated on the entity.

Use

XML definition of a method "Finder"
<entity name="Contact">
    <string name="email" required="true" unique="true"/>
    ...
    <finder-method name="findByEmail" using="email" />
    ...
</entity>

The static method below is generated in the class Contact .

Method "Finder" generated the following XML definition above
public class Contact {
    ...
    public static Contact findByEmail(String email) {
        return Contact.all()
        .filter("self.email = :email")
        .bind("email", email)
        .fetchOne();
    }
}

And this method can be used as follows:

Contact c = Contact.findByEmail("[email protected]");

Using Advanced

Defining multiple "Finder"
<entity name="Order">
    ...
    <many-to-one name="customer" ref="Customer" required="true"/>
    <date name="createDate" required="true" />
    <decimal name="totalAmount" />
    ...
    <finder-method name="findByCustomer" using="long:id" filter="self.customer.id = :id" all="true" />

    <finder-method name="findByCustomer" using="String:email" filter="self.customer.email = :email" all="true" />

    <finder-method name="findByCustomerInMonthOf" using="long:id, LocalDate:date" filter="self.customer.id = :id AND MONTH(self.createDate) = MONTH(:date)" all="true"/>

    <finder-method name="findByCustomerName" using="String:firstName, String:lastName" filter="self.customer.firstName = :firstName AND self.customer.lastName = :lastName" all="true" />
</entity>

Static methods below are generated in the class Order .

Methods "Finder" generated
public static Query<Order> findByCustomer(long id) {
    return Order.all()
    .filter("self.customer.id = :id")
    .bind("id", id);
}

public static Query<Order> findByCustomer(String email) {
    return Order.all()
    .filter("self.customer.email = :email")
    .bind("email", email);
}

public static Query<Order> findByCustomerInMonthOf(long id, LocalDate date) {
    return Order.all()
    .filter("self.customer.id = :id AND MONTH(self.createDate) = MONTH(:date)")
    .bind("id", id)
    .bind("date", date);
}

public static Query<Order> findByCustomerName(String firstName, String lastName) {
    return Order.all()
    .filter("self.customer.firstName = :firstName AND self.customer.lastName = :lastName")
    .bind("firstName", firstName)
    .bind("lastName", lastName);
}

And here are some examples:

// find first 100 orders of the customer found by the given email in current month
List<Order> all = Order.findByCustomerInMonthOf(Customer.findByEmail(...), new LocalDate()).fetch(100);

The advantage of this syntax and conciseness over filters clear.

Attributes of a method "Finder"

  • name - the name of the method, by convention use the prefix: findBy
  • using - the list of parameters (separated by commas), (see below)
  • filter - the expression defining the filter. Only named parameters are allowed.
  • orderBy - list of columns to use to order the answer in a phrase like: orderBy = "name, -dateOfBirth"
  • all - default one record is returned. This attribute is used to return so paged all matching records.

The syntax used to define the attribute using :

[type:]<name>[, [<type>:]<name>]*

The arguments are defined either by their name as used in the definition of the entity, or by specifying the type and name of the parameter.

If the type of the parameter is specified, then an attribute filter must also be provided. Otherwise, if all provided names are names used in the definition of the entity, the attribute filter is optional and a method is generated using the filter AND with all the fields provided.

A few examples:

using="long:id, createDate"
using="code, name"
using="LocalDate:date, BigDecimal:amount"

Methods findByCode and FindByName are automatically generated for any entity which has fields named code and name and having no finder-method .