| この記事の要点 |
|---|
|
取得が必要なケース
通常は JPA / Spring Data でクエリは十分。低レベル Connection が欲しいのは:
- JPA で対応できないベンダ固有 SQLを実行
- 大量 INSERTでバッチ処理
- CallableStatementでストアドプロシージャ
- BLOB / CLOB のストリーム書き込み
- カーソル制御を細かく行う
方法 1: EntityManager から取得(JPA 経由、推奨)
@Service
public class MyService {
@PersistenceContext
private EntityManager em;
@Transactional
public void doSomething() throws SQLException {
// JPA トランザクション内の Connection を取得
Connection conn = em.unwrap(Connection.class);
try (PreparedStatement ps = conn.prepareStatement("SELECT 1")) {
ResultSet rs = ps.executeQuery();
// ...
}
// conn.close() しない! JPA が管理する
}
}
# 利点:
# - 同じトランザクション内で動作 (commit/rollback 連携)
# - JPA キャッシュとも整合性が保たれる
方法 2: DataSource から取得
@Service
public class MyService {
@Autowired
private DataSource dataSource;
public void doSomething() throws SQLException {
try (Connection conn = dataSource.getConnection()) {
// 独立した接続 (JPA トランザクションとは別)
try (PreparedStatement ps = conn.prepareStatement("SELECT 1")) {
ResultSet rs = ps.executeQuery();
// ...
}
}
}
}
# 注意:
# - JPA トランザクションと別の接続なので、JPA 側の未 commit データは見えない
# - 自分で close 必須
# - try-with-resources 推奨
方法 3: トランザクション内で同じ Connection を取得
@Service
public class MyService {
@Autowired
private DataSource dataSource;
@Transactional
public void doSomething() throws SQLException {
// トランザクション中なら JPA と同じ Connection が返る
Connection conn = DataSourceUtils.getConnection(dataSource);
try (PreparedStatement ps = conn.prepareStatement("SELECT 1")) {
ResultSet rs = ps.executeQuery();
// ...
}
// 必ず DataSourceUtils.releaseConnection() で解放
DataSourceUtils.releaseConnection(conn, dataSource);
}
}
# DataSourceUtils 経由なら:
# - トランザクション参加 (commit/rollback 共有)
# - close は releaseConnection で行う
方法 4: JdbcTemplate.execute(ConnectionCallback)
@Service
public class MyService {
@Autowired
private JdbcTemplate jdbcTemplate;
public void doSomething() {
jdbcTemplate.execute((ConnectionCallback<Void>) conn -> {
// この conn は JdbcTemplate が管理
try (PreparedStatement ps = conn.prepareStatement("SELECT 1")) {
ResultSet rs = ps.executeQuery();
// ...
}
return null;
});
}
}
# 利点:
# - リソース管理が自動 (close 不要)
# - JdbcTemplate の例外変換も効く
# - トランザクション統合
典型的な利用例
例 1: 大量 INSERT バッチ
@Service
public class BatchService {
@PersistenceContext
private EntityManager em;
@Transactional
public void bulkInsert(List<UserData> users) throws SQLException {
Connection conn = em.unwrap(Connection.class);
String sql = "INSERT INTO users (name, email) VALUES (?, ?)";
try (PreparedStatement ps = conn.prepareStatement(sql)) {
int count = 0;
for (UserData user : users) {
ps.setString(1, user.getName());
ps.setString(2, user.getEmail());
ps.addBatch();
if (++count % 1000 == 0) {
ps.executeBatch();
ps.clearBatch();
}
}
ps.executeBatch();
}
}
}
# JPA の persist() より圧倒的に高速 (10-50x)
例 2: ストアドプロシージャ呼び出し
@Transactional
public ProcedureResult callProcedure() throws SQLException {
Connection conn = em.unwrap(Connection.class);
try (CallableStatement cs = conn.prepareCall("{call my_procedure(?, ?)}")) {
cs.setLong(1, 123L);
cs.registerOutParameter(2, Types.VARCHAR);
cs.execute();
return new ProcedureResult(cs.getString(2));
}
}
// または JPA の StoredProcedureQuery
StoredProcedureQuery query = em.createStoredProcedureQuery("my_procedure")
.registerStoredProcedureParameter(1, Long.class, ParameterMode.IN)
.registerStoredProcedureParameter(2, String.class, ParameterMode.OUT)
.setParameter(1, 123L);
query.execute();
String result = (String) query.getOutputParameterValue(2);
例 3: 大きな BLOB のストリーミング書き込み
@Transactional
public void uploadFile(MultipartFile file) throws SQLException, IOException {
Connection conn = em.unwrap(Connection.class);
try (PreparedStatement ps = conn.prepareStatement(
"INSERT INTO files (name, content) VALUES (?, ?)")) {
ps.setString(1, file.getOriginalFilename());
ps.setBinaryStream(2, file.getInputStream(), file.getSize());
ps.executeUpdate();
}
}
トランザクション管理の理解
@Transactional
public void txAware() throws SQLException {
Connection conn1 = em.unwrap(Connection.class);
Connection conn2 = DataSourceUtils.getConnection(dataSource);
// → conn1 と conn2 は同じインスタンス (トランザクション中)
// PROPAGATION_REQUIRES_NEW で別トランザクション
anotherService.doInNewTransaction();
// → 別の Connection
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void doInNewTransaction() {
Connection conn = em.unwrap(Connection.class);
// 親と別の接続・トランザクション
}
注意点
- close() しない: JPA / Spring 管理の Connection は自動 close
- DataSource.getConnection() は close 必須: try-with-resources で確実に
- auto-commit に注意: トランザクション中は false(手動 commit 必要なし、Spring が制御)
- JPA の 1 次キャッシュとの整合性: SQL 直接実行はキャッシュをバイパス → flush() / refresh() で同期
関連記事
子ページ
子ページはありません
同階層のページ
- インストール(eclipseプラグイン)
- クイックスタート
- プロジェクトの作成
- Spring Bootプロジェクトの作成
- Spring Bootプロジェクトの実行
- Spring BootでHello World!
- アノテーション一覧
- DB接続設定からエンティティおよびリポジトリの作成、値の取得まで(JPA編)
- DB接続設定や値の取得(JdbcTemplate編)
- ビューから値をモデルに格納しコントローラーで受け取る方法
- コントローラーにてモデルに値を格納してビューに渡す方法
- テンプレートエンジン
- ModelとModelAndViewの違い
- AOPの使用方法
- classpath: 内部ファイルの読み込み
- file: 外部ファイルの読み込み
- CSVファイルアップロード方法(Ajax)
- CSVファイルダウンロード方法(Ajax)
- Spring Bootプロジェクトのビルドと本番環境へのデプロイ方法(内部tomcat使用)
- Application.propertiesの環境依存設定の分割方法
- JPAにおけるEntityManagerの取得方法
- JPAにおけるjava.sql.Connectionの取得方法
- エラー一覧
- jarの引数を受け取る方法
- Spring BootでGmailからメール送信
- 複数のDBに接続する設定(Spring Boot & JPA編)
- ポート番号の変更
- Basic認証の実装と特定のURLに限定する方法
- Spring SecurityのBasic認証の無効化
- 独自のエラーページを定義する方法
- プロパティファイルの値やjar実行時の引数を取得する方法
人気ページ
- 1 Eclipseで「サーバーに追加または除去できるリソースがありません。」の原因と対処法
- 2 tomcat の起動 / 停止ログと catalina.log・catalina.out の違い
- 3 JavaScript で base URL を取得する方法|window.location.origin
- 4 YouTube Data API v3 エラー一覧|403・400・404 の原因と対処
- 5 Laravel エラー一覧|500/Blade/DB 接続/ルーティングの代表エラー
- 6 3Dグラフィックスとは|モデリング/レンダリング/主要ソフトウェア (Blender / Maya)
- 7 Spring Frameworkのアノテーション一覧
- 8 【Spring】@Valueアノテーションとは
- 9 CATALINA_HOME の確認方法 (Linux / Mac)
- 10 【Spring】@Autowiredアノテーションとは
最近更新/作成されたページ
- プロジェクトをTomcatプロジェクトとして認識させる方法 2026-10-07 22:32:50
- MySQLの1366 Incorrect string value|Laravelの文字コード・絵文字エラー 2026-10-07 21:54:03
- curlの証明書ホスト名不一致|旧エラー51・現行60の確認と対処 2026-10-07 21:54:03
- LaravelのMassAssignmentException|fillableの原因と安全な対処 2026-10-07 21:54:03
- Eclipse で Tomcat の起動ログがコンソールに出ない時の確認手順 2026-10-07 21:54:02
- MySQLにおける中央値(Median)の導き方(バージョン8未満) 2026-10-07 13:49:45
- getInputForward 2026-10-07 13:41:15
- JSONから配列に変換 2026-10-07 13:41:15
- ビューから値をモデルに格納しコントローラーで受け取る方法 2026-10-07 13:23:41
- Laravelのテーブル作成と定義変更|マイグレーション・up/down・注意点 2026-10-07 13:23:41
- NumPy 配列に要素を追加する方法 (append / concatenate) 2026-10-07 13:23:41
- MariaDB・MySQLで現在日時を取得する方法|NOW・タイムゾーン・保存型 2026-10-07 13:13:36
- 【django】テンプレートで定数を使用する方法 2026-10-07 13:10:15
- Spring BootにおけるApplication.propertiesの環境依存設定の分割方法 2026-10-07 12:09:35
- Not supported for DML operations【Springエラー】 2026-10-07 11:09:38