2009-09-23 13 views
8

में पर्सिस्टेंस क्लासेस मैं नेट से क्यूटी तक एक मध्यम आकार के सीआरयूडी अनुप्रयोग को पोर्ट कर रहा हूं और मैं दृढ़ता वर्ग बनाने के लिए एक पैटर्न की तलाश में हूं। नेट में मैं आमतौर पर बुनियादी तरीके (डालने, अद्यतन,, हटाने का चयन करें) उदाहरण के लिए के साथ सार हठ श्रेणी का निर्माण:क्यूटी

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) {...} 
} 

फिर, मैं इसे विशिष्ट टेबल/DTOs के लिए subclassed और डीबी तालिका लेआउट के लिए विशेषताएं कहा:

[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> 
{ 
} 

धन्यवाद। नेट प्रतिबिंब प्रणाली मैं भारी कोड पुन: उपयोग और नए ओआरएम के आसान निर्माण को प्राप्त करने में सक्षम था।

क्यूटी में इस तरह की चीजें करने का सबसे आसान तरीका QtSQL मॉड्यूल से मॉडल कक्षाओं का उपयोग करना प्रतीत होता है। दुर्भाग्यवश, मेरे मामले में वे बहुत ही इंटरफेस प्रदान करते हैं। मुझे कम से कम लेन-देन समर्थन और व्यक्तिगत प्रतिबद्धताओं पर नियंत्रण की आवश्यकता है जो QSqlTableModel प्रदान नहीं करता है।

क्या आप मुझे क्यूटी का उपयोग करके इस समस्या को हल करने के बारे में कुछ संकेत दे सकते हैं या मुझे कुछ संदर्भ सामग्री पर इंगित कर सकते हैं?


अद्यतन:

हेराल्ड के सुराग पर मैं एक समाधान है कि काफी ऊपर नेट वर्गों के समान है क्रियान्वित किया है के आधार पर। अब मेरे पास दो वर्ग हैं।

UniversalDAO कि QObject और QObject DTOs का उपयोग कर metatype प्रणाली के साथ सौदों विरासत:

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); 
}; 

ऊपर का उपयोग करना, मैं निम्नलिखित के रूप में ठोस डीएओ वर्ग की घोषणा: मैं

class ClientDAO : public QObject, public SpecializedDAO<ClientDTO> 
{ 
    Q_OBJECT 

public: 
    ClientDAO(UniversalDAO *dao, QObject *parent = 0) : 
     QObject(parent), SpecializedDAO<ClientDTO>(dao) 
    {} 
}; 

से भीतर ClientDAOUniversalDAO के लिए कुछ डेटाबेस जानकारी सेट करना होगा।

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 संस्करण में स्पॉट और समझना आसान था।

क्या आपके पास कुछ विचार हैं कि मैं इसे बेहतर कैसे बना सकता हूं?

उत्तर

5

जहां तक ​​मुझे पता है कि वहां कुछ भी तैयार नहीं है जो इस सुविधा को सीधे क्यूटी में देता है। कुछ संभावित दृष्टिकोण हैं।

  • Q_PROPERTY जैसे क्षेत्रों को लागू करें, तो The तो Metaclass प्रणाली के माध्यम से परिलक्षित होते हैं और सामान्य डीएओ कार्यक्षमता

  • लागू करने के लिए आप अभी भी QSqlTableModel का उपयोग लेकिन संपुटित सकता है, लेनदेन के साथ लिखते हैं एक सौदे अगर इस्तेमाल किया जा सकता विफल रहता है, डीबी से मॉडल रीफ्रेश करें। व्यवहार्यता आपके द्वारा मॉडल में रखे गए डेटा के आकार पर निर्भर करती है।

हम वर्तमान में पढ़ने और लिखने के लिए एक TableModel/QSqlRecord आधारित दृष्टिकोण का उपयोग, वहाँ कोई ORM हमारी प्रणाली में किया मानचित्रण है। मैं एक और सामान्य दृष्टिकोण इंजीनियर करने की कोशिश कर रहा हूं लेकिन इस समय रिफैक्टरिंग काम जो हमें करने के लिए करना होगा, उस समय महंगा होना है।

