иерархия класса уровня БД

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by cupper, 11 Dec 2010.

  1. cupper

    cupper Elder - Старейшина

    Joined:
    6 Jun 2007
    Messages:
    369
    Likes Received:
    92
    Reputations:
    5
    В кратце, трех звенная архитектура: уровень БД, уровень логики, уровень представления.

    Думаю как организовать класс на уровне БД.
    Требования:
    1. Возможность загрузи параметров для соединения с БД из внешнего ресурса
    2. Методы доходящие по уровня логики только конечные методы. Все строки запросов, функции конекта и прочее скрыто. Доступны лишь функции типа: добавить строку, получить строки, обновить строку, удалить строку.
    3. На этом же уровни решаются все вопросы по поводу проблем соединения, блокировок (транзакций). В случае если проблемы решить не получается автоматически выбрасываются типизированные исключения с доп. информацией.
    Контроль за логической целостностью БД реализован в самой БД ( по средством внешних ключей), и если сервер возвращает ошибки связанные с этим, то также выбрасываются исключения...

    Реализую на С++. БД MySQL. Но это в принципе не должно играть роли.

    Значит, в голове крутиться следующая карусель
    1. Иметь класс сингелтон DatabaseHelper
    Code:
    class DatabaseHelper : private boost::noncopyable
    	{
    	public:
    		static const DatabaseHelper& GetHelper();
    	private:
    		static DatabaseHelper* theSingelton;
    		DatabaseHelper();
    		DatabaseHelper(std::string& address, std::string& user,
    			std::string pwd, std::string database);
    		// функции получения членом класса
    		// Информация для подлкючение к БД
    		std::string address_;
    		std::string user_;
    		std::string pwd_;
    		std::string database_;
    	};
    реализовать в нем сериализацию. И при запуске приложения десериализовать данные из внешнего xml файла. Таким образом можно в ручную будет править параметры подключения.
    А при закрытии сериализовать тудаже, что позволит еще в будущем добавить правку параметров прям из программы.
    2. Базовый класс BaseDB
    Code:
    class BaseDB : private boost::noncopyable
    	{
    		protected:
    			static sql::Connection* Connect() throw(sql::SQLException);
    			static boost::shared_ptr<sql::ResultSet> Transaction(sql::PreparedStatement*) throw(sql::SQLException);
    			// возможно потом чтото еще сюда доавить
    	}
    бызовый класс будет реализовывать рабочие второстепенные функции типа получения коннекта к БД, выполнения транзакции по набору параметров и возврат результатов. Будет юзать класс DatabaseHelper.
    3. Конечные классы предоставляющие методы пользователю (также статические, без возможности сосздания экземпляра класса, так сказать хелперы)
    Code:
    class AddressDB : public BaesDB
    {
    public:
    	static Address* GetAddressByID(const int) throw(sql::SQLException);
    	static vector<Address> GetAddressByPersone(const Persone&) throw(sql::SQLException);
    	static void AddAddresByPersone(const Persone&) throw(sql::SQLException);
    	static void DeleteAddressByPersone(const Persone&) throw(sql::SQLException);
    	
    	// Вспомогательные функции, выборки справочников
    	static vector<City> GetAllCity() throw(sql::SQLException);
    	static vector<Street> GetAllStreetByCity(const City&) throw(sql::SQLException);
    private:
    	static const std::string QuerySelectAddressByID;
    	static const std::string QuerySelectAllAddressByPersone;
    	static const std::string QueryInsertAddressByPersone;
    	static const std::string QueryDeleteAddressByPersone;
    	static const std::string QueryGetAllCity;
    	static const std::string QueryGetAllStreetByCity;
    	// Класс используется только как хелпер
    	PersoneDB();
    }
    
    Воот. Но чтото больно косяков тут возникает. Например, нахрена в базовом классе функция выполнения транзакции, это конечно удобно с точки зрения что она ее открывает и она же ее закрывает и за этим следить не надо. Но не удобно в плане что если транзакция большая то передать ей нужно все это в виде одной охренено больной команды. В этом случае проще следить за транзакциями в конечных функция 3 пункта.
    Тогда в базовом классе оставить одну единственную функци открытия соединения, чтобы не дублировать ее в коде.

    Задача конечно надуманная. Но нужно же на чемто учиться.
    Что скажите ? Предложите свое видение реализации.
     
    #1 cupper, 11 Dec 2010
    Last edited: 11 Dec 2010