【问题标题】:MyBatis-guice 3.3 + Multiple datasources + properties + scriptrunnerMyBatis-guice 3.3 + 多个数据源 + 属性 + scriptrunner
【发布时间】:2013-05-28 09:04:33
【问题描述】:

我正在使用 MyBatis-guice 3.3 连接到第一个数据库,使用 java Properties 对象和 ScriptRunner 来运行一些脚本:

Environment environment = injector.getInstance(SqlSessionFactory.class).getConfiguration().getEnvironment();
DataSource source = environment.getDataSource();
ScriptRunner runner = new ScriptRunner(source.getConnection());
runner.setLogWriter(null);
runner.setStopOnError(true);
runner.runScript(Resources.getResourceAsReader(properties.getProperty("script.dbA.create.schema")));

现在我想使用相同的方法添加第二个数据源 (dbB)。按照 MyBatis-guice 参考指南,我必须使用 2 PrivateModule。这部分工作正常。

但是我应该如何调用我的 ScriptRunner 来为 dbA 运行一些脚本,而为 dbB 运行一些其他脚本呢?

【问题讨论】:

    标签: java datasource guice mybatis


    【解决方案1】:

    创建 2 个限定符注释 @DbA 和 @DbB 或类似的。

    现在每个私有模块都会调用(通过 MyBatisModule)

    binder().bind(SqlSessionFactory.class).toProvider(SqlSessionFactoryProvider.class).in(Scopes.SINGLETON);
    

    这意味着不可能这样做

    expose(SqlSessionFactory.class).annotatedWith(DbA.class);
    

    这需要

    binder().bind(SqlSessionFactory.class).annotatedWith(DbA.class).toProvider(SqlSessionFactoryProvider.class).in(Scopes.SINGLETON);
    

    相反,您需要提供一个使用 SqlSessionFactory 注入并通过限定符注释公开的中间类。

    并且在每个私有模块中做一些事情

    bind(MyBatisEnv.class).to(MyBatisImpl.class).annotatedWith(DbX.class);
    expose(MyBatisEnv.class).annotatedWith(DbX.class);
    

    【讨论】:

    • 根据您的评论,我创建了 2 个注释 @BindingAnnotation @Retention(RetentionPolicy.RUNTIME) @interface DbA and DbB and my PrivateModule expose(SqlSessionFactory.class).annotatedWith(DbA.class)。我收到以下错误:Could not expose() SqlSessionFactory annotated with DbA, it must be explicitly bound。有什么想法吗?
    • 更新了答案,第一次写起来有点快。
    【解决方案2】:

    这里有一个解决方案。

    Injector injector = Guice.createInjector(
        new PrivateModule() {
            @Override protected void configure() {
                install(new MyBatisModule() {
                    @Override protected void initialize() {
                         bindDataSourceProviderType(BasicDataSourceProvider.class);
                         bindTransactionFactoryType(JdbcTransactionFactory.class);
                         // add all your mappers here nowhere else
                         addMapperClass(MapperA1.class);
                    }
                });
                Names.bindProperties(binder(), createProperties("dbA"));
                // expose all your mappers here
                expose(MapperA1.class);
    
                // bind&expose all db specific stuff here (SessionFactory, SessionManager, etc.)
                bind(SqlSessionFactory.class).annotatedWith(DbA.class).to(SqlSessionFactory.class);
                expose(SqlSessionFactory.class).annotatedWith(DbA.class);
        }},
        new PrivateModule() {
            @Override protected void configure() {
                install(new MyBatisModule() {
                    @Override protected void initialize() {
                         bindDataSourceProviderType(BasicDataSourceProvider.class);
                         bindTransactionFactoryType(JdbcTransactionFactory.class);
                         // add all your mappers here nowhere else
                         addMapperClass(MapperB1.class);
                    }
                });
                Names.bindProperties(binder(), createProperties("dbB"));
                // expose all your mappers here
                expose(MapperB1.class);
    
                // bind&expose all db specific stuff here (SessionFactory, SessionManager, etc.)
                bind(SqlSessionFactory.class).annotatedWith(DbB.class).to(SqlSessionFactory.class);
                expose(SqlSessionFactory.class).annotatedWith(DbB.class);
        }}
    );
    DataSource dbA dataSource = injector.getInstance(Key.get(SqlSessionFactory.class), DbA.class).getConfiguration().getEnvironment().getDataSource();
    ScriptRunner runner = new ScriptRunner(source.getConnection());
    runner.runScript(Resources.getResourceAsReader("dbA/path/create_db.sql"));
    runner.closeConnection();
    
    private static Properties createDbProperties(String schema) {
        final Properties p = new Properties();
        p.setProperty("mybatis.environment.id", "test");
        p.setProperty("JDBC.driver", "org.hsqldb.jdbcDriver");
        p.setProperty("JDBC.url", "jdbc:hsqldb:mem" + schema + ";sql.syntax_ora=true");
        p.setProperty("JDBC.username", "sa");
        p.setProperty("JDBC.password", "");
        return p;
    }
    

    【讨论】:

      【解决方案3】:

      如果有人在 GWT 平台环境中寻找解决方案,这里是来自工作环境的配置。希望这有用。

      // mybatis-dbA-config.xml
      <configuration>
      
        <settings>
          <setting name="cacheEnabled" value="false" />
          <setting name="useGeneratedKeys" value="true" />
          <setting name="defaultExecutorType" value="REUSE" />
        </settings>
      
        <typeAliases>
          <package name="com.example.domain" />
        </typeAliases>
      
        <environments default="test">
          <environment id="test">
            <transactionManager type="JDBC" />
            <dataSource type="POOLED">
              <property name="driver" value="oracle.jdbc.driver.OracleDriver" />
              <property name="url" value="jdbc:oracle:thin:@//localhost:1521/SchemaName" />
              <property name="username" value="user" />
              <property name="password" value="pwd" />
            </dataSource>
          </environment>
        </environments>
      
        <mappers>
          <mapper resource="com/example/mapper/DomainAMapper.xml" />
        </mappers>
      
      </configuration>
      
      ...
      
      //dbA Dao implementation
      public class DbADaoImpl implements DbADao {
          @Inject
          @Named("DbA")
          private SqlSession sqlSession;
      
          public List<DomainA> listDbADomains() {
              return this.sqlSession.selectList("com.example.mapper.DomainAMapper.listDomainAs");
          }
      ...
      
      //dbB Dao implementation
      public class DbBDaoImpl implements DbBDao {
          @Inject
          @Named("DbB")
          private SqlSession sqlSession;
      
          public List<DomainB> listDbBDomains() {
              return this.sqlSession.selectList("com.example.mapper.DomainBMapper.listDomainBs");
          }
      ...
      
      // Service implementation
      public class MyServiceImpl implements MyService {
        @Inject
        private DbADao aDao;
        @Inject
        private DbBDao bDao;
      
        @Transactional(isolation = Isolation.SERIALIZABLE)
        @Override
        public Boolean doBusinessStuff() {
            // use aDao.
            // use bDao.
        }
      ...
      
      // DbA Module
      public class DbAModule extends PrivateModule {
          @Override
          protected void configure() {
              install(new XMLMyBatisModule() {
                  @Override
                  protected void initialize() {
                      setEnvironmentId("test");
                      setClassPathResource("mybatis-dbA-config.xml");
      
                      useJdbcDriverClassLoaderoracle.jdbc.OracleDriver.class.getClassLoader());
                      addProperties(createTestProperties());
                  }
              });
      
              bind(SqlSession.class).annotatedWith(Names.named("DbA")).toProvider(SqlSessionManagerProvider.class).in(Scopes.SINGLETON);
              expose(SqlSession.class).annotatedWith(Names.named("DbA"));
          }
      
          protected static Properties createTestProperties() {
              final Properties myBatisProperties = new Properties();
              myBatisProperties.setProperty("mybatis.environment.id", "test");
              myBatisProperties.setProperty("JDBC.autoCommit", "false");
              return myBatisProperties;
          }
      }
      
      ...
      // DbB Module
      // identical to the above replacing DbA with DbB
      
      ...
      
      //
      // GWTP Configurations
      //
      
      //
      public class DaoServiceModule extends AbstractModule {
        @Override
        protected void configure() {
          bind(Service.class).to(ServiceImpl.class);
          bind(DbADao.class).to(DbADaoImpl.class);
          bind(DbBDao.class).to(DbBDaoImpl.class);
        }
      
      public class GuiceServletConfig extends GuiceServletContextListener {
        @Override
        protected Injector getInjector() {
          return Guice.createInjector(new ServerModule(),
              new DispatchServletModule(),
              new DbAModule(), 
              new DbAModule(),
              new DaoServiceModule());
        }
      

      【讨论】:

        猜你喜欢
        • 2016-02-28
        • 1970-01-01
        • 2011-06-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-02-12
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多