Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit ab09a2b

Browse files
Merge pull request #994 from jeffgbutler/transformers
Add an example of converting a select statement to a count statement
2 parents 74a4b63 + 40aa0bc commit ab09a2b

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)

AltStyle によって変換されたページ (->オリジナル) /