如果您的数据库很少更改,则可以使用数据库JDBC驱动程序随附的数据源,并在提供程序中隔离对第3方库的调用(我的示例使用H2
dataabse提供的方法,但是所有JDBC提供程序都应具有一个)。如果更改为DataSource的其他实现(例如c3PO,Apache
DBCP或由应用服务器容器提供的实现),则只需编写新的Provider实现即可从适当的位置获取数据源。在这里,我使用单例作用域来允许DataSource实例在依赖它的那些类之间共享(池化所必需)。
public class DataSourceModule extends AbstractModule { @Override protected void configure() { Names.bindProperties(binder(), loadProperties()); bind(DataSource.class).toProvider(H2DataSourceProvider.class).in(Scopes.SINGLETON); bind(MyService.class); } static class H2DataSourceProvider implements Provider<DataSource> { private final String url; private final String username; private final String password; public H2DataSourceProvider(@Named("url") final String url, @Named("username") final String username, @Named("password") final String password) { this.url = url; this.username = username; this.password = password; } @Override public DataSource get() { final JdbcDataSource dataSource = new JdbcDataSource(); dataSource.setURL(url); dataSource.setUser(username); dataSource.setPassword(password); return dataSource; } } static class MyService { private final DataSource dataSource; @Inject public MyService(final DataSource dataSource) { this.dataSource = dataSource; } public void singleUnitOfWork() { Connection cn = null; try { cn = dataSource.getConnection(); // Use the connection } finally { try { cn.close(); } catch (Exception e) {} } } } private Properties loadProperties() { // Load properties from appropriate place... // should contain definitions for: // url=... // username=... // password=... return new Properties(); }}
要处理事务,应使用“事务感知”数据源。我不建议手动执行此 *** 作。使用诸如warp-persist或容器提供的事务管理之类的东西,看起来像这样:
public class TxModule extends AbstractModule { @Override protected void configure() { Names.bindProperties(binder(), loadProperties()); final TransactionManager tm = getTransactionManager(); bind(DataSource.class).annotatedWith(Real.class).toProvider(H2DataSourceProvider.class).in(Scopes.SINGLETON); bind(DataSource.class).annotatedWith(TxAware.class).to(TxAwareDataSource.class).in(Scopes.SINGLETON); bind(TransactionManager.class).toInstance(tm); bindInterceptor(Matchers.any(), Matchers.annotatedWith(Transactional.class), new TxMethodInterceptor(tm)); bind(MyService.class); } private TransactionManager getTransactionManager() { // Get the transaction manager return null; } static class TxMethodInterceptor implements MethodInterceptor { private final TransactionManager tm; public TxMethodInterceptor(final TransactionManager tm) { this.tm = tm; } @Override public Object invoke(final MethodInvocation invocation) throws Throwable { // Start tx if necessary return invocation.proceed(); // Commit tx if started here. } } static class TxAwareDataSource implements DataSource { static ThreadLocal<Connection> txConnection = new ThreadLocal<Connection>(); private final DataSource ds; private final TransactionManager tm; @Inject public TxAwareDataSource(@Real final DataSource ds, final TransactionManager tm) { this.ds = ds; this.tm = tm; } public Connection getConnection() throws SQLException { try { final Transaction transaction = tm.getTransaction(); if (transaction != null && transaction.getStatus() == Status.STATUS_ACTIVE) { Connection cn = txConnection.get(); if (cn == null) { cn = new TxAwareConnection(ds.getConnection()); txConnection.set(cn); } return cn; } else { return ds.getConnection(); } } catch (final SystemException e) { throw new SQLException(e); } } // Omitted delegate methods. } static class TxAwareConnection implements Connection { private final Connection cn; public TxAwareConnection(final Connection cn) { this.cn = cn; } public void close() throws SQLException { try { cn.close(); } finally { TxAwareDataSource.txConnection.set(null); } } // Omitted delegate methods. } static class MyService { private final DataSource dataSource; @Inject public MyService(@TxAware final DataSource dataSource) { this.dataSource = dataSource; } @Transactional public void singleUnitOfWork() { Connection cn = null; try { cn = dataSource.getConnection(); // Use the connection } catch (final SQLException e) { throw new RuntimeException(e); } finally { try { cn.close(); } catch (final Exception e) {} } } }}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)