web-dev-qa-db-fra.com

Quelle est la différence entre JDBC et JDBI?

Je souhaite connaître les différences entre JDBC et JDBI en Java. En particulier, lequel est généralement meilleur et pourquoi?

34

(Je suis l'auteur principal de jDBI)

jDBI est une bibliothèque pratique construite sur JDBC . JDBC fonctionne très bien, mais semble généralement optimiser pour les fournisseurs de bases de données (auteurs de pilotes) par rapport aux utilisateurs. jDBI tente d'exposer la même fonctionnalité, mais dans une API optimisée pour les utilisateurs. 

C'est beaucoup plus bas que des choses comme Hibernate ou JPA . La bibliothèque similaire la plus proche est probablement MyBatis (successeur bifide de iBATIS ).

jDBI prend en charge deux API de style, un style ancien et fluide, qui ressemble à ceci:

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

Une nouvelle API SQL Object est beaucoup plus réfléchissante et commence vraiment à faire abstraction de nombreux éléments JDBC:

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);
}

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

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

    Something martin = dao.findById(7);
}

La bibliothèque possède de bons documents de référence (javadoc) et une documentation de style tutoriel raisonnable sur http://jdbi.org/ . Il existe depuis 2004 et est utilisé par un nombre relativement restreint de personnes (quelques dizaines de personnes que je connais personnellement et peut-être une douzaine de sociétés), mais cela fonctionne très bien pour elles. La plupart des gens qui y travaillent sont des gens d'A + et sont principalement concernés par la construction d'un outil qui fonctionne bien pour eux - le fait qu'il soit open source est en grande partie un effet secondaire.

87
brianm

Voulez-vous dire http://jdbi.codehaus.org/ ?

jDBI est conçu pour fournir un accès pratique aux données sous forme de tableaux en Java (tm). Il utilise la structure de collections Java pour les résultats de la requête, fournit un moyen commode d’externaliser les instructions SQL et fournit une prise en charge des paramètres nommés pour toute base de données utilisée.

JDBI utilise JDBC, si vous ne savez pas si vous avez besoin de JDBI, je vous suggère de ne pas l'utiliser.

8
Peter Lawrey

JDBC est une norme établie de longue date utilisée en Java pour accéder aux bases de données SQL. Les fournisseurs de base de données implémentent un pilote JDBC afin que toutes les bases de données soient accessibles de manière uniforme. Pratiquement tout ce qui est fait avec les bases de données en Java utilise JDBC.

JDBI semble être une sorte de couche d'abstraction au-dessus de JDBC, mais c'est difficile à dire car il est peu documenté Ce n'est certainement pas largement utilisé et c'est la première fois que j'en entends parler.

7
Michael Borgwardt

jDBI est construit sur JDBC. Toutes les applications Java utilisent JDBC pour accéder à des bases de données relationnelles. Ce n'est donc pas un choix. Ils sont complémentaires. Vous ne pouvez pas utiliser jDBI sans JDBC.

Cela dit, jDBI est la tentative d'une autre personne de libérer les développeurs Java du standard requis par JDBC. C'est comme choisir Hibernate, TopLink ou iBatis.

5
duffymo

En effet, JDBI est construit sur JDBC. En fait, vous utiliserez probablement JDBC pour accéder à la base de données, et JDBI sera celui qui englobera (ou encapsulera) JDBC pour exécuter les déclarations PreparedStatements sur la base de données.

En interne, le pilote JDBC est celui qui exécute la transaction, JDBI ne fonctionne que comme intermédiaire.

Il est plus léger qu'un ORM (comme Hibernate ou Spring), mais il aide vraiment à accélérer le développement et à avoir encore plus, "Nice and clean", car il dispose de nombreux utilitaires pour rendre le codage plus facile et plus propre, par exemple:

Pour définir un objet simple pour insérer/lire une table, procédez comme suit:

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);

    @SqlQuery("SELECT LOCATIONID, NAME, COUNTRY, CREATEDON FROM pocAgent WHERE LOCATIONID = :LocationId")
    @Mapper(AgentMapper.class)
    Agent getAgentByLocation(@Bind("LocationId") String locationId);

    void close();    
}

JDBI vous donne la possibilité d'avoir toutes les logiques de mappage au même endroit, telles que:

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> {
    @Override
    public Agent map(int index, ResultSet r, StatementContext ctx) throws SQLException {
        return new Agent(r.getString("LocationId"),
                r.getString("Name"),
                r.getString("Country"),
                r.getDate("CreatedOn"));
    }
}

Et puis, il vous suffit d’utiliser le 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;

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

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

    @org.skife.jdbi.v2.sqlobject.Transaction
    public Agent insertAgent(String locationId, String name, String country) {
        openConnection();
        Agent agent = _daoHandler.getAgentByLocation(locationId);
        if (agent == null) {
            _daoHandler.insertAgent(locationId, name, country);
        }
        agent = _daoHandler.getAgentByLocation(locationId);
        _daoHandler.commit();
        return agent;
    }
}

Ensuite, si nous allons un peu plus loin et que nous vérifions comment la connexion est établie avec la base de données, vous remarquerez que, pour cet exemple de validation du concept, JDBC est utilisé:

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;

    @Inject
    TandemMPConnectionHelper() {
        try {
            Class.forName("com.tandem.t4jdbc.SQLMXDriver");
        } catch (ClassNotFoundException e) {
            System.out.println(e.toString());
        }
        _dataSource = setupDataSource("jdbc:t4sqlmx://<server>:<port>/:<username>:<password>:", "user1", "password1");
    }

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

    @Override
    public DataSource getDataSource() {
        return _dataSource;
    }

    @Override
    public Connection getConnection() {
        Connection connection;
        try {
            connection = _dataSource.getConnection();
            connection.setAutoCommit(false);
        } catch (SQLException e) {
            System.out.println(e.getMessage());
            return null;
        }
        return connection;
    }
}

Dans ce cas, j'atteins une base de données Tandem Non/Stop, mais le même fonctionne pour SQL Server, Oracle, ou quelle que soit la base de données que vous atteignez, vous avez juste besoin du pilote JDBC correct ( que vous pouvez trouver facilement, juste Google il! ).

J'espère que cela vous donnera une idée plus claire de l'emplacement conceptuel de JDBI et JDBC dans votre code.

4
Marco Vargas

J'ai trouvé jDBI quand je recherche des paramètres nommés SQL. J'utilise le concurrent connu Spring JDBC NamedTemplate, mais a des dépendances étranges pour 8-10MB. J'ai déjà une dépendance à ANTLR.

Je regarde depuis quelques heures, jDBI semble inspirant. Les deux (jDBI/Spring JDBC) peuvent être comparés dans une certaine mesure avec un ORM léger comme iBatis/MyBatis, etc.

0
Jacek Cz