001package io.ebean; 002 003import javax.annotation.Nonnull; 004import javax.annotation.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 */ 058public class Finder<I, T> { 059 060 /** 061 * The entity bean type. 062 */ 063 private final Class<T> type; 064 065 /** 066 * The name of the database this finder will use, null for the default database. 067 */ 068 private final String _$dbName; 069 070 /** 071 * Create with the type of the entity bean. 072 * <pre>{@code 073 * 074 * public class CustomerFinder extends Finder<Customer> { 075 * 076 * public CustomerFinder() { 077 * super(Customer.class); 078 * } 079 * 080 * // ... add extra customer specific finder methods 081 * } 082 * 083 * @Entity 084 * public class Customer extends BaseModel { 085 * 086 * public static final CustomerFinder find = new CustomerFinder(); 087 * ... 088 * 089 * } 090 * }</pre> 091 */ 092 public Finder(Class<T> type) { 093 this.type = type; 094 this._$dbName = null; 095 } 096 097 /** 098 * Create with the type of the entity bean and specific database name. 099 */ 100 public Finder(Class<T> type, String databaseName) { 101 this.type = type; 102 this._$dbName = databaseName; 103 } 104 105 /** 106 * Return the current transaction. 107 */ 108 public Transaction currentTransaction() { 109 return db().currentTransaction(); 110 } 111 112 /** 113 * Flush the JDBC batch on the current transaction. 114 */ 115 public void flush() { 116 db().flush(); 117 } 118 119 /** 120 * Return the Database this finder will use. 121 */ 122 public Database db() { 123 return DB.byName(_$dbName); 124 } 125 126 /** 127 * Return typically a different Database to the default. 128 * <p> 129 * This is equivalent to {@link DB#byName(String)} 130 * 131 * @param databaseName The name of the Database. If this is null then the default database is returned. 132 */ 133 public Database db(String databaseName) { 134 return DB.byName(databaseName); 135 } 136 137 /** 138 * Creates an entity reference for this ID. 139 * <p> 140 * Equivalent to {@link Database#getReference(Class, Object)} 141 */ 142 @Nonnull 143 public T ref(I id) { 144 return db().getReference(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 @Nonnull 170 public List<T> all() { 171 return query().findList(); 172 } 173 174 /** 175 * Creates an update query. 176 * 177 * <pre>{@code 178 * 179 * int rows = 180 * finder.update() 181 * .set("status", Customer.Status.ACTIVE) 182 * .set("updtime", new Timestamp(System.currentTimeMillis())) 183 * .where() 184 * .gt("id", 1000) 185 * .update(); 186 * 187 * }</pre> 188 * 189 * <p> 190 * Equivalent to {@link Database#update(Class)} 191 */ 192 public UpdateQuery<T> update() { 193 return db().update(type); 194 } 195 196 /** 197 * Creates a query. 198 * <p> 199 * Equivalent to {@link Database#find(Class)} 200 */ 201 public Query<T> query() { 202 return db().find(type); 203 } 204 205 /** 206 * Creates a native sql query. 207 */ 208 public Query<T> nativeSql(String nativeSql) { 209 return db().findNative(type, nativeSql); 210 } 211 212 /** 213 * Creates a query using the ORM query language. 214 */ 215 public Query<T> query(String ormQuery) { 216 return db().createQuery(type, ormQuery); 217 } 218 219}