/* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jdbi.v3.sqlobject; import static org.assertj.core.api.Assertions.assertThat; import java.lang.reflect.Method; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; import org.jdbi.v3.core.Jdbi; import org.jdbi.v3.core.extension.ExtensionMethod; import org.jdbi.v3.core.rule.H2DatabaseRule; import org.jdbi.v3.core.statement.PreparedBatch; import org.jdbi.v3.core.statement.StatementContext; import org.jdbi.v3.core.statement.TimingCollector; import org.jdbi.v3.sqlobject.customizer.Bind; import org.jdbi.v3.sqlobject.statement.BatchChunkSize; import org.jdbi.v3.sqlobject.statement.SqlBatch; import org.jdbi.v3.sqlobject.statement.SqlCall; import org.jdbi.v3.sqlobject.statement.SqlQuery; import org.jdbi.v3.sqlobject.statement.SqlUpdate; import org.junit.Before; import org.junit.Rule; import org.junit.Test; public class TestTimingCollector { @Rule public H2DatabaseRule dbRule = new H2DatabaseRule().withPlugins(); private final CustomTimingCollector timingCollector = new CustomTimingCollector(); private DAO dao; private Jdbi db; @Before public void setUp() throws Exception { db = dbRule.getJdbi(); db.useHandle(h -> h.execute("CREATE ALIAS custom_insert FOR " + "\"org.jdbi.v3.sqlobject.TestTimingCollector.customInsert\";")); db.setTimingCollector(timingCollector); dao = db.onDemand(DAO.class); } @Test public void testInsert() { dao.insert(1, "Brian"); dao.insert(2, "Jeff"); assertThat(timingCollector.statementNames).containsExactly("org.jdbi.v3.sqlobject.DAO.insert"); } @Test public void testInsertBatch() { dao.insertBatch(Arrays.asList(1, 2, 3), Arrays.asList("Mary", "David", "Kate")); assertThat(timingCollector.statementNames).containsOnly("org.jdbi.v3.sqlobject.DAO.insertBatch"); } @Test public void testCustomInsert() { dao.customInsert(1, "Robb"); dao.customInsert(2, "Greg"); assertThat(timingCollector.statementNames).containsOnly("org.jdbi.v3.sqlobject.DAO.customInsert"); } @Test public void testSqlQuery() { AdvancedDAO advancedDAO = db.onDemand(AdvancedDAO.class); advancedDAO.insertBatch(Arrays.asList(1, 2, 3), Arrays.asList("Mary", "David", "Kate")); String name = advancedDAO.findNameById(3); assertThat(name).isEqualTo("Kate"); assertThat(timingCollector.statementNames).containsOnly( "org.jdbi.v3.sqlobject.AdvancedDAO.insertBatch", "org.jdbi.v3.sqlobject.AdvancedDAO.findNameById"); } @Test public void testRawSql() { db.useHandle(h -> { PreparedBatch batch = h.prepareBatch("insert into something (id, name) values (?, ?)"); batch.add(1, "Mary"); batch.add(2, "David"); batch.add(3, "Kate"); batch.execute(); }); List<String> names = db.withHandle(h -> h.createQuery("select name from something order by name") .mapTo(String.class) .list()); assertThat(names).containsExactly("David", "Kate", "Mary"); assertThat(timingCollector.statementNames).containsOnly( "sql.raw.insert into something (id, name) values (?, ?)", "sql.raw.select name from something order by name"); } public static int customInsert(Connection conn, int id, String name) throws SQLException { PreparedStatement stmt = conn.prepareStatement("insert into something (id, name) values (?, ?)"); stmt.setInt(1, id); stmt.setString(2, name); return stmt.executeUpdate(); } private static class CustomTimingCollector implements TimingCollector { private final Set<String> statementNames = new HashSet<>(); private final SqlObjectStrategy statementNameStrategy = new SqlObjectStrategy(); @Override public void collect(long elapsedTime, StatementContext ctx) { statementNames.add(statementNameStrategy.getStatementName(ctx)); } } private static class SqlObjectStrategy { String getStatementName(StatementContext statementContext) { ExtensionMethod extensionMethod = statementContext.getExtensionMethod(); if (extensionMethod != null) { Class<?> type = extensionMethod.getType(); Method method = extensionMethod.getMethod(); String group = type.getPackage().getName(); String name = type.getSimpleName(); return group + "." + name + "." + method.getName(); } else { return "sql.raw." + statementContext.getRawSql(); } } } public interface DAO { @SqlUpdate("insert into something (id, name) values (:id, :name)") void insert(@Bind("id") int id, @Bind("name") String name); @SqlBatch("insert into something (id, name) values (:id, :name)") @BatchChunkSize(2) void insertBatch(@Bind("id") List<Integer> ids, @Bind("name") List<String> names); @SqlCall("call custom_insert(:id, :name)") void customInsert(@Bind("id") int id, @Bind("name") String name); } public interface AdvancedDAO extends DAO { @SqlQuery("select name from something where id = :id") String findNameById(@Bind("id") int id); } }