Skip to content

Commit 40aa0bc

Browse files
committed
Add an example of converting a select statement to a count statement
1 parent 66dbf91 commit 40aa0bc

File tree

1 file changed

+69
-0
lines changed

1 file changed

+69
-0
lines changed

src/test/java/examples/simple/ReusableWhereTest.java

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,13 @@
1717

1818
import static examples.simple.PersonDynamicSqlSupport.id;
1919
import static examples.simple.PersonDynamicSqlSupport.occupation;
20+
import static examples.simple.PersonDynamicSqlSupport.person;
2021
import static org.assertj.core.api.Assertions.assertThat;
22+
import static org.assertj.core.api.Assertions.entry;
2123
import static org.mybatis.dynamic.sql.SqlBuilder.isEqualTo;
24+
import static org.mybatis.dynamic.sql.SqlBuilder.isLessThan;
2225
import static org.mybatis.dynamic.sql.SqlBuilder.isNull;
26+
import static org.mybatis.dynamic.sql.SqlBuilder.select;
2327
import static org.mybatis.dynamic.sql.SqlBuilder.where;
2428

2529
import java.io.InputStream;
@@ -38,6 +42,12 @@
3842
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
3943
import org.junit.jupiter.api.BeforeEach;
4044
import org.junit.jupiter.api.Test;
45+
import org.mybatis.dynamic.sql.render.RenderingStrategies;
46+
import org.mybatis.dynamic.sql.select.QueryExpressionModel;
47+
import org.mybatis.dynamic.sql.select.SelectModel;
48+
import org.mybatis.dynamic.sql.select.SubQuery;
49+
import org.mybatis.dynamic.sql.select.aggregate.CountAll;
50+
import org.mybatis.dynamic.sql.select.render.SelectStatementProvider;
4151
import org.mybatis.dynamic.sql.where.WhereApplier;
4252

4353
class ReusableWhereTest {
@@ -114,5 +124,64 @@ void testUpdate() {
114124
}
115125
}
116126

127+
@Test
128+
void testTransformToCount() {
129+
try (SqlSession session = sqlSessionFactory.openSession()) {
130+
PersonMapper mapper = session.getMapper(PersonMapper.class);
131+
132+
SelectModel selectModel = select(PersonMapper.selectList)
133+
.from(person)
134+
.where(id, isLessThan(5))
135+
.limit(2)
136+
.build();
137+
138+
SelectStatementProvider selectStatement = selectModel.render(RenderingStrategies.MYBATIS3);
139+
140+
assertThat(selectStatement.getSelectStatement()).isEqualTo(
141+
"select id as A_ID, first_name, last_name, birth_date, employed, occupation, address_id from Person where id < #{parameters.p1,jdbcType=INTEGER} limit #{parameters.p2}");
142+
assertThat(selectStatement.getParameters()).containsOnly(entry("p1", 5), entry("p2", 2L));
143+
144+
SelectModel countModel = toCount(selectModel);
145+
SelectStatementProvider countStatement = countModel.render(RenderingStrategies.MYBATIS3);
146+
147+
assertThat(countStatement.getSelectStatement()).isEqualTo(
148+
"select count(*) from (select id as A_ID, first_name, last_name, birth_date, employed, occupation, address_id from Person where id < #{parameters.p1,jdbcType=INTEGER})");
149+
assertThat(countStatement.getParameters()).containsOnly(entry("p1", 5));
150+
151+
long count = mapper.count(countStatement);
152+
153+
assertThat(count).isEqualTo(4);
154+
}
155+
156+
}
157+
117158
private final WhereApplier commonWhere = where(id, isEqualTo(1)).or(occupation, isNull()).toWhereApplier();
159+
160+
/**
161+
* This function transforms a select statement into a count statement by wrapping the select statement into
162+
* a subquery. This can be used to create a single select statement and use it for both selects and counts
163+
* in a paging scenario. This is more appropriate than a reusable where clause if the query is complex. For simple
164+
* queries, a reusable where clause is best.
165+
*
166+
* <p>This function will strip any paging configuration, waits, order bys, etc. from the top level query. This
167+
* will allow usage of a paging query for selects, and the transformed query for a count of all rows.
168+
*
169+
* @param selectModel the select model to transform
170+
* @return a new select model that is "select count(*) from (subquery)" where subquery is the input select statement
171+
*/
172+
static SelectModel toCount(SelectModel selectModel) {
173+
// remove any paging configuration, order by, wait clause, etc. from the incoming select model
174+
SelectModel strippedSelectModel = SelectModel.withQueryExpressions(selectModel.queryExpressions().toList())
175+
.withStatementConfiguration(selectModel.statementConfiguration())
176+
.build();
177+
178+
QueryExpressionModel model = QueryExpressionModel
179+
.withSelectList(List.of(new CountAll()))
180+
.withTable(new SubQuery.Builder().withSelectModel(strippedSelectModel).build())
181+
.build();
182+
183+
return SelectModel.withQueryExpressions(List.of(model))
184+
.withStatementConfiguration(selectModel.statementConfiguration())
185+
.build();
186+
}
118187
}

0 commit comments

Comments
 (0)