What is the difference between JDBC and JDBI?

I want to know about the differences between JDBC and JDBI in java. In particular, which one is generally better and why?


(I am the primary author of jDBI)

jDBI is a convenience library built on top of JDBC. JDBC works very well but generally seems to optimize for the database vendors (driver writers) over the users. jDBI attempts to expose the same functionality, but in an API optimized for users.

It is much lower level than things like Hibernate or JPA. The closest similar library is probably MyBatis (forked successor to iBATIS).

jDBI supports two style APIs, an older fluent style, which looks like:

List<Something> r = h.createQuery("select * from something where name = :name and id = :id")
                .bind(0, "eric")
                .bind("id", 1)

A newer SQL Object API does much more reflective type stuff and really does start to abstract a bunch of JDBC stuff:

interface TheBasics
    @SqlUpdate("insert into something (id, name) values (:id, :name)")
    int insert(@BindBean Something something);

    @SqlQuery("select id, name from something where id = :id")
    Something findById(@Bind("id") long id);

public void useTheBasics() throws Exception
    TheBasics dao = dbi.onDemand(TheBasics.class);

    dao.insert(new Something(7, "Martin"));

    Something martin = dao.findById(7);

The library has good reference docs (javadoc) and some reasonable tutorial style documentation at http://jdbi.org/. It has been around since 2004, and is used by a relatively small number of folks (some few dozen people I know of personally, and maybe a dozen companies) but it works very well for them. Most of the folks who work on it are A+ folks, and are primarily concerned with building a tool that works well for them -- that it is open source is largely a side effect.

Do you mean http://jdbi.codehaus.org/ ?

jDBI is designed to provide convenient tabular data access in Java(tm). It uses the Java collections framework for query results, provides a convenient means of externalizing sql statements, and provides named parameter support for any database being used.

JDBI uses JDBC, if you don't know if you need JDBI, I would suggest you don't use it.

JDBC is a long-established standard used in Java to access SQL databases. DB Vendors implement a JDBC driver so that all DBs can be accessed in a uniform manner. Practically everything done with databases in Java uses JDBC.

JDBI seems to be some sort of abstraction layer on top of JDBC, but it's hard to tell since it's poorly documented. It's certainly not widely used and this is the first time I've heard of it.

jDBI is built on top of JDBC. All Java applications use JDBC to access relational databases, so it's not an either/or choice. They're complimentary. You can't use jDBI without JDBC.

With that said, jDBI is another person's attempt to relieve Java developers from the boilerplate required by JDBC. It's like choosing Hibernate or TopLink or iBatis.

Indeed, JDBI is built on top of JDBC, actually, most likely you will use JDBC to reach the DB, and JDBI will be the one that embraces(or wrapped) JDBC to get the PreparedStatements executed against the DB.

Internally, the JDBC Driver is the one that executes the transaction, JDBI just works as an Intermediary.

It's lighter than an ORM (like Hibernate or Spring), but it really helps to speed up development and have everything more, "nice and clean", since it has a lot of utilities to make coding easier and cleaner, for example:

To define a simple object to insert/read a table, you can do it like this:

import com.sql.poc.data.jDBI.map.AgentMapper;
import com.sql.poc.domain.Agent;
import org.skife.jdbi.v2.sqlobject.Bind;
import org.skife.jdbi.v2.sqlobject.SqlQuery;
import org.skife.jdbi.v2.sqlobject.SqlUpdate;
import org.skife.jdbi.v2.sqlobject.customizers.Mapper;
import org.skife.jdbi.v2.sqlobject.mixins.Transactional;

public interface SqlObjectDataAccess extends Transactional<SqlObjectDataAccess> {

    @SqlUpdate("INSERT INTO pocAgent (LocationId, Name, Country) VALUES (:id, :name, :country)")
    void insertAgent(@Bind("id") String locationId,
                     @Bind("name") String name,
                     @Bind("country") String country);

