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 * .orderBy("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 * }</pre> 047 * <p> 048 * When the Finder is registered as a field on Customer it can then be used like: 049 * </p> 050 * <pre>{@code 051 * 052 * Customer rob = Customer.find.byName("Rob"); 053 * 054 * }</pre> 055 * 056 */ 057public class Finder<I, T> { 058 059 /** 060 * The entity bean type. 061 */ 062 private final Class<T> type; 063 064 /** 065 * The name of the database this finder will use, null for the default database. 066 */ 067 private final String _$dbName; 068 069 /** 070 * Create with the type of the entity bean. 071 * <pre>{@code 072 * 073 * public class CustomerFinder extends Finder<Customer> { 074 * 075 * public CustomerFinder() { 076 * super(Customer.class); 077 * } 078 * 079 * // ... add extra customer specific finder methods 080 * } 081 * 082 * @Entity 083 * public class Customer extends BaseModel { 084 * 085 * public static final CustomerFinder find = new CustomerFinder(); 086 * ... 087 * 088 * }</pre> 089 */ 090 public Finder(Class<T> type) { 091 this.type = type; 092 this._$dbName = null; 093 } 094 095 /** 096 * Create with the type of the entity bean and specific database name. 097 */ 098 public Finder(Class<T> type, String databaseName) { 099 this.type = type; 100 this._$dbName = databaseName; 101 } 102 103 /** 104 * Return the current transaction. 105 */ 106 public Transaction currentTransaction() { 107 return db().currentTransaction(); 108 } 109 110 /** 111 * Flush the JDBC batch on the current transaction. 112 */ 113 public void flush() { 114 db().flush(); 115 } 116 117 /** 118 * Return the Database this finder will use. 119 */ 120 public Database db() { 121 return DB.byName(_$dbName); 122 } 123 124 /** 125 * Return typically a different Database to the default. 126 * <p> 127 * This is equivalent to {@link DB#byName(String)} 128 * 129 * @param databaseName The name of the Database. If this is null then the default database is returned. 130 */ 131 public Database db(String databaseName) { 132 return DB.byName(databaseName); 133 } 134 135 /** 136 * Creates an entity reference for this ID. 137 * <p> 138 * Equivalent to {@link Database#getReference(Class, Object)} 139 */ 140 @Nonnull 141 public T ref(I id) { 142 return db().getReference(type, id); 143 } 144 145 /** 146 * Retrieves an entity by ID. 147 * <p> 148 * Equivalent to {@link Database#find(Class, Object)} 149 */ 150 @Nullable 151 public T byId(I id) { 152 return db().find(type, id); 153 } 154 155 /** 156 * Delete a bean by Id. 157 * <p> 158 * Equivalent to {@link Database#delete(Class, Object)} 159 */ 160 public void deleteById(I id) { 161 db().delete(type, id); 162 } 163 164 /** 165 * Retrieves all entities of the given type. 166 */ 167 @Nonnull 168 public List<T> all() { 169 return query().findList(); 170 } 171 172 /** 173 * Creates an update query. 174 * 175 * <pre>{@code 176 * 177 * int rows = 178 * finder.update() 179 * .set("status", Customer.Status.ACTIVE) 180 * .set("updtime", new Timestamp(System.currentTimeMillis())) 181 * .where() 182 * .gt("id", 1000) 183 * .update(); 184 * 185 * }</pre> 186 * 187 * <p> 188 * Equivalent to {@link Database#update(Class)} 189 */ 190 public UpdateQuery<T> update() { 191 return db().update(type); 192 } 193 194 /** 195 * Creates a query. 196 * <p> 197 * Equivalent to {@link Database#find(Class)} 198 */ 199 public Query<T> query() { 200 return db().find(type); 201 } 202 203 /** 204 * Creates a native sql query. 205 */ 206 public Query<T> nativeSql(String nativeSql) { 207 return db().findNative(type, nativeSql); 208 } 209 210 /** 211 * Creates a query using the ORM query language. 212 */ 213 public Query<T> query(String ormQuery) { 214 return db().createQuery(type, ormQuery); 215 } 216 217}