首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用spring-data-couchbase的多租户

使用spring-data-couchbase的多租户
EN

Stack Overflow用户
提问于 2018-10-15 22:15:28
回答 1查看 293关注 0票数 2

背景

我正在构建一个具有多个couchbase存储桶的spring应用程序。主存储桶包含有关其他租户配置的数据,而其余的存储桶特定于租户/客户,并共享相同的DAOs和服务。

问题

我想在租户特定的存储桶中保存/检索文档,但Spring data couchbase本质上是静态的,不允许将存储桶动态绑定到存储库,也不允许在运行时在存储桶之间切换。在spring data couchbase中,有没有办法动态地将存储桶映射/绑定到存储库?

配置

我正在初始化3个租户模板,将主模板设置为默认值,并希望在运行时基于租户在其他2个之间切换。

代码语言:javascript
复制
@Configuration
@EnableCouchbaseRepositories(basePackages = {"com.user"})
@EnableCouchbaseAuditing
public class CouchbaseMultiBucketConfig extends AbstractCouchbaseConfiguration {

private static final String ACCESS_FAILED = "Failed to access bucket template: ";

@Value("${bucket.master.name}")
private String masterBucketName;
@Value("${bucket.master.password}")
private String masterBucketPassword;
@Value("${bucket.master.host:#{null}}")
private String masterBucketHost;

@Value("${bucket.tenant1.name}")
private String tenant1BucketName;
@Value("${bucket.tenant1.password}")
private String tenant1BucketPassword;
@Value("${bucket.tenant1.host:#{null}}")
private String tenant1BucketHost;

@Value("${bucket.tenant2.name}")
private String tenant2BucketName;
@Value("${bucket.tenant2.password}")
private String tenant2ucketPassword;
@Value("${bucket.tenant2.host:#{null}}")
private String tenant2ucketHost;

@Value("${cb.hosts}")
private String hosts;

@Bean
@Qualifier("tenant1")
public Bucket tenant1Bucket() {
    return openBucket(tenant1BucketName, tenant1BucketPassword, tenant1BucketHost);
}

@Bean
@Qualifier("tenant2")
public Bucket tenant1Bucket() {
    return openBucket(tenant2BucketName, tenant2BucketPassword, tenant2BucketHost);
}

@Bean
@Qualifier("master")
public Bucket masterBucket() {
    return openBucket(masterBucketName, masterBucketPassword, masterBucketHost);
}

@Bean
@Qualifier("masterTemplate")
public CouchbaseTemplate masterTemplate() {
    try {
        final CouchbaseTemplate template = new CouchbaseTemplate(
                couchbaseClusterInfo(), //reuse the default bean
                masterBucket(), //the bucket is non-default
                mappingCouchbaseConverter(), translationService() //default beans here as well
        );
        template.setDefaultConsistency(getDefaultConsistency());
        return template;
    } catch (Exception ex) {
        throw new IllegalStateException(ACCESS_FAILED, ex);
    }
}

@Bean
@Qualifier("tenant1Template")
public CouchbaseTemplate tenant1Template() {
    try {
        final CouchbaseTemplate template = new CouchbaseTemplate(
                couchbaseClusterInfo(), //reuse the default bean
                tenant1Bucket(), //the bucket is non-default
                mappingCouchbaseConverter(), translationService() //default beans here as well
        );
        template.setDefaultConsistency(getDefaultConsistency());
        return template;
    } catch (Exception ex) {
        throw new IllegalStateException(ACCESS_FAILED, ex);
    }
}

@Bean
@Qualifier("tenant2Template")
public CouchbaseTemplate tenant2Template() {
    try {
        final CouchbaseTemplate template = new CouchbaseTemplate(
                couchbaseClusterInfo(), //reuse the default bean
                tenant2Bucket(), //the bucket is non-default
                mappingCouchbaseConverter(), translationService() //default beans here as well
        );
        template.setDefaultConsistency(getDefaultConsistency());
        return template;
    } catch (Exception ex) {
        throw new IllegalStateException(ACCESS_FAILED, ex);
    }
}

private Bucket openBucket(final String bucketName, final String bucketPassword, final String alternativeHost)
        throws IllegalStateException {
    try {
        return couchbaseCluster(alternativeHost).openBucket(bucketName, bucketPassword);
    } catch (Exception ex) {
        throw new IllegalStateException("Failed to open bucket " + bucketName, ex);
    }
}


@Override
public void configureRepositoryOperationsMapping(final RepositoryOperationsMapping baseMapping) {
    baseMapping.setDefault(masterTemplate());
}

@Override
protected List<String> getBootstrapHosts() {
    return parse(hosts);
}

@Override
protected String getBucketName() {
    return tenant1BucketName;
}

@Override
protected String getBucketPassword() {
    return tenant1BucketPassword;
}

private List<String> parse(final String hosts) {
    return Arrays.asList(hosts.split(","))
            .stream().map(in -> in.trim()).collect(Collectors.toList());
}

}

存储库

代码语言:javascript
复制
@Repository
public interface UserRepository extends CouchbaseRepository<User, String> {

User getByDocKey(final String docKey);

@Query("#{#n1ql.selectEntity} WHERE tenantId= $1")
List<User> findByTenantId(String tenantId);

}

谢谢

EN

回答 1

Stack Overflow用户

发布于 2018-10-15 23:30:19

简单答案

看起来这是可以做到的,但这并不是微不足道的。https://forums.couchbase.com/t/spring-couchbase-multiple-buckets/16984

Long answer

您正在向数据库推送本应由您的应用程序处理的内容。如果你有这样的问题,这可能意味着你应该有一个单一的存储桶来服务所有的客户。毕竟,使用这种方法不会允许您为100个客户端提供服务。

PS:使用n1ql,您仍然可以轻松地在存储桶之间切换,甚至可以在一个查询中使用多个存储桶。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52818780

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档