001package io.ebean; 002 003import javax.annotation.Nonnull; 004import javax.annotation.Nullable; 005import java.io.Serializable; 006import java.math.BigDecimal; 007import java.util.List; 008import java.util.Optional; 009import java.util.function.Consumer; 010import java.util.function.Predicate; 011 012/** 013 * Query object for performing native SQL queries that return SqlRow or directly read 014 * ResultSet using a RowMapper. 015 * <p> 016 * The returned SqlRow objects are similar to a LinkedHashMap with some type 017 * conversion support added. 018 * </p> 019 * <p> 020 * Refer to {@link DtoQuery} for native sql queries returning DTO beans. 021 * </p> 022 * <p> 023 * Refer to {@link Database#findNative(Class, String)} for native sql queries returning entity beans. 024 * </p> 025 * 026 * <pre>{@code 027 * 028 * // example using named parameters 029 * 030 * String sql = "select id, name from customer where name like :name and status_code = :status"; 031 * 032 * List<SqlRow> list = 033 * DB.sqlQuery(sql) 034 * .setParameter("name", "Acme%") 035 * .setParameter("status", "ACTIVE") 036 * .findList(); 037 * 038 * }</pre> 039 */ 040public interface SqlQuery extends Serializable { 041 042 /** 043 * Execute the query returning a list. 044 */ 045 @Nonnull 046 List<SqlRow> findList(); 047 048 /** 049 * Execute the SqlQuery iterating a row at a time. 050 * <p> 051 * This streaming type query is useful for large query execution as only 1 row needs to be held in memory. 052 * </p> 053 */ 054 void findEach(Consumer<SqlRow> consumer); 055 056 /** 057 * Execute the SqlQuery iterating a row at a time with the ability to stop consuming part way through. 058 * <p> 059 * Returning false after processing a row stops the iteration through the query results. 060 * </p> 061 * <p> 062 * This streaming type query is useful for large query execution as only 1 row needs to be held in memory. 063 * </p> 064 */ 065 void findEachWhile(Predicate<SqlRow> consumer); 066 067 /** 068 * Execute the query returning a single row or null. 069 * <p> 070 * If this query finds 2 or more rows then it will throw a 071 * PersistenceException. 072 * </p> 073 */ 074 @Nullable 075 SqlRow findOne(); 076 077 /** 078 * Execute the query returning a single result using the mapper. 079 * 080 * @param mapper Used to map each ResultSet row into the result object. 081 */ 082 <T> T findOne(RowMapper<T> mapper); 083 084 /** 085 * Execute the query returning a list using the mapper. 086 * 087 * @param mapper Used to map each ResultSet row into the result object. 088 */ 089 <T> List<T> findList(RowMapper<T> mapper); 090 091 /** 092 * Execute the query reading each row from ResultSet using the RowConsumer. 093 * <p> 094 * This provides a low level option that reads directly from the JDBC ResultSet 095 * and is good for processing very large results where (unlike findList) we don't 096 * hold all the results in memory but instead can process row by row. 097 * </p> 098 * 099 * <pre>{@code 100 * 101 * String sql = "select id, name, status from customer order by name desc"; 102 * 103 * DB.sqlQuery(sql) 104 * .findEachRow((resultSet, rowNum) -> { 105 * 106 * // read directly from ResultSet 107 * 108 * long id = resultSet.getLong(1); 109 * String name = resultSet.getString(2); 110 * 111 * // do something interesting with the data 112 * 113 * }); 114 * 115 * }</pre> 116 * 117 * @param consumer Used to read and process each ResultSet row. 118 */ 119 void findEachRow(RowConsumer consumer); 120 121 /** 122 * Execute the query returning an optional row. 123 */ 124 @Nonnull 125 Optional<SqlRow> findOneOrEmpty(); 126 127 /** 128 * Execute the query returning a single scalar attribute. 129 * <pre>@{code 130 * 131 * String sql = "select max(unit_price) from o_order_detail where order_qty > ?"; 132 * 133 * BigDecimal maxPrice = DB.sqlQuery(sql) 134 * .setParameter(1, 2) 135 * .findSingleAttribute(BigDecimal.class); 136 * 137 * }</pre> 138 * 139 * <p> 140 * The attributeType can be any scalar type that Ebean supports (includes javax time types, Joda types etc). 141 * </p> 142 * 143 * @param attributeType The type of the returned value 144 */ 145 <T> T findSingleAttribute(Class<T> attributeType); 146 147 /** 148 * Execute the query returning a single BigDecimal value. 149 * <p> 150 * This is an alias for <code>findSingleAttribute(BigDecimal.class)</code> 151 * </p> 152 */ 153 BigDecimal findSingleDecimal(); 154 155 /** 156 * Execute the query returning a single Long value. 157 * <p> 158 * This is an alias for <code>findSingleAttribute(Long.class)</code> 159 * </p> 160 */ 161 Long findSingleLong(); 162 163 /** 164 * Execute the query returning a list of scalar attribute values. 165 * 166 * <pre>{@code 167 * 168 * String sql = 169 * " select (unit_price * order_qty) " + 170 * " from o_order_detail " + 171 * " where unit_price > ? " + 172 * " order by (unit_price * order_qty) desc"; 173 * 174 * // 175 * List<BigDecimal> lineAmounts = 176 * DB.sqlQuery(sql) 177 * .setParameter(1, 3) 178 * .findSingleAttributeList(BigDecimal.class); 179 * 180 * }</pre> 181 * 182 * <p> 183 * The attributeType can be any scalar type that Ebean supports (includes javax time types, Joda types etc). 184 * </p> 185 * 186 * @param attributeType The type of the returned value 187 */ 188 <T> List<T> findSingleAttributeList(Class<T> attributeType); 189 190 /** 191 * The same as bind for named parameters. 192 */ 193 SqlQuery setParameter(String name, Object value); 194 195 /** 196 * Set one of more positioned parameters. 197 * <p> 198 * This is a convenient alternative to multiple calls setParameter(). 199 * 200 * <pre>{@code 201 * 202 * String sql = "select id, name from customer where name like ? and status = ?"; 203 * 204 * List<SqlRow> list = 205 * DB.sqlQuery(sql) 206 * .setParams("Rob", Status.NEW) 207 * .findList(); 208 * 209 * 210 * // is the same as ... 211 * 212 * List<SqlRow> list = 213 * DB.sqlQuery(sql) 214 * .setParameter(1, "Rob") 215 * .setParameter(2, "Status.NEW) 216 * .findList(); 217 * 218 * }</pre> 219 */ 220 SqlQuery setParams(Object... values); 221 222 /** 223 * The same as bind for positioned parameters. 224 */ 225 SqlQuery setParameter(int position, Object value); 226 227 /** 228 * Set the index of the first row of the results to return. 229 */ 230 SqlQuery setFirstRow(int firstRow); 231 232 /** 233 * Set the maximum number of query results to return. 234 */ 235 SqlQuery setMaxRows(int maxRows); 236 237 /** 238 * Set a timeout on this query. 239 * <p> 240 * This will typically result in a call to setQueryTimeout() on a 241 * preparedStatement. If the timeout occurs an exception will be thrown - this 242 * will be a SQLException wrapped up in a PersistenceException. 243 * </p> 244 * 245 * @param secs the query timeout limit in seconds. Zero means there is no limit. 246 */ 247 SqlQuery setTimeout(int secs); 248 249 /** 250 * Set a label that can be put on performance metrics that are collected. 251 */ 252 SqlQuery setLabel(String label); 253 254 /** 255 * A hint which for JDBC translates to the Statement.fetchSize(). 256 * <p> 257 * Gives the JDBC driver a hint as to the number of rows that should be 258 * fetched from the database when more rows are needed for ResultSet. 259 * </p> 260 */ 261 SqlQuery setBufferFetchSizeHint(int bufferFetchSizeHint); 262 263}