我正在将一个中等大小的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