使用 SQLC 时,如何使数据库连接在运行时可切换

我知道这个问题已经被问过很多次了,但我没有为我的情况找到一个好的答案。我正在使用 SQLC 生成用于查询数据库的方法。使用开始时初始化的一个连接时,一切正常。现在,我需要在多租户环境中进行设置,其中每个租户将具有单独的数据库。现在,我想从连接映射(映射[字符串]*sql。DB) 将租户与数据库连接连接起来。我的问题是关于在运行时覆盖/选择连接。使用一个连接,存储库被初始化为:


type Repository interface {

    GetCustomerById(ctx context.Context, id int64) (Customer, error)

    ListCustomers(ctx context.Context) ([]Customer, error)

}


type repoSvc struct {

    *Queries

    db *sql.DB

}


func NewRepository(dbconn *sql.DB) Repository {

    return &repoSvc{

        Queries: New(dbconn),

        db:      dbconn,

    }

}


customerRepo := customerRepo.NewRepository(conn)

GetCustomerById 是 SQLC 生成的方法,连接是数据库连接


如何根据参数(从 Cookie 或上下文)建立连接?


拉风的咖菲猫
浏览 62回答 1
1回答

冉冉说

假设您使用的是单独的数据库,最简单的方法是维护 ,其中是区分租户(例如,包含租户 ID 的 或)的方式。map[tenantID]RepositorytenantIDstringuint这样,您就可以在运行时执行所有操作:当您需要添加租户时,只需实例化该租户并将其添加到地图中Repository当您需要删除租户时,只需将其从映射中删除并关闭数据库连接Repository当您需要对租户执行查询时,请在映射中查找相应的,并使用它来执行该租户的查询Repository如果上述操作可能同时发生,请确保使用某种同步机制来避免访问映射时的数据争用(例如 、或 )。sync.Mapsync.RWMutex如果您有一个存储租户及其数据库连接 URI 的数据库表,您仍然可以使用此方法:当您需要执行查询检查时,如果 缺少 :,则查询租户表并将该租户的 添加到映射中。然后,您可以定期扫描 并删除任何一段时间未使用的内容。RepositorymapRepositorymapRepository为了使所有这些更容易,您还可以将整个机器包装到一个接口中,该接口与接口相同,但每个方法上都接受一个附加参数:MultitenantRepositoryRepositorytenantIDtype MultitenantRepository interface {     GetCustomerById(ctx context.Context, tenant tenantID, id int64) (Customer, error)     ListCustomers(ctx context.Context, tenant tenantID) ([]Customer, error) }这将避免将多租户设置的所有复杂性暴露给业务逻辑。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go