Skip to main content

Benchmarks

Methodology

All benchmarks run against an in-memory DuckDB database on a single shared connection. Each library executes a SELECT returning 15 columns of varied types (VARCHAR, INTEGER, DECIMAL, DOUBLE, BOOLEAN, TIMESTAMP, DATE) and maps every row into a Kotlin data class.

  • 5 warmup runs (discarded)
  • 11 measured runs, median reported
  • Row counts verified on every run
  • All libraries share the same javax.sql.DataSource (single connection, no pooling overhead)
  • VARCHAR columns contain realistic-length strings (50-200 chars)

Results

RowsRaw JDBCFoundations JDBCHibernate (entity)Hibernate (native)JDBIJdbcTemplate
1288.5 us383.8 us775.4 us544.5 us415.2 us297.4 us
10391.3 us403.0 us1.05 ms487.6 us434.5 us294.0 us
100934.4 us1.00 ms2.20 ms1.07 ms916.0 us875.4 us
1,0006.18 ms5.79 ms9.03 ms7.36 ms6.65 ms6.41 ms
10,00054.49 ms55.15 ms64.75 ms58.60 ms55.33 ms55.69 ms
100,000569.79 ms581.46 ms687.91 ms595.33 ms582.34 ms585.63 ms

Libraries

LibraryApproach
Raw JDBCPreparedStatement + positional getInt/getString — theoretical minimum
Foundations JDBCRowCodec + Fragment.query() + Transactor
Hibernate (entity)@Entity + SessionFactory + native SQL mapped to managed entity — full ORM machinery
Hibernate (native)SessionFactory + native SQL + manual Object[] tuple mapping — lightest Hibernate usage
JDBIJdbi.create(ds) + RowMapper + withHandle
JdbcTemplateJdbcTemplate(ds) + RowMapper

Notes

  • This benchmark measures mapping overhead, not database query execution time. All libraries run the same SQL against the same in-memory DuckDB instance.
  • Hibernate (entity) uses @Entity annotation with full ORM machinery: bytecode-enhanced entity hydration, persistence context management, and dirty-checking state snapshots. This is how Hibernate is typically used in production.
  • Hibernate (native) uses createNativeQuery with Object[] tuple result and manual column mapping — the absolute lightest-weight Hibernate usage, bypassing the entire entity lifecycle.
  • DuckDB is an embedded analytical database — there is no network latency. Differences between libraries are pure framework overhead.