gpt4 book ai didi

java - MyBatis Guice 中 MyBatis XML 多环境等价物

转载 作者:行者123 更新时间:2023-11-30 10:53:41 26 4
gpt4 key购买 nike

我正在编写一项服务,该服务需要根据上下文(一个简单的字符串标签)使用不同的数据库。每个数据库都有完全相同的模式。数据库列表是动态的。

浏览MyBatis-Guice documentation on multiple data sources ,该示例是预先知道数据源列表的地方,并且每个数据源都有不同的映射器。同样,发现一个问题here on SO假设相同的要求。

如前所述,我的要求更具动态性和流动性。这个想法是将所有当前已知的数据库(及其连接信息)放在一个配置中,并在服务启动时对其进行解析。然后,根据任何传入请求的上下文,代码应该为正确的数据库提取 SqlSessionFactory。使用该 SqlSessionFactory 的所有下游代码完全相同 - 即不依赖于请求上下文。这意味着无论需要什么数据库,都使用相同的映射器。

诚然,我对 MyBatis 和 Guice 的了解非常新且有限。但是,我无法用谷歌搜索任何显示 MyBatis-Guice 等同于 multiple environment approach supported by the XML configuration 的内容。 MyBatis 的。

最佳答案

我想出了一个适合我的解决方案,所以我想在这里分享它。使用 Guice 的决定已经做出,因此没有回旋余地。

首先,我编写了一个用于注册单个数据源的 MyBatis Guice 模块。这是一个PrivateModule这样所有为一个数据源注册的 MyBatis 类就不会与其他数据源的其他注册冲突。它使用内部 MyBatisModule 实现,因为 Java 不支持多重继承。这意味着我们不能做public class MyMyBatisModule extends PrivateModule, MyBatisModule {...}

public class MyMyBatisModule extends PrivateModule {

private final String datasourceLabel;
private final Properies datasourceProperties;
private List< Key<?> > exposedKeys = new ArrayList< Key<?> >();

public MyMyBatisModule( String datasourceLabel, Properties datasourceProperties ) {

this.datasourceLabel = datasourceLabel;
this.datasourceProperties = datasourceProperties;
}

@Override
protected void configure() {

install( new InternalMyMyBatisModule( ) );

for( Key<?> key: keys ) {
expose( key );
}
}

private class InternalMyMyBatisModule extends MyBatisModule {

@Override
protected void initialize( ) {

environmentId( datasourceLabel );
Names.bindProperties( binder(), properties );

install( JdbcHelper.MySQL ); // See JDBC Helper commentary below

bindDataSourceProviderType( C3p0DataSourceProvider.class ); // Choose whichever one you want
bindTransactionFactoryType( JdbcTransactionFactory.class );

// Register your mapper classes here. These mapper classes will have their
// keys exposed from the PrivateModule
//
// i.e.
//
// keys.add( registerMapper( FredMapper.class );
// kets.add( registerMapper( GingerMapper.class );
}

private <T> Key<T> registerMapper( Class<T> mapperClass ) {
Key<T> key = Key.get( mapperClass, Names.named( datasourceLabel ) );
bind( key ).to( mapperClass );
addMapperClass( mapperClass );
return key;
}
}
}

JdbcHeler.MySQL:我使用 JdbcHelper.MySQL 作为将属性映射到连接字符串的快捷方式,并使用 com.mysql.jdbc。 Driver 作为 JDBC 驱动程序。它声明为:

MySQL("jdbc:mysql://${JDBC.host|localhost}:${JDBC.port|3306}/${JDBC.schema}", "com.mysql.jdbc.Driver"),

现在是注册所有数据源的时候了。 MyBatisModules 为我们处理这个。它需要 datasourceLabel 到 jdbc 属性的映射。

public class MyBatisModules extends AbstractModule {

private Map< String, Properties > connectionsProperties;

public MyBatisModules( Map< String, Properties > = new HashMap< String, Properties > connectionsProperties ) {
this.connectionsProperties = connectionsProperties; // consider deep copy if appropriate
}

@Override
protected void configure( ) {

for( Entry< String, Properties > datasourceConnectionProperties : this.connectionsProperties.entrySet() ) {
install( new MyMyBatisModule( datasourceConnectionProperties.getKey(), datasourceConnectionProperties.getValue() ) );
}

bind( MapperRetriever.class ); // See MapperRetriever later

// bind your DAO classes here. By wrapping MyBatis Mapper use in DAO implementations, theoretically we
// can fairly easily change from MyBatis to any other database library just by changing the DAO implementation.
// The rest of our codebase would remain the same.
//
// i.e.
//
// bind( FredDao.class ).to( FredDaoMyBatis.class );
// bind( GingerDao.class).to( GingerDaoMyBatis.class );
}
}

现在我们只需要一些方法来获得正确的 Mapper 类(它本身与正确的数据源相关联)。为此,我们实际上需要在 Guice Injector 上调用一个方法。我不太喜欢传递它的想法,所以我将它包装在 MapperRetriever 中。您需要为每个 Mapper 实现一个检索方法。

public class MapperRetriever {

private final Injector injector;

@Inject
public MapperRetriver( Injector injector ) {
this.injector = injector;
}

// The follwing two methods use the example Mappers referenced in the MyMyBatisModule implementation above

public FredMapper getFredMapper( String datasourceLabel ) {
return this.injector.getInstance( Key.get( FredMapper.class, Names.named( datasourceLabel ) ) );
}

public GingerMapper getGingerMapper( String datasourceLabel ) {
return this.injector.getInstance( Key.get( GingerMapper.class, Names.named( datasourceLabel ) ) );
}
}

还有一个示例 DAO 实现 ...

public interface FredDao {
Fred selectFred( String datasourceLable, String fredId );
}

public class FredDaoMyBatis implements FredDao {

private MapperRetriever mapperRetriever;

@Inject
public FredDaoMyBatis( MapperRetriever mapperRetriever ) {
this.mapperRetriever = mapperRetriever;
}

@Override
public Fred selectFred( String datasourceLabel, String fredId ) {
FredMapper fredMapper = this.mapperRetriever.getFredMapper( datasourceLabel );
return fredMapper.getFred( fredId );
}
}

关于java - MyBatis Guice 中 MyBatis XML 多环境等价物,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33917115/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com