我正在將一箇中等大小的CRUD應用程序從.Net移植到Qt,我正在尋找一種創建持久性類的模式。在.net我通常創建抽象持久類基本方法(插入,更新,刪除,選擇),例如:Qt中的持久化類
public class DAOBase<T>
{
public T GetByPrimaryKey(object primaryKey) {...}
public void DeleteByPrimaryKey(object primaryKey) {...}
public List<T> GetByField(string fieldName, object value) {...}
public void Insert(T dto) {...}
public void Update(T dto) {...}
}
然後,我子類它爲特定的表/ DTO的和添加的屬性爲DB表佈局:
[DBTable("note", "note_id", NpgsqlTypes.NpgsqlDbType.Integer)]
[DbField("note_id", NpgsqlTypes.NpgsqlDbType.Integer, "NoteId")]
[DbField("client_id", NpgsqlTypes.NpgsqlDbType.Integer, "ClientId")]
[DbField("title", NpgsqlTypes.NpgsqlDbType.Text, "Title", "")]
[DbField("body", NpgsqlTypes.NpgsqlDbType.Text, "Body", "")]
[DbField("date_added", NpgsqlTypes.NpgsqlDbType.Date, "DateAdded")]
class NoteDAO : DAOBase<NoteDTO>
{
}
由於.Net反射系統,我能夠實現大量的代碼重用和輕鬆創建新的ORM。
在Qt中做這種東西的最簡單方法似乎是使用QtSql模塊中的模型類。不幸的是,在我的情況下,它們提供的接口太抽象了。我至少需要事務支持和對QSqlTableModel不提供的單個提交進行控制。
你可以給我一些關於使用Qt解決這個問題的提示,或者指點我一些參考資料嗎?
更新:
基於哈拉爾的線索,我實現了一個解決方案,是非常類似於上面的.NET類。現在我有兩個班。
UniversalDAO繼承的QObject並用QObject的 DTO的使用元類型系統處理:
class UniversalDAO : public QObject
{
Q_OBJECT
public:
UniversalDAO(QSqlDatabase dataBase, QObject *parent = 0);
virtual ~UniversalDAO();
void insert(const QObject &dto);
void update(const QObject &dto);
void remove(const QObject &dto);
void getByPrimaryKey(QObject &dto, const QVariant &key);
};
和通用SpecializedDAO其投射從UniversalDAO獲得適當類型的數據:
template<class DTO>
class SpecializedDAO
{
public:
SpecializedDAO(UniversalDAO *universalDao)
virtual ~SpecializedDAO() {}
DTO defaultDto() const { return DTO; }
void insert(DTO dto) { dao->insert(dto); }
void update(DTO dto) { dao->update(dto); }
void remove(DTO dto) { dao->remove(dto); }
DTO getByPrimaryKey(const QVariant &key);
};
使用上面,我宣佈具體的DAO類如下:
class ClientDAO : public QObject, public SpecializedDAO<ClientDTO>
{
Q_OBJECT
public:
ClientDAO(UniversalDAO *dao, QObject *parent = 0) :
QObject(parent), SpecializedDAO<ClientDTO>(dao)
{}
};
從內ClientDAO我必須設置一些數據庫信息UniversalDAO。這就是我的實現變得醜陋,因爲我不喜歡這樣寫道:
QMap<QString, QString> fieldMapper;
fieldMapper["client_id"] = "clientId";
fieldMapper["name"] = "firstName";
/* ...all column <-> field pairs in here... */
dao->setFieldMapper(fieldMapper);
dao->setTable("client");
dao->setPrimaryKey("client_id");
我這樣做是在構造函數,因此它在有人通過標題瀏覽乍一看是不可見的。在.Net版本中,很容易發現和理解。
你有什麼想法可以讓它變得更好嗎?
以您的提示和鏈接爲出發點,我已經發布了我的解決方案實施。請告訴我你的想法。 – zarzych 2009-10-01 18:42:57