数据库连接模式

时间:2017-02-07 07:20:53

标签: database-connection mariadb connection-pooling d vibed

我使用mysql-native。此驱动程序是suppport vibed的连接池。在dlang新闻组mysql-native开发人员Nick Sabalausky写道:

"如果您正在使用连接池,则不必担心关闭连接。重点是连接保持打开状态,直到您需要再次使用连接。当你的程序结束时,连接将自行关闭。"

"您可以创建一次池(无论何时/何时)。然后,每次要使用数据库时,都可以通过调用MySqlPool.lockConnection来获取连接。"

"致电'关闭'将始终关闭连接。如果您从池中获得了连接,那么当您不再使用它时它将自动返回池中。不需要做任何特别的事情。"

关于如何进行游泳池的问题?我已经阅读了关于单身人士模式的内容,并且在这种情况下无法解决问题。

我写了下一段代码:

database class:
import std.stdio;
import std.string;
import mysql;
import vibe.d;

import config;
import user;

class Database
{
    Config config;
    MySqlPool mydb;
    Connection connection;

    this(Config config)
    {
        this.config = config;
        mydb = new MySqlPool(config.dbhost, config.dbuser, config.dbpassword, config.dbname, config.dbport);    
    }

    void connect()
    {
        if(connection is null)
        {
            connection = mydb.lockConnection();
        }
        scope(exit) connection.close();
    }

}

users class / struct:

module user;

import mysql;
import vibe.d;

struct User
{
    int id;
    string login;
    string password;
    string usergroup;
}
    void getUserByName(string login)
    {
        User user;
        Prepared prepared = prepare(connection, `SELECT id, login, password, usergroup from users WHERE login=?`); // need to get connection accessible here to make request to DB
        prepared.setArgs(login);
        ResultRange result = prepared.query();
        if (result.empty) 
            logWarn(`user: "%s" do not exists`, login);
        else
        {
                Row row = result.front;
                user.id = row[0].coerce!(int);
                user.login = row[1].coerce!string;
                user.password = row[2].coerce!string;
                user.usergroup = row[3].coerce!string;

        logInfo(`user: "%s" is exists`, login);
        }

    }

我无法理解访问connection实例的正确方法的问题。在users结构中创建每个新的数据库连接类似乎是非常愚蠢的想法。但是如何以更好的方式做到这一点?使Connection connection全球化?这样好吗?还是有更正确的方法?

2 个答案:

答案 0 :(得分:1)

一种方法是将连接传递给需要它的函数。因此,您将重构getUserByName()以将连接作为参数。

另一种选择是使用DAO pattern。 DAO类的构造函数将连接作为主要参数之一,并且所有方法都将使用它来执行数据库操作。

答案 1 :(得分:1)

scope(exit) connection.close();

删除该行。它正在关闭您在connect函数返回之前从池中收到的连接。你在那里所做的只是打开一个连接,只是为了立即再次关闭它。

更改getUserByName以将连接作为参数(通常作为第一个参数)。通常,任何需要调用getUserByName的代码都应该打开连接,或者通过lockConnection从池中获取连接,然后将该连接传递给getUserByName以及其他任何与DB相关的函数它需要使用。然后,在你的代码完成后调用getUserByName(以及它需要调用的任何其他数据库函数),你或者只是不再担心连接,让你的振动纤维完成(如果你使用振动和从池中获得连接)或者close连接(如果你没有从振动池获得连接)。