• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

jhannes / fluent-jdbc / #198

06 Oct 2025 10:27PM UTC coverage: 91.711% (-0.5%) from 92.242%
#198

push

jhannes-test
improved ergonomics of select builders

88 of 100 new or added lines in 13 files covered. (88.0%)

2 existing lines in 1 file now uncovered.

1195 of 1303 relevant lines covered (91.71%)

0.92 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

84.62
/src/main/java/org/fluentjdbc/DbContextSelectBuilder.java
1
package org.fluentjdbc;
2

3
import javax.annotation.CheckReturnValue;
4
import javax.annotation.Nonnull;
5
import java.sql.Connection;
6
import java.util.List;
7
import java.util.stream.Stream;
8

9
/**
10
 * Used to construct SQL SELECT statements in a flexible way with {@link #where(String, Object)}
11
 * clauses, {@link #select(String...)} column names, {@link #from(String)} table statement,
12
 * {@link #groupBy(String...)}, {@link #orderBy(String)} and {@link #skipAndLimit(int, int)}.
13
 *
14
 * <h2>Example:</h2>
15
 *
16
 * <pre>
17
 * new DbContextSqlBuilder(dbContext)
18
 *      .select("first_name", "last_name")
19
 *      .select("p.id")
20
 *      .from("person p full join organizations o")
21
 *      .where("organization_sector", sector)
22
 *      .limit(100)
23
 *      .list(row -&gt; List.of(row.getString("first_name"), row.getString("last_name"), row.getUUID("p.id"));
24
 * </pre>
25
 *
26
 */
