我想在学习Guice的同时创建一个示例项目,该项目使用JDBC读取/写入SQL数据库。但是,在使用Spring多年之后,让它抽象化了连接处理和事务,我正在努力从概念上进行工作。
我想要一个可以启动和停止事务并调用大量存储库的服务,这些存储库可以重用相同的连接并参与相同的事务。我的问题是:
下面的代码显示了我将如何在Spring中执行此操作。注入到每个存储库中的JdbcOperations可以访问与活动事务关联的连接。
除了显示如何为事务创建拦截器的教程以外,我还没有找到很多涵盖此内容的教程。
我对继续使用Spring感到很满意,因为它在我的项目中运行良好,但是我想知道如何在纯Guice和JBBC中做到这一点(不使用JPA / Hibernate
/ Warp / Reusing Spring)
@Service
public class MyService implements MyInterface {
@Autowired
private RepositoryA repositoryA;
@Autowired
private RepositoryB repositoryB;
@Autowired
private RepositoryC repositoryC;
@Override
@Transactional
public void doSomeWork() {
this.repositoryA.someInsert();
this.repositoryB.someUpdate();
this.repositoryC.someSelect();
}
}
@Repository
public class MyRepositoryA implements RepositoryA {
@Autowired
private JdbcOperations jdbcOperations;
@Override
public void someInsert() {
//use jdbcOperations to perform an insert
}
}
@Repository
public class MyRepositoryB implements RepositoryB {
@Autowired
private JdbcOperations jdbcOperations;
@Override
public void someUpdate() {
//use jdbcOperations to perform an update
}
}
@Repository
public class MyRepositoryC implements RepositoryC {
@Autowired
private JdbcOperations jdbcOperations;
@Override
public String someSelect() {
//use jdbcOperations to perform a select and use a RowMapper to produce results
return "select result";
}
}
如果您的数据库很少更改,则可以使用数据库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) {}
}
}
}
}
主要内容:1. 导入JDBC包,2. 注册JDBC驱动程序,数据库URL配置,创建连接对象,使用具有用户名和密码的数据库URL,关闭JDBC连接安装相应的驱动程序后,现在是时候来学习使用JDBC建立数据库连接了。 建立JDBC连接所涉及的编程相当简单。 以下是基本的四个步骤 - 导入JDBC包:使用Java语言的语句在Java代码开头位置导入所需的类。 注册JDBC驱动程序:使JVM将所需的驱动程序实现加载到内存中,从而可以满足JDBC请求。 数据库URL配置:创建一个正确格式化的地址,指向要连
我使用作为我的数据源实现,我的代码获取连接并关闭连接,如下所示: 当我完成连接工作时,我将关闭它 我的问题是:确实是关闭的,所以当连接像一样关闭时,数据源是如何工作的。我听说datasource connection close并不是真正的close,只是release,但我在datasource类中找不到release API。我想知道datasource如何管理数据库连接的创建、关闭和释放。
我正在尝试一个程序来检查与oracle数据库的连接,如下所示 但在eclipse中运行之后,它显示了以下异常。 JAVAsql。SQLException:Listener拒绝了连接,出现以下错误:ORA-12505,TNS:Listener当前不知道连接描述符中给出的SID 请帮助我,我是oracle数据库的新手。
我们正在用Java重写来自PHP的web应用程序。我认为,但我不是很确定,我们可能会在连接池方面遇到问题。应用程序本身是多租户的,是“独立数据库”和“独立模式”的组合。 对于每个Postgres数据库服务器实例,可以有一个以上的数据库(命名为schemax_XXX),其中包含一个以上的模式(模式是租户)。注册时,可能会发生以下两种情况之一: 在编号最高的schema_XXX数据库中创建新的租户模式
我在oracle DB中创建了示例表,如下所示 和从java插入的值如下所示 亚洲/加尔各答的JVM时区。我使用SQL developer查询数据。我只是想澄清我的理解 我在下面的文章中提到了,但我的观察看起来完全不同。http://brian.pontarelli.com/2011/08/16/时区数据库处理/
我是wordpress的新手,在管理数据库方面有困难。我已经安装了“管理员”插件来管理数据库。我已经创建了一个名为“usersupp_admin”的新表。现在我还创建了一个自定义模板,该模板将使用PDO语句连接到此数据库,现在的问题是在哪里可以获取主机、数据库名、用户和密码?以下是代码: 任何帮助都将不胜感激。