JavaでのJDBCとJDBIの違いについて知りたいです。特に、一般的にどちらが優れているのか、そしてその理由は何ですか?
7 に答える
(私は jDBI の主な作成者です)
jDBIは、 JDBCの上に構築された便利なライブラリです。JDBC は非常にうまく機能しますが、一般的に、ユーザーよりもデータベース ベンダー (ドライバー ライター) 向けに最適化されているようです。jDBI は同じ機能を公開しようとしますが、ユーザー向けに最適化された API を使用します。
HibernateやJPAなどよりもはるかに低いレベルです。最も近い同様のライブラリは、おそらくMyBatis ( iBATISのフォークされた後継) です。
jDBI は 2 つのスタイル API をサポートしています。これは古い流暢なスタイルで、次のようになります。
List<Something> r = h.createQuery("select * from something where name = :name and id = :id")
.bind(0, "eric")
.bind("id", 1)
.map(Something.class)
.list();
新しい SQL オブジェクト API は、より多くのリフレクション型の処理を行い、実際に一連の 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);
}
このライブラリには、優れたリファレンス ドキュメント (javadoc) と、適切なチュートリアル スタイルのドキュメントがhttp://jdbi.org/にあります。これは 2004 年から存在しており、比較的少数の人々 (私が個人的に知っている数十人、おそらく十数社の企業) によって使用されていますが、非常にうまく機能しています。それに取り組んでいる人々のほとんどは A+ の人々であり、主に彼らにとってうまく機能するツールを構築することに関心があります。それがオープンソースであることは、主に副作用です。
https://jdbi.org のことですか?
jDBI は、Java(tm) で便利な表形式のデータ アクセスを提供するように設計されています。クエリ結果に Java コレクション フレームワークを使用し、SQL ステートメントを外部化する便利な手段を提供し、使用されているデータベースに対して名前付きパラメーターのサポートを提供します。
JDBI は JDBC を使用します。JDBI が必要かどうかわからない場合は、使用しないことをお勧めします。
JDBC は、Java で SQL データベースにアクセスするために使用される、長い間確立された標準です。DB ベンダーは JDBC ドライバーを実装して、すべての DB に均一な方法でアクセスできるようにします。Java でデータベースを操作する場合、実際にはすべて JDBC を使用します。
JDBI は、JDBC の上にあるある種の抽象化レイヤーのように見えますが、文書化が不十分なため、見分けるのは困難です。確かにあまり使われていませんし、初めて聞きました。
jDBI は JDBC の上に構築されています。すべての Java アプリケーションは JDBC を使用してリレーショナル データベースにアクセスするため、どちらか一方しか選択できません。無料です。JDBC なしで jDBI を使用することはできません。
そうは言っても、jDBI は、Java 開発者を JDBC に必要なボイラープレートから解放しようとする別の人物の試みです。Hibernate、TopLink、または iBatis を選択するようなものです。
実際、JDBI は JDBC の上に構築されています。実際、ほとんどの場合、JDBC を使用して DB にアクセスします。JDBI は、JDBC を包含 (またはラップ) して、DB に対して PreparedStatements を実行するものになります。
内部的には、JDBC ドライバーはトランザクションを実行するドライバーであり、JDBI は単に仲介者として機能します。
ORM (Hibernate や Spring など) よりも軽量ですが、コーディングをより簡単かつクリーンにするための多くのユーティリティがあるため、開発をスピードアップし、すべてを「素晴らしくクリーン」にするのに本当に役立ちます。次に例を示します。
テーブルを挿入/読み取る単純なオブジェクトを定義するには、次のようにします。
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 は、次のようなすべてのマッピング ロジックを同じ場所に配置する機能を提供します。
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"));
}
}
そして、DAO (データ アクセス オブジェクト) を使用する必要があります。
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;
}
}
次に、もう少し深く掘り下げて、DB への接続がどのように行われるかを確認すると、この概念実証のサンプルでは JDBC が使用されていることがわかります。
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;
}
}
この場合、Tandem Non/Stop データベースに到達していますが、SQL Server、ORACLE、または到達しているデータベースでも同じように機能します。正しい JDBC ドライバーが必要なだけです (簡単に見つけることができます。Google で検索してください!)。
概念的に、コード内で JDBI と JDBC を配置する場所がより明確になることを願っています。
名前付き SQL パラメータを検索すると、jDBI が見つかりました。私は既知の競合他社の Spring JDBC NamedTemplate を使用していますが、8 ~ 10 MB の奇妙な依存関係があります。私はすでにANTLRに依存しています。
数時間前から見ていますが、jDBI は刺激的なようです。両方 (jDBI/Spring JDBC) は、iBatis/MyBatis などの軽い ORM とある程度比較できます。