001package io.ebean; 002 003import io.avaje.lang.NonNullApi; 004import io.avaje.lang.Nullable; 005import java.util.List; 006 007/** 008 * Intended to be used as a base class for 'Finder' implementations that can then 009 * be injected or used as public static fields on the associated entity bean. 010 * <p> 011 * These 'finders' are a place to organise all the finder methods for that bean type 012 * and specific finder methods are expected to be added (find by unique properties etc). 013 * </p> 014 * <h3>Testing</h3> 015 * <p> 016 * For testing the mocki-ebean project has the ability to replace the finder implementation. 017 * </p> 018 * <pre>{@code 019 * 020 * public class CustomerFinder extends Finder<Long,Customer> { 021 * 022 * public CustomerFinder() { 023 * super(Customer.class); 024 * } 025 * 026 * // Add finder methods ... 027 * 028 * public Customer byName(String name) { 029 * return query().eq("name", name).findOne(); 030 * } 031 * 032 * public List<Customer> findNew() { 033 * return query().where() 034 * .eq("status", Customer.Status.NEW) 035 * .order("name") 036 * .findList() 037 * } 038 * } 039 * 040 * @Entity 041 * public class Customer extends BaseModel { 042 * 043 * public static final CustomerFinder find = new CustomerFinder(); 044 * ... 045 * 046 * } 047 * }</pre> 048 * <p> 049 * When the Finder is registered as a field on Customer it can then be used like: 050 * </p> 051 * <pre>{@code 052 * 053 * Customer rob = Customer.find.byName("Rob"); 054 * 055 * }</pre> 056 * 057 */ 058@NonNullApi 059public class Finder<I, T> { 060 061 /** 062 * The entity bean type. 063 */ 064 private final Class<T> type; 065 066 /** 067 * The name of the database this finder will use, null for the default database. 068 */ 069 private final String _$dbName; 070 071 /** 072 * Create with the type of the entity bean. 073 * <pre>{@code 074 * 075 * public class CustomerFinder extends Finder<Customer> { 076 * 077 * public CustomerFinder() { 078 * super(Customer.class); 079 * } 080 * 081 * // ... add extra customer specific finder methods 082 * } 083 * 084 * @Entity 085 * public class Customer extends BaseModel { 086 * 087 * public static final CustomerFinder find = new CustomerFinder(); 088 * ... 089 * 090 * } 091 * }</pre> 092 */ 093 public Finder(Class<T> type) { 094 this.type = type; 095 this._$dbName = null; 096 } 097 098 /** 099 * Create with the type of the entity bean and specific database name. 100 */ 101 public Finder(Class<T> type, String databaseName) { 102 this.type = type; 103 this._$dbName = databaseName; 104 } 105 106 /** 107 * Return the current transaction. 108 */ 109 public Transaction currentTransaction() { 110 return db().currentTransaction(); 111 } 112 113 /** 114 * Flush the JDBC batch on the current transaction. 115 */ 116 public void flush() { 117 db().flush(); 118 } 119 120 /** 121 * Return the Database this finder will use. 122 */ 123 public Database db() { 124 return DB.byName(_$dbName); 125 } 126 127 /** 128 * Return typically a different Database to the default. 129 * <p> 130 * This is equivalent to {@link DB#byName(String)} 131 * 132 * @param databaseName The name of the Database. If this is null then the default database is returned. 133 */ 134 public Database db(String databaseName) { 135 return DB.byName(databaseName); 136 } 137 138 /** 139 * Creates an entity reference for this ID. 140 * <p> 141 * Equivalent to {@link Database#reference(Class, Object)} 142 */ 143 public T ref(I id) { 144 return db().reference(type, id); 145 } 146 147 /** 148 * Retrieves an entity by ID. 149 * <p> 150 * Equivalent to {@link Database#find(Class, Object)} 151 */ 152 @Nullable 153 public T byId(I id) { 154 return db().find(type, id); 155 } 156 157 /** 158 * Delete a bean by Id. 159 * <p> 160 * Equivalent to {@link Database#delete(Class, Object)} 161 */ 162 public void deleteById(I id) { 163 db().delete(type, id); 164 } 165 166 /** 167 * Retrieves all entities of the given type. 168 */ 169 public List<T> all() { 170 return query().findList(); 171 } 172 173 /** 174 * Creates an update query. 175 * 176 * <pre>{@code 177 * 178 * int rows = 179 * finder.update() 180 * .set("status", Customer.Status.ACTIVE) 181 * .set("updtime", new Timestamp(System.currentTimeMillis())) 182 * .where() 183 * .gt("id", 1000) 184 * .update(); 185 * 186 * }</pre> 187 * 188 * <p> 189 * Equivalent to {@link Database#update(Class)} 190 */ 191 public UpdateQuery<T> update() { 192 return db().update(type); 193 } 194 195 /** 196 * Creates a query. 197 * <p> 198 * Equivalent to {@link Database#find(Class)} 199 */ 200 public Query<T> query() { 201 return db().find(type); 202 } 203 204 /** 205 * Creates a native sql query. 206 */ 207 public Query<T> nativeSql(String nativeSql) { 208 return db().findNative(type, nativeSql); 209 } 210 211 /** 212 * Creates a query using the ORM query language. 213 */ 214 public Query<T> query(String ormQuery) { 215 return db().createQuery(type, ormQuery); 216 } 217 218}