यह लिंक http://giorgiosironi.blogspot.com/2009/08/10-orm-patterns-components-of-object.html क्यूटी संबंधित नहीं है, लेकिन कार्यान्वयन पैटर्न

+0

शुरुआती बिंदु के रूप में अपनी युक्तियों और लिंक का उपयोग करके, मैंने समाधान के कार्यान्वयन को पोस्ट किया है। कृपया मुझे बताएं कि आप इसके बारे में क्या सोचते हैं। – zarzych

2

Tegesoft हाल ही में नामित अपने पुस्तकालय का एक नया संस्करण CAMP जारी है का एक अच्छा सिंहावलोकन प्रदान सी ++ क्रम परछाई के रूप में आप नेट में उपयोग कर रहे हैं। मुझे लगता है कि यह आपको अपने आवेदन को प्राप्त करने की अनुमति देगा जैसे आपने नेट में किया है।

+0

यह बहुत ही आशाजनक प्रतीत होता है लेकिन अगर मैं शुद्ध क्यूटी में समस्या का समाधान कर सकता हूं तो मैं निर्भरता के रूप में बढ़ावा खींचना नहीं चाहता हूं। – zarzych

2

एक नया ओपन सोर्स ओआरएम सी ++ लाइब्रेरी भी है: QxOrm। QxOrm QtSql Qt मॉड्यूल पर आधारित है और डेटाबेस और बूस्ट :: serialization के साथ संवाद करने के लिए xml और बाइनरी प्रारूप के साथ क्रमबद्ध करने के लिए मॉड्यूल पर आधारित है। वेबसाइट फ्रेंच में है लेकिन त्वरित नमूना कोड और ट्यूटोरियल कोड अंग्रेजी में है (एक अनुवाद प्रगति पर है ...)।

3

यदि आप एक ओआरएम चाहते हैं जो केवल क्यूटी पर निर्भर करता है और निष्पादन प्रदान करने के लिए क्यूटी के मेटा-ऑब्जेक्ट सिस्टम पर बनाता है, तो आप QDjango को आजमाने पर विचार कर सकते हैं। मॉडल स्तर पर बुनियादी निर्माण/अद्यतन/हटाए गए संचालन के शीर्ष पर, यह एक क्वेरीसेट टेम्पलेट क्लास (django के क्वेरीसेट के बाद मॉडलिंग) प्रदान करता है जो काफी जटिल लुकअप बनाने की अनुमति देता है। क्यूटीस्क्रिप्ट एकीकरण भी चल रहा है।

1

... और एक और नया क्यूटी ओआरएम: QST: QsT SQL Tools (नवीनतम स्थिर संस्करण - 0.4.2 ए रिलीज)। क्यूएसटी सरल एसक्यूएल प्रश्न उत्पन्न करने के लिए तंत्र प्रदान करता है: चुनें, सम्मिलित करें, हटाएं, संयुक्त करें और निष्पादित करें। संस्करण 0.4 टी-एसक्यूएल का उपयोग करता है; नया संस्करण - 0.5 - डिफ़ॉल्ट रूप से PostgreSQL का उपयोग करेगा। आपको मूल, असामान्य अवधारणाओं के आधार पर यह ओआरएम मिलेगा। उदाहरण के लिए, यह क्यूटी साक्षात्कार प्रणाली के साथ एकीकृत है, ताकि आप दृश्य प्रतिनिधित्व (कॉलम चौड़ाई, शीर्षक) को बहुत आसान बना सकें।

संस्करण 0.3 और 0.4 के लिए उदाहरण परियोजनाएं हैं: ट्रेड डीबी 0.3, ट्रेड डीबी 0.4। क्यूएसटी सीखना शुरू करने के लिए ट्रेड डीबी 0.4 उपयोगी होना चाहिए।

0