    Agent getAgentByLocation(@Bind("LocationId") String locationId);

    void close();    

JDBI gives you the facility to have all mapping logic in the same place, such as:

import com.sql.poc.domain.Agent;
import org.skife.jdbi.v2.StatementContext;
import org.skife.jdbi.v2.tweak.ResultSetMapper;
import java.sql.ResultSet;
import java.sql.SQLException;

public class AgentMapper implements ResultSetMapper<Agent> {
    public Agent map(int index, ResultSet r, StatementContext ctx) throws SQLException {
        return new Agent(r.getString("LocationId"),

And then you just need to use the DAO (Data Access Object):

import com.google.inject.Inject;
import com.sql.poc.IConnectionHelper;
import com.sql.poc.domain.Agent;
import org.skife.jdbi.v2.DBI;
import org.skife.jdbi.v2.logging.Log4JLog;

public class SqlObjectRepository {
    IConnectionHelper _connectionHelper;
    DBI _dbiInstance;
    SqlObjectDataAccess _daoHandler;

    SqlObjectRepository() {
        _dbiInstance = new DBI(_connectionHelper.getDataSource());
        _dbiInstance.setSQLLog(new Log4JLog());

    public void openConnection() {
        if (_daoHandler == null)
            _daoHandler = _dbiInstance.open(SqlObjectDataAccess.class);

    public Agent insertAgent(String locationId, String name, String country) {
        Agent agent = _daoHandler.getAgentByLocation(locationId);
        if (agent == null) {
            _daoHandler.insertAgent(locationId, name, country);
        agent = _daoHandler.getAgentByLocation(locationId);
        return agent;

Then, if we go a bit deeper, and check how the Connection is done to the DB, you will notice that, for this Proof of Concept sample JDBC is used:

import com.google.inject.Inject;
import com.sql.poc.IConnectionHelper;
import org.apache.commons.dbcp.ConnectionFactory;
import org.apache.commons.dbcp.DriverManagerConnectionFactory;
import org.apache.commons.dbcp.PoolableConnectionFactory;
import org.apache.commons.dbcp.PoolingDataSource;
import org.apache.commons.pool.impl.GenericObjectPool;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;

public class TandemMPConnectionHelper implements IConnectionHelper {
    private final DataSource _dataSource;

    TandemMPConnectionHelper() {
        try {
        } catch (ClassNotFoundException e) {
        _dataSource = setupDataSource("jdbc:t4sqlmx://<server>:<port>/:<username>:<password>:", "user1", "password1");

    public DataSource setupDataSource(String connectURI, String userName, String password) {
        GenericObjectPool connectionPool = new GenericObjectPool();
        ConnectionFactory connectionFactory = new DriverManagerConnectionFactory(
        new PoolableConnectionFactory(connectionFactory, connectionPool, null, null, false, false);
        return new PoolingDataSource(connectionPool);

    public DataSource getDataSource() {
        return _dataSource;

    public Connection getConnection() {
        Connection connection;
        try {
            connection = _dataSource.getConnection();
        } catch (SQLException e) {
            return null;
        return connection;

In this case, I'm reaching a Tandem Non/Stop database, but the same works for SQL Server, ORACLE, or whatever db you are reaching, you just need the correct JDBC Driver (that you can find easily, just Google it!).

Hope it give you a clearer idea where, conceptually, locate JDBI and JDBC in your code.

I found jDBI when i search named SQL parameters. I use known competitor Spring JDBC NamedTemplate, but has strange dependencies for 8-10MB. I have already dependency to ANTLR.

I look since few hours, jDBI seems inspiring. Both (jDBI/Spring JDBC) can be compared to some degree with light ORM like iBatis/MyBatis etc.

Need Your Help

count occurrences of elements

scala list haskell dictionary list-comprehension

Counting all elements in a list is a one-liner in Haskell:

Format a date using the new date time API

java datetime java-8 java-time

I was playing with the new date time API but when running this: