【发布时间】:2009-09-23 20:20:05
【问题描述】:
我正在将一个中型 CRUD 应用程序从 .Net 移植到 Qt,并且我正在寻找一种用于创建持久性类的模式。在 .Net 中,我通常使用基本方法(插入、更新、删除、选择)创建抽象持久性类,例如:
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 解决此问题的提示或指向一些参考资料?
更新:
根据 Harald 的线索,我实现了一个与上述 .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 版本中很容易发现和理解。
你有什么想法可以让它变得更好吗?
【问题讨论】: