package com.brightgenerous.injection.jdbc; import java.sql.Connection; import java.sql.SQLException; import javax.inject.Inject; import javax.sql.DataSource; import com.brightgenerous.injection.jdbc.Transactional.Isolation; public class ThreadLocalSqlSession implements SqlSessionManager, SqlSession { private final ThreadLocal<Holder> threadLocal = new ThreadLocal<>(); @Inject private DataSource dataSource; // as SqlSessionManager @Override public boolean isManagedSessionStarted() { return isStarted(); } @Override public void startManagedSession(Isolation isolation) { start(isolation); } @Override public void commit(boolean force) { commit(); } @Override public void rollback(boolean force) { rollback(); } // as SqlSession @Override public boolean isStarted() { Holder holder = threadLocal.get(); return (holder != null) && holder.started; } @Override public void start(Isolation isolation) { Holder holder = threadLocal.get(); if (holder != null) { if (holder.connection != null) { try { if (!holder.connection.isClosed()) { throw new IllegalStateException(); } } catch (SQLException e) { throw new RuntimeException(e); } } } threadLocal.set(new Holder(true, isolation)); } @Override public Connection getConnection() { Holder holder = threadLocal.get(); if (holder == null) { return null; } if (holder.connection == null) { try { holder.connection = dataSource.getConnection(); Isolation iso = holder.isolation; if (iso != null) { Integer level = iso.getLevel(); if (level != null) { holder.connection.setTransactionIsolation(level.intValue()); } } } catch (SQLException e) { throw new RuntimeException(e); } } return holder.connection; } @Override public void commit() { Holder holder = threadLocal.get(); if (holder == null) { return; } if (holder.connection != null) { try { holder.connection.commit(); } catch (SQLException e) { throw new RuntimeException(e); } } } @Override public void rollback() { Holder holder = threadLocal.get(); if (holder == null) { return; } if (holder.connection != null) { try { holder.connection.rollback(); } catch (SQLException e) { throw new RuntimeException(e); } } } @Override public void close() { Holder holder = threadLocal.get(); if (holder == null) { return; } try { if (holder.connection != null) { try { holder.connection.close(); } catch (SQLException e) { throw new RuntimeException(e); } } } finally { threadLocal.set(null); } } private static class Holder { boolean started; Isolation isolation; Connection connection; Holder(boolean started, Isolation isolation) { this.started = started; this.isolation = isolation; } } }