Skip to content

Commit 38988bd

Browse files
committed
1. Added DataSupport class.
2. Added new aggregate function APIs. 3. Optimize code.
1 parent ae752a4 commit 38988bd

4 files changed

Lines changed: 178 additions & 31 deletions

File tree

src/main/java/com/github/artbits/jsqlite/Core.java

Lines changed: 141 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -108,13 +108,26 @@ public void drop(Class<?>... classes) {
108108

109109

110110
@Override
111-
public <T> void insert(T t) {
111+
public String version() {
112+
String s = "select sqlite_version();";
113+
try (Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery(s)) {
114+
return (resultSet.next()) ? resultSet.getString(1) : "unknown";
115+
} catch (SQLException e) {
116+
throw new RuntimeException(e);
117+
}
118+
}
119+
120+
121+
@Override
122+
public <T extends DataSupport<T>> void insert(T t) {
112123
synchronized (this) {
113124
try (Statement statement = connection.createStatement()) {
125+
t.createdAt = System.currentTimeMillis();
126+
t.updatedAt = t.createdAt;
114127
statement.executeUpdate(SQLTemplate.insert(t));
115128
try (ResultSet result = statement.executeQuery("select last_insert_rowid()")) {
116129
if (result.next()) {
117-
new Reflect<>(t).setValue("id", result.getLong(1));
130+
t.id = result.getLong(1);
118131
}
119132
}
120133
} catch (Exception e) {
@@ -125,9 +138,10 @@ public <T> void insert(T t) {
125138

126139

127140
@Override
128-
public <T> void update(T t, String predicate, Object... args) {
141+
public <T extends DataSupport<T>> void update(T t, String predicate, Object... args) {
129142
synchronized (this) {
130143
try (Statement statement = connection.createStatement()) {
144+
t.updatedAt = System.currentTimeMillis();
131145
statement.executeUpdate(SQLTemplate.update(t, new Options().where(predicate, args)));
132146
} catch (Exception e) {
133147
throw new RuntimeException(e);
@@ -137,14 +151,13 @@ public <T> void update(T t, String predicate, Object... args) {
137151

138152

139153
@Override
140-
public <T> void update(T t) {
141-
Object id = new Reflect<T>(t).getValue("id");
142-
update(t, "id = ?", id);
154+
public <T extends DataSupport<T>> void update(T t) {
155+
update(t, "id = ?", t.id());
143156
}
144157

145158

146159
@Override
147-
public void delete(Class<?> tClass, String predicate, Object... args) {
160+
public <T extends DataSupport<T>> void delete(Class<T> tClass, String predicate, Object... args) {
148161
synchronized (this) {
149162
String sql = SQLTemplate.delete(tClass, new Options().where(predicate, args));
150163
try (Statement statement = connection.createStatement()) {
@@ -157,27 +170,27 @@ public void delete(Class<?> tClass, String predicate, Object... args) {
157170

158171

159172
@Override
160-
public void delete(Class<?> tClass, List<Long> ids) {
173+
public <T extends DataSupport<T>> void delete(Class<T> tClass, List<Long> ids) {
161174
StringBuilder builder = new StringBuilder(String.valueOf(ids));
162175
builder.deleteCharAt(0).deleteCharAt(builder.length() - 1);
163176
delete(tClass, "id in(?)", builder);
164177
}
165178

166179

167180
@Override
168-
public void delete(Class<?> tClass, Long... ids) {
181+
public <T extends DataSupport<T>> void delete(Class<T> tClass, Long... ids) {
169182
delete(tClass, Arrays.asList(ids));
170183
}
171184

172185

173186
@Override
174-
public void deleteAll(Class<?> tClass) {
187+
public <T extends DataSupport<T>> void deleteAll(Class<T> tClass) {
175188
delete(tClass, null, (Object) null);
176189
}
177190

178191

179192
@Override
180-
public <T> List<T> find(Class<T> tClass, Consumer<Options> consumer) {
193+
public <T extends DataSupport<T>> List<T> find(Class<T> tClass, Consumer<Options> consumer) {
181194
Options options = (consumer != null) ? new Options() : null;
182195
Optional.ofNullable(consumer).ifPresent(c -> c.accept(options));
183196
String sql = SQLTemplate.query(tClass, options);
@@ -195,35 +208,147 @@ public <T> List<T> find(Class<T> tClass, Consumer<Options> consumer) {
195208

196209

197210
@Override
198-
public <T> List<T> find(Class<T> tClass, List<Long> ids) {
211+
public <T extends DataSupport<T>> List<T> find(Class<T> tClass, List<Long> ids) {
199212
StringBuilder builder = new StringBuilder(String.valueOf(ids));
200213
builder.deleteCharAt(0).deleteCharAt(builder.length() - 1);
201214
return find(tClass, options -> options.where("id in(?)", builder));
202215
}
203216

204217

205218
@Override
206-
public <T> List<T> find(Class<T> tClass, Long... ids) {
219+
public <T extends DataSupport<T>> List<T> find(Class<T> tClass, Long... ids) {
207220
return find(tClass, Arrays.asList(ids));
208221
}
209222

210223

211224
@Override
212-
public <T> List<T> findAll(Class<T> tClass) {
225+
public <T extends DataSupport<T>> List<T> findAll(Class<T> tClass) {
213226
return find(tClass, (Consumer<Options>) null);
214227
}
215228

216229

217230
@Override
218-
public <T> T findOne(Class<T> tClass, String predicate, Object... args) {
231+
public <T extends DataSupport<T>> T findOne(Class<T> tClass, String predicate, Object... args) {
219232
List<T> list = find(tClass, options -> options.where(predicate, args));
220233
return (!list.isEmpty()) ? list.get(0) : null;
221234
}
222235

223236

224237
@Override
225-
public <T> T findOne(Class<T> tClass, Long id) {
238+
public <T extends DataSupport<T>> T findOne(Class<T> tClass, Long id) {
226239
return findOne(tClass, "id = ?", id);
227240
}
228241

242+
243+
@Override
244+
public <T extends DataSupport<T>> T first(Class<T> tClass, String predicate, Object... args) {
245+
List<T> list = find(tClass, options -> options.where(predicate, args).order("id", Options.ASC));
246+
return (!list.isEmpty()) ? list.get(0) : null;
247+
}
248+
249+
250+
@Override
251+
public <T extends DataSupport<T>> T first(Class<T> tClass) {
252+
return first(tClass, null, (Object) null);
253+
}
254+
255+
256+
@Override
257+
public <T extends DataSupport<T>> T last(Class<T> tClass, String predicate, Object... args) {
258+
List<T> list = find(tClass, options -> options.where(predicate, args).order("id", Options.DESC));
259+
return (!list.isEmpty()) ? list.get(0) : null;
260+
}
261+
262+
263+
@Override
264+
public <T extends DataSupport<T>> T last(Class<T> tClass) {
265+
return last(tClass, null, (Object) null);
266+
}
267+
268+
269+
@Override
270+
public <T extends DataSupport<T>> long count(Class<T> tClass, String predicate, Object... args) {
271+
String s = SQLTemplate.query(tClass, new Options().select("count(*)").where(predicate, args));
272+
try (Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery(s)) {
273+
return (resultSet.next()) ? resultSet.getLong(1) : 0;
274+
} catch (SQLException e) {
275+
throw new RuntimeException(e);
276+
}
277+
}
278+
279+
280+
@Override
281+
public <T extends DataSupport<T>> long count(Class<T> tClass) {
282+
return count(tClass, null, (Object) null);
283+
}
284+
285+
286+
@Override
287+
public <T extends DataSupport<T>> double average(Class<T> tClass, String column, String predicate, Object... args) {
288+
String s = SQLTemplate.query(tClass, new Options().select(String.format("avg(%s)", column)).where(predicate, args));
289+
try (Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery(s)) {
290+
return (resultSet.next()) ? resultSet.getDouble(1) : 0;
291+
} catch (SQLException e) {
292+
throw new RuntimeException(e);
293+
}
294+
}
295+
296+
297+
@Override
298+
public <T extends DataSupport<T>> double average(Class<T> tClass, String column) {
299+
return average(tClass, column, null, (Object) null);
300+
}
301+
302+
303+
@Override
304+
public <T extends DataSupport<T>> Number sum(Class<T> tClass, String column, String predicate, Object... args) {
305+
String s = SQLTemplate.query(tClass, new Options().select(String.format("sum(%s)", column)).where(predicate, args));
306+
try (Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery(s)) {
307+
return (resultSet.next()) ? (Number) resultSet.getObject(1) : 0;
308+
} catch (SQLException e) {
309+
throw new RuntimeException(e);
310+
}
311+
}
312+
313+
314+
@Override
315+
public <T extends DataSupport<T>> Number sum(Class<T> tClass, String column) {
316+
return sum(tClass, column, null, (Object) null);
317+
}
318+
319+
320+
@Override
321+
public <T extends DataSupport<T>> Number max(Class<T> tClass, String column, String predicate, Object... args) {
322+
String s = SQLTemplate.query(tClass, new Options().select(String.format("max(%s)", column)).where(predicate, args));
323+
try (Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery(s)) {
324+
return (resultSet.next()) ? (Number) resultSet.getObject(1) : 0;
325+
} catch (SQLException e) {
326+
throw new RuntimeException(e);
327+
}
328+
}
329+
330+
331+
@Override
332+
public <T extends DataSupport<T>> Number max(Class<T> tClass, String column) {
333+
return max(tClass, column, null, (Object) null);
334+
}
335+
336+
337+
@Override
338+
public <T extends DataSupport<T>> Number min(Class<T> tClass, String column, String predicate, Object... args) {
339+
String s = SQLTemplate.query(tClass, new Options().select(String.format("min(%s)", column)).where(predicate, args));
340+
try (Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery(s)) {
341+
return (resultSet.next()) ? (Number) resultSet.getObject(1) : 0;
342+
} catch (SQLException e) {
343+
throw new RuntimeException(e);
344+
}
345+
}
346+
347+
348+
@Override
349+
public <T extends DataSupport<T>> Number min(Class<T> tClass, String column) {
350+
return min(tClass, column, null, (Object) null);
351+
}
352+
353+
229354
}

src/main/java/com/github/artbits/jsqlite/DB.java

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,34 @@ public interface DB extends AutoCloseable {
2424
void close();
2525
void tables(Class<?>... classes);
2626
void drop(Class<?>... classes);
27-
<T> void insert(T t);
28-
<T> void update(T t, String predicate, Object... args);
29-
<T> void update(T t);
30-
void delete(Class<?> tClass, String predicate, Object... args);
31-
void delete(Class<?> tClass, List<Long> ids);
32-
void delete(Class<?> tClass, Long... ids);
33-
void deleteAll(Class<?> tClass);
34-
<T> List<T> find(Class<T> tClass, Consumer<Options> consumer);
35-
<T> List<T> find(Class<T> tClass, List<Long> ids);
36-
<T> List<T> find(Class<T> tClass, Long... ids);
37-
<T> List<T> findAll(Class<T> tClass);
38-
<T> T findOne(Class<T> tClass, String predicate, Object... args);
39-
<T> T findOne(Class<T> tClass, Long id);
27+
String version();
28+
<T extends DataSupport<T>> void insert(T t);
29+
<T extends DataSupport<T>> void update(T t, String predicate, Object... args);
30+
<T extends DataSupport<T>> void update(T t);
31+
<T extends DataSupport<T>> void delete(Class<T> tClass, String predicate, Object... args);
32+
<T extends DataSupport<T>> void delete(Class<T> tClass, List<Long> ids);
33+
<T extends DataSupport<T>> void delete(Class<T> tClass, Long... ids);
34+
<T extends DataSupport<T>> void deleteAll(Class<T> tClass);
35+
<T extends DataSupport<T>> List<T> find(Class<T> tClass, Consumer<Options> consumer);
36+
<T extends DataSupport<T>> List<T> find(Class<T> tClass, List<Long> ids);
37+
<T extends DataSupport<T>> List<T> find(Class<T> tClass, Long... ids);
38+
<T extends DataSupport<T>> List<T> findAll(Class<T> tClass);
39+
<T extends DataSupport<T>> T findOne(Class<T> tClass, String predicate, Object... args);
40+
<T extends DataSupport<T>> T findOne(Class<T> tClass, Long id);
41+
<T extends DataSupport<T>> T first(Class<T> tClass, String predicate, Object... args);
42+
<T extends DataSupport<T>> T first(Class<T> tClass);
43+
<T extends DataSupport<T>> T last(Class<T> tClass, String predicate, Object... args);
44+
<T extends DataSupport<T>> T last(Class<T> tClass);
45+
<T extends DataSupport<T>> long count(Class<T> tClass, String predicate, Object... args);
46+
<T extends DataSupport<T>> long count(Class<T> tClass);
47+
<T extends DataSupport<T>> double average(Class<T> tClass, String column, String predicate, Object... args);
48+
<T extends DataSupport<T>> double average(Class<T> tClass, String column);
49+
<T extends DataSupport<T>> Number sum(Class<T> tClass, String column, String predicate, Object... args);
50+
<T extends DataSupport<T>> Number sum(Class<T> tClass, String column);
51+
<T extends DataSupport<T>> Number max(Class<T> tClass, String column, String predicate, Object... args);
52+
<T extends DataSupport<T>> Number max(Class<T> tClass, String column);
53+
<T extends DataSupport<T>> Number min(Class<T> tClass, String column, String predicate, Object... args);
54+
<T extends DataSupport<T>> Number min(Class<T> tClass, String column);
4055

4156
static DB connect(String path) {
4257
return new Core(path);

src/main/java/com/github/artbits/jsqlite/Options.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,12 @@ public Options where(String predicate, Object... objects) {
5656
if (o instanceof String || o instanceof Character) {
5757
return String.format("'%s'", o);
5858
} else {
59-
return String.valueOf(o);
59+
String s = String.valueOf(o);
60+
switch (s) {
61+
case "true": return "1";
62+
case "false": return "0";
63+
default: return s;
64+
}
6065
}
6166
}).toArray());
6267
}

src/main/java/com/github/artbits/jsqlite/Reflect.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.sql.ResultSet;
2121
import java.util.*;
2222
import java.util.function.BiConsumer;
23+
import java.util.function.Consumer;
2324

2425
final class Reflect<T> {
2526

@@ -140,7 +141,8 @@ static <T> T toEntity(Class<T> tClass, Options options, ResultSet resultSet) {
140141
columnsMap.put(column, true);
141142
}
142143
}
143-
Reflect<T> reflect = new Reflect<>(tClass.newInstance());
144+
T t = tClass.getConstructor(Consumer.class).newInstance((Consumer<T>) (c -> {}));
145+
Reflect<T> reflect = new Reflect<>(t);
144146
for (Field field : reflect.fieldMap.values()) {
145147
String name = field.getName();
146148
if (!columnsMap.isEmpty() && !columnsMap.getOrDefault(name, false)) {

0 commit comments

Comments
 (0)