यह एक उत्कृष्ट तकनीक की तरह लगता है। हालांकि, मुझे एन लिंक को संकलित करने के लिए मेरे प्रोटोटाइप को प्राप्त करने में कुछ समस्याएं हैं ....

मैंने मूलभूत रूप से लागू किया है जैसा कि आप वर्णन करते हैं और डीएओ कक्षा को मेरी डीबी-निवासी वस्तुओं में से एक का उदाहरण पुनर्प्राप्त करने के लिए कहते हैं।

_db = <create QSqlDatabase>; 

    dao = new UniversalDAO (_db); 

    AddressDAO * aDAO = new AddressDAO (dao); 
    Address addr = aDAO->getByPrimaryKey(QVariant(1)); 

मेरी AddressDAO में:

यहाँ इस इन मॉडल वर्गों बुला बयान कर रहे हैं।सीपीपी, मेरे पास है:

template<class Address> 
Address SpecializedDAO<Address>::getByPrimaryKey(const QVariant &key) 
{ } 

लिंक समय में, मैं निम्नलिखित हो:

undefined reference to 
`SpecializedDAO<Address>::getByPrimaryKey(QVariant const&)' 

कैसे मैं सही ढंग से SpecializedDAO कक्षा में तरीकों को लागू करेंगे?

अद्यतन:

मुझे बेवकूफ, मुझे बेवकूफ, मुझे बेवकूफ .... मैं ज्यादातर इस काम मिल गया। मुद्दों ....

  1. मेरे मॉडल वर्गों (DTOs) नामस्थान में लिपटे रहे हैं और मैं मैक्रो का उपयोग को परिभाषित करने और इन नामस्थान उपयोग करने के लिए। साथ ही, मैं इन कक्षाओं के लिए एक अच्छा पदानुक्रम का उपयोग करने की कोशिश की और पाया कि moc वर्ग नामस्थान में लिपटे पदानुक्रम के साथ एक reeeeal समस्या है ....

  2. मैं fergot टेम्पलेट वर्गों की कि समारोह परिभाषाओं हेडर फाइल में होने की जरूरत है - अलग संकलन इकाइयों में नहीं हो सकता है।

  3. qmake लाइब्रेरी सीमाओं को पार करते समय बहुत अच्छी तरह से (हेडर फ़ाइल) निर्भरताओं से निपटता नहीं है। मेरे पास साझा मॉडल में मेरा मॉडल सामान है और 'मुख्य()' फ़ंक्शन (एक अलग निर्देशिका में) डीबी से रिकॉर्ड पढ़ने की कोशिश कर रहा था। 'मुख्य()' सी फ़ाइल को फिर से संकलित हो रही नहीं किया गया था जब मैं अपने मॉडल वर्ग हेडर फाइल बदल ...

यहाँ अधिक विवरण हैं:

SpecializedDAO.h में:

template<class DTO> 
DTO SpecializedDAO<DTO>::getByPrimaryKey(const QVariant &key) 
     throw (FlowException) 
{ 
    DTO obj; 
    dao->getByPrimaryKey(static_cast<QObject &> (obj), key); 
    return obj; 
} 

UniversalDAO.cpp में:

void 
UniversalDAO::getByPrimaryKey (QObject & dto, const QVariant & key) 
{ 
    <retrieve properties from 'dto' n build up QSqlQuery> 
    <execute QSqlQuery 'SELECT...' to retrieve record> 
    <call dto.setProperty() on all fields> 
} 

एक मौजूदा बकाया अंक में संपत्ति प्रकार के लिए उपयोगकर्ता परिभाषित प्रकार का प्रयोग होता है मेरी डीटीओ कक्षाएं मैं std::string बनाम QString का उपयोग करने की कोशिश कर रहा हूं, लेकिन इससे कोई फर्क नहीं पड़ता कि मैंने (Q_DECLARE_METATYPE(std::string), qRegisterMetaType<std::string>() इत्यादि की कोशिश की, कुछ भी काम नहीं कर रहा था .... क्यूटी-आधारित प्रकारों पर वापस जाना पड़ा। बमर ....