Javaでの [〜#〜] jdbc [〜#〜] と [〜#〜] jdbi [〜#〜] の違いについて知りたい。特に、どちらが一般的により良いのか、そしてその理由は?
(私はjDBIの主要著者です)
jDBI は [〜#〜] jdbc [〜#〜] の上に構築された便利なライブラリです。 JDBCは非常にうまく機能しますが、一般的にはユーザーよりもデータベースベンダー(ドライバー作成者)向けに最適化されているようです。 jDBIは同じ機能を公開しようとしますが、ユーザー向けに最適化されたAPIを使用します。
Hibernate や [〜#〜] jpa [〜#〜] などよりもはるかに低いレベルです。最も近い類似のライブラリは、おそらく MyBatis ( iBATIS の後継フォーク)です。
jDBIは、次のような古いFluentスタイルの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年以来あり、比較的少数の人々(私が個人的に知っている数十人、そしておそらく12の会社)によって使用されていますが、彼らにとって非常にうまく機能します。それに取り組んでいるほとんどの人々はA +の人々であり、主に彼らのためにうまく機能するツールの構築に関心があります-オープンソースであることは主に副作用です。
http://jdbi.codehaus.org/ ですか?
jDBIは、Java(tm)で便利な表形式のデータアクセスを提供するように設計されています。クエリ結果にJavaコレクションフレームワークを使用し、SQLステートメントを外部化する便利な手段を提供し、使用されているデータベースに名前付きパラメーターサポートを提供します。
JDBIはJDBCを使用します。JDBIが必要かどうかわからない場合は、使用しないことをお勧めします。
JDBCは、SQLデータベースにアクセスするためにJavaで使用されている古くからある標準です。 DBベンダーはJDBCドライバを実装しているため、すべてのDBに統一された方法でアクセスできます。 Javaのデータベースで行われる実際にはすべてJDBCを使用します。
JDBIは、JDBCの上のある種の抽象化レイヤーのようですが、十分に文書化されていないため、判別が困難です。それは確かに広く使われているわけではなく、私がそれを聞いたのはこれが初めてです。
jDBIはJDBCの上に構築されています。すべてJavaアプリケーションは、JDBCを使用してリレーショナルデータベースにアクセスするため、どちらかまたは両方の選択肢ではありません。これらは補完的なものです。JDBCなしでjDBIを使用することはできません。
そうは言っても、jDBIは、JDBCが必要とする定型文からJava開発者を解放するための別の人の試みです。これは、HibernateまたはTopLinkまたはiBatisを選択するようなものです。
実際、JDBIはJDBCの上に構築されており、実際には、JDBCを使用してDBに到達します。JDBIは、JDBCを包含(またはラップ)して、DBに対してPreparedStatementsを実行します。
内部的には、JDBCドライバーはトランザクションを実行するものであり、JDBIは単に仲介者として機能します。
これはORM(HibernateやSpringなど)よりも軽量ですが、コーディングを簡単かつクリーンにするためのユーティリティがたくさんあるので、開発を高速化し、「Nice and clean」などのすべてを実現するのに役立ちます。
テーブルを挿入/読み取る単純なオブジェクトを定義するには、次のようにします。
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、または到達しているどのdbでも同じように機能し、正しいJDBCドライバー(簡単に見つけることができますが、グーグルだけ!)。
概念的には、コード内でJDBIとJDBCをどこに配置するかがより明確になることを願っています。
すでに回答したほとんどの人と同様に、JDBI
はJDBC
の上にある便利なライブラリであり、特にユーザーフレンドリーではなく、ほとんどのアプリケーションにとって低レベルです。
私の個人的な経験から、JDBI
は、本格的なORMと自分で行うすべてのJDBCの中間に位置しています。つまり、制御(SQLを簡単に調整できます)と利便性(JDBC
に比べて生産性が劇的に向上します)の間でバランスをとることにより、平均的な開発者が必要とする可能性のあるものの95%をカバーします。
もちろん、絵は千の言葉に値します。これは、行をフェッチし、JDBI
を使用してオブジェクト階層に変換するDAOメソッドです。
@Override
public Widget fetchWidget(String widgetGuid) {
Widget widget = jdbi.withHandle(
handle -> {
return handle.createQuery(
"SELECT guid, x AS p_x, y AS p_y, width, height, zindex FROM widget WHERE guid = :widgetGuid"
).bind("widgetGuid", widgetGuid)
.registerRowMapper(ConstructorMapper.factory(Widget.class))
.mapTo(Widget.class)
.one();
}
);
return widget;
}
JDBC
で同じことを行うことを想像してみてください-実行可能ですが、とても退屈です...そしてJDBI
はそれよりもはるかに多くのことができます-たとえば、SqlObject
APIを確認してください。
名前付きSQLパラメータを検索すると、jDBIが見つかりました。私は既知の競合他社のSpring JDBC NamedTemplateを使用していますが、8〜10MBの奇妙な依存関係があります。私はすでにANTLRに依存しています。
私は数時間から見ています、jDBIは刺激的です。両方(jDBI/Spring JDBC)は、iBatis/MyBatisなどの軽いORMである程度比較できます。