27
public class DbContextSelectBuilder implements DbContextListableSelect<DbContextSelectBuilder> {
28

29
    private final DbContext dbContext;
30
    private final DatabaseSelectBuilder builder;
31

32
    public DbContextSelectBuilder(DbContext dbContext) {
33
        this(dbContext, new DatabaseSelectBuilder(dbContext.getStatementFactory()));
1✔
34
    }
1✔
35

36
    public DbContextSelectBuilder(DbContext dbContext, DatabaseSelectBuilder builder) {
1✔
37
        this.dbContext = dbContext;
1✔
38
        this.builder = builder;
1✔
39
    }
1✔
40

41
    /**
42
     * Implemented as <code>return this</code> for compatibility purposes
43
     */
44
    @Override
45
    public DbContextSelectBuilder query() {
UNCOV
46
        return this;
×
47
    }
48

49
    @SuppressWarnings("unused")
50
    private DbContextSelectBuilder query(DatabaseSelectBuilder builder) {
51
        return this;
1✔
52
    }
53

54
    /**
55
     * Add the arguments to the column list for the <code>SELECT column, column...</code> statement
56
     */
57
    @CheckReturnValue
58
    public DbContextSelectBuilder select(String... columns) {
59
        return query(builder.select(columns));
1✔
60
    }
61

62
    /**
63
     * Replace the "from" part of the <code>SELECT ... FROM fromStatement</code> in the select statement
64
     */
65
    @CheckReturnValue
66
    public DbContextSelectBuilder from(String fromStatement) {
67
        return query(builder.from(fromStatement));
1✔
68
    }
69

70
    /**
71
     * Adds the parameter to the WHERE-clause and all the parameter list.
72
     * E.g. <code>where(new DatabaseQueryParameter("created_at between ? and ?", List.of(earliestDate, latestDate)))</code>
73
     */
74
    @Override
75
    public DbContextSelectBuilder where(DatabaseQueryParameter parameter) {
76
        builder.where(parameter);
1✔
77
        return this;
1✔
78
    }
79

80
    /**
81
     * Add the arguments to the column list for the <code>SELECT ... FROM ... ... GROUP BY groupByStatement</code> statement
82
     */
83
    @CheckReturnValue
84
    public DbContextSelectBuilder groupBy(String... groupByStatement) {
85
        return query(builder.groupBy(groupByStatement));
1✔
86
    }
87

88
    /**
89
     * Adds <code>ORDER BY ...</code> clause to the <code>SELECT</code> statement
90
     */
91
    @Override
92
    public DbContextSelectBuilder orderBy(String orderByClause) {
93
        return query(builder.orderBy(orderByClause));
1✔
94
    }
95

96
    /**
97
     * If you haven't called {@link #orderBy}, the results of {@link DatabaseListableQueryBuilder#list}
98
     * will be unpredictable. Call <code>unordered()</code> if you are okay with this.
99
     */
100
    @CheckReturnValue
101
    public DbContextSelectBuilder unordered() {
102
        return query(builder.unordered());
1✔
103
    }
104

105
    /**
106
     * Adds <code>FETCH ... ROWS ONLY</code> clause to the <code>SELECT</code> statement.
107
     * FETCH FIRST was introduced in
108
     * <a href="https://en.wikipedia.org/wiki/Select_%28SQL%29#Limiting_result_rows">SQL:2008</a>
109
     * and is supported by Postgresql 8.4, Oracle 12c, IBM DB2, HSQLDB, H2, and SQL Server 2012.
110
     */
111
    @CheckReturnValue
112
    public DbContextSelectBuilder limit(int rowCount) {
113
        return skipAndLimit(0, rowCount);
1✔
114
    }
115

116
    /**
117
     * Adds <code>OFFSET ... ROWS FETCH ... ROWS ONLY</code> clause to the <code>SELECT</code>
118
     * statement. FETCH FIRST was introduced in
119
     * <a href="https://en.wikipedia.org/wiki/Select_%28SQL%29#Limiting_result_rows">SQL:2008</a>
120
     * and is supported by Postgresql 8.4, Oracle 12c, IBM DB2, HSQLDB, H2, and SQL Server 2012.
121
     */
122
    @CheckReturnValue
123
    public DbContextSelectBuilder skipAndLimit(int offset, int rowCount) {
124
        return query(builder.skipAndLimit(offset, rowCount));
1✔
125
    }
126

127
    /**
128
     * Execute the query and map each return value over the {@link DatabaseResult.RowMapper} function to return a stream. Example:
129
     * <pre>
130
     *     table.where("status", status).stream(row -&gt; row.getInstant("created_at"))
131
     * </pre>
132
     */
133
    @Override
134
    public <OBJECT> Stream<OBJECT> stream(DatabaseResult.RowMapper<OBJECT> mapper) {
135
        return builder.stream(getConnection(), mapper);
1✔
136
    }
137

138
    /**
139
     * Execute the query and map each return value over the {@link DatabaseResult.RowMapper} function to return a list. Example:
140
     * <pre>
141
     *     List&lt;Instant&gt; creationTimes = table.where("status", status).list(row -&gt; row.getInstant("created_at"))
142
     * </pre>
143
     */
144
    @Override
145
    public <OBJECT> List<OBJECT> list(DatabaseResult.RowMapper<OBJECT> mapper) {
146
        return builder.list(getConnection(), mapper);
1✔
147
    }
148

149
    /**
150
     * Executes <code>SELECT count(*) FROM ...</code> on the query and returns the result
151
     */
152
    @Override
153
    public int getCount() {
154
        return builder.getCount(getConnection());
1✔
155
    }
156

157
    /**
158
     * If the query returns no rows, returns {@link SingleRow#absent}, if exactly one row is returned, maps it and return it,
159
     * if more than one is returned, throws `IllegalStateException`
160
     *
161
     * @param mapper Function object to map a single returned row to an object
162
     * @return the mapped row if one row is returned, {@link SingleRow#absent} otherwise
163
     * @throws MultipleRowsReturnedException if more than one row was matched the query
164
     */
165
    @Nonnull
166
    @Override
167
    public <OBJECT> SingleRow<OBJECT> singleObject(DatabaseResult.RowMapper<OBJECT> mapper) {
168
        return builder.singleObject(getConnection(), mapper);
1✔
169
    }
170

171
    /**
172
     * Returns a string from the specified column name
173
     *
174
     * @return the mapped row if one row is returned, {@link SingleRow#absent} otherwise
175
     * @throws MultipleRowsReturnedException if more than one row was matched the query
176
     */
177
    @Nonnull
178
    @Override
179
    public SingleRow<String> singleString(String fieldName) {
NEW
180
        return builder.singleString(getConnection(), fieldName);
×
181
    }
182

183
    /**
184
     * Executes the <code>SELECT * FROM ...</code> statement and calls back to
185
     * {@link DatabaseResult.RowConsumer} for each returned row
186
     */
187
    @Override
188
    public void forEach(DatabaseResult.RowConsumer consumer) {
NEW
189
        builder.forEach(getConnection(), consumer);
×
UNCOV
190
    }
×
191

192
    @Nonnull
193
    private Connection getConnection() {
194
        return dbContext.getThreadConnection();
1✔
195
    }
196

197
    /**
198
     * Returns a {@link DatabaseQueryParameter} with a <code>column in (SELECT ....)</code>
199
     * with this expression and the same parameters as this builder
200
     */
201
    public DatabaseQueryParameter asNestedSelectOn(String column) {
202
        return builder.asNestedSelectOn(column);
1✔
203
    }
204
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc