Russian Qt Forum

Qt => Кладовая готовых решений => Тема начата: nata267 от Июнь 19, 2012, 12:16



Название: Вопрос сохранения данных.
Отправлено: nata267 от Июнь 19, 2012, 12:16
Допустим я проектирую программу-редактор чегото там. У меня в интерфейсе программы есть окошко типа QDockWidget+QTreeView, где пользователь будет формировать древовидную структуру чегото там с помощью кнопок "Добавить узел такого-то типа", "Удалить", "Переименовать", "Переместить" и т.д.  Когда мы щелкаем на созданный узел в другое окошко загружается содержимое этого узла. Допустим это форма с элементами типа: текстовое поле, картинка, видео, аудио файл. Эти элементы можно двигать на форме, менять размер. БД, где все это хранится после сохранения пользователем путь будет MYSQL.

Вопрос заключается в том. Как организовать хранение всех изменений и сохранения общего изменившегося состояния в БД по кнопке главного меню "Сохранить"? Если бы можно было сохранять только изменения формы это была бы простая задача. Но как быть с древовидной структурой? Я дала упрощенное описание программы. На самом деле она намного сложнее, там куча окошек с различными данными которые изменяет пользователь. Все изменения фиксируются в базе где куча взаимосвязанных таблиц. Как делать общее сохранение данных по кнопке сохранить?? Какие есть варианты решения данной задачи?? И еще вопрос. Является ли это архитектурной задачей?? И стоит ли её рассматриваить и выделять отдельную ветку для решения архитектурных задач?


Название: Re: Вопрос сохранения данных.
Отправлено: Bepec от Июнь 19, 2012, 12:30
Кхм. А сохранить всю базу, религия не позволяет? :)


Название: Re: Вопрос сохранения данных.
Отправлено: alexis031182 от Июнь 19, 2012, 12:33
Кхм. А сохранить всю базу, религия не позволяет? :)
undo/redo хранят на время одной сессии работы приложения. В БД держать это ни к чему.


Название: Re: Вопрос сохранения данных.
Отправлено: alexis031182 от Июнь 19, 2012, 12:45
Как делать общее сохранение данных по кнопке сохранить??
Как обычно. Пройтись по списку виджетов и сохранить их текущее состояние в БД.

Какие есть варианты решения данной задачи??
Я бы сделал через медиатор + классы, хранящие состояние виджетов. Только медиатор должен быть Медиатором в данном случае, а не простым контейнером перекрёстных ссылок. Медиатор сам реализует логику, и не должен использоваться в роли пассивного участника событий.

И еще вопрос. Является ли это архитектурной задачей?? И стоит ли её рассматриваить и выделять отдельную ветку для решения архитектурных задач?
Страшное слово. Не загоняйте себя в рамки. Задача как задача, не более и не менее архитектурна, нежели другие.


Название: Re: Вопрос сохранения данных.
Отправлено: nata267 от Июнь 19, 2012, 13:09
Как делать общее сохранение данных по кнопке сохранить??
Как обычно. Пройтись по списку виджетов и сохранить их текущее состояние в БД.

Это очень хорошо, но тогда есть вопросы. Во-первых, в базе храняться несколько проектов. Их пользователь открывает по кнопке допустим "Открыть проект". В этом случае предыдущий проект должен быть сохранен и закрыт. То есть вы предлагаете при сохранении стереть в базе данных всю информация касающуюся этого проекта и занести целиком новую во все таблицы или как?? Там куча взаимосвязанных таблиц. и куча данных по проекту. Изменение проекта за один сеанс работы с ним может быть как незначительным, так и кардинально меняющим вообще всю структуру проекта. И в том и в том случае придется сгененрировать и запустить кучу запросов? Это разве рационально?? Или вы имеете ввиду помечать элементы бд статусами deleted, inserted, modified. Поясните пожалуйста??


Название: Re: Вопрос сохранения данных.
Отправлено: nata267 от Июнь 19, 2012, 13:19

Какие есть варианты решения данной задачи??
Я бы сделал через медиатор + классы, хранящие состояние виджетов. Только медиатор должен быть Медиатором в данном случае, а не простым контейнером перекрёстных ссылок. Медиатор сам реализует логику, и не должен использоваться в роли пассивного участника событий.


Если я не ошибаюсь,то вы предлагаете наследовать все элементы, хранящиеся в бд от одного класса например DBObject. и медиатор, хранящий ссылки на все эти объекты, медиатор проходит по объектам и смотрит их состояние (inserted, modified, deleted) и в зависимости от этого выполняется запрос к базе??? Правда в этом случае это уже не медиатор, а итератор)) Но там очень много иерархических и взаимосвязанных по id структур( Id генерируются при вставке в бд автоматически).  Как быть с их удалением, вставкой?


Название: Re: Вопрос сохранения данных.
Отправлено: nata267 от Июнь 19, 2012, 13:35
И еще вопрос. Является ли это архитектурной задачей?? И стоит ли её рассматриваить и выделять отдельную ветку для решения архитектурных задач?
Страшное слово. Не загоняйте себя в рамки. Задача как задача, не более и не менее архитектурна, нежели другие.

К какому же существующему разделу на этом форуме  можно отнести эту тему?


Название: Re: Вопрос сохранения данных.
Отправлено: nata267 от Июнь 19, 2012, 13:39
Только медиатор должен быть Медиатором в данном случае, а не простым контейнером перекрёстных ссылок. Медиатор сам реализует логику, и не должен использоваться в роли пассивного участника событий.

Почему он не должен быть простым контейнером перекрестных ссылок? И как он должен реализовывать логику? И почему медиатор, а не итератор?? Вообще не могу себе представить ваш медиатор. Что он вообще делает??


Название: Re: Вопрос сохранения данных.
Отправлено: Bepec от Июнь 19, 2012, 13:47
http://ru.wikipedia.org/wiki/Медиатор


Название: Re: Вопрос сохранения данных.
Отправлено: nata267 от Июнь 19, 2012, 13:57
http://ru.wikipedia.org/wiki/Медиатор


)) не волнуйтесь, я знаю что такое медиатор. мне интересно как он реализован в контексте данной задачи.  классы, хранящие состояние виджетов знают о нем, он знает о них. вопрос. что он делает? и что собой представляют эти классы, хранящие состояние виджетов? по идее через медиатор они должны обмениваться сообщениями. какими именно сообщениями могут обмениваться ваши классы, хранящие состояние виджетов? зачем им вообще обмениваться сообщениями?


Название: Re: Вопрос сохранения данных.
Отправлено: alexis031182 от Июнь 19, 2012, 14:09
Это очень хорошо, но тогда есть вопросы. Во-первых, в базе храняться несколько проектов. Их пользователь открывает по кнопке допустим "Открыть проект". В этом случае предыдущий проект должен быть сохранен и закрыт. То есть вы предлагаете при сохранении стереть в базе данных всю информация касающуюся этого проекта и занести целиком новую во все таблицы или как?? Там куча взаимосвязанных таблиц. и куча данных по проекту. Изменение проекта за один сеанс работы с ним может быть как незначительным, так и кардинально меняющим вообще всю структуру проекта. И в том и в том случае придется сгененрировать и запустить кучу запросов? Это разве рационально?? Или вы имеете ввиду помечать элементы бд статусами deleted, inserted, modified. Поясните пожалуйста??
А почему нерационально? Только конечно в БД следует вносить изменения только в те записи, виджеты которых реально изменились. А за фактом изменения каждого конкретного виджета должен следить медиатор.


Название: Re: Вопрос сохранения данных.
Отправлено: nata267 от Июнь 19, 2012, 14:12
Это очень хорошо, но тогда есть вопросы. Во-первых, в базе храняться несколько проектов. Их пользователь открывает по кнопке допустим "Открыть проект". В этом случае предыдущий проект должен быть сохранен и закрыт. То есть вы предлагаете при сохранении стереть в базе данных всю информация касающуюся этого проекта и занести целиком новую во все таблицы или как?? Там куча взаимосвязанных таблиц. и куча данных по проекту. Изменение проекта за один сеанс работы с ним может быть как незначительным, так и кардинально меняющим вообще всю структуру проекта. И в том и в том случае придется сгененрировать и запустить кучу запросов? Это разве рационально?? Или вы имеете ввиду помечать элементы бд статусами deleted, inserted, modified. Поясните пожалуйста??
А почему нерационально? Только конечно в БД следует вносить изменения только в те записи, виджеты которых реально изменились. А за фактом изменения каждого конкретного виджета должен следить медиатор.

вот я и справшиваю. как реализован ваш медиатор в контексте данной задачи.  классы, хранящие состояние виджетов знают о нем, он знает о них. вопрос. что он делает? и что собой представляют эти классы, хранящие состояние виджетов? по идее через медиатор они должны обмениваться сообщениями. какими именно сообщениями могут обмениваться ваши классы, хранящие состояние виджетов? зачем им вообще обмениваться сообщениями? если нужен обход, то это итератор, а не медиатор, а ваш медиатор я не представляю себе его никаак


Название: Re: Вопрос сохранения данных.
Отправлено: alexis031182 от Июнь 19, 2012, 14:17
Если я не ошибаюсь,то вы предлагаете наследовать все элементы, хранящиеся в бд от одного класса например DBObject.
Нет. Виджеты как были так и пусть будут. Не надо никаких их наследований.

и медиатор, хранящий ссылки на все эти объекты
Так точно.

, медиатор проходит по объектам и смотрит их состояние (inserted, modified, deleted) и в зависимости от этого выполняется запрос к базе???
Нет. Каждый виджет должен сам информировать медиатор о своих изменениях.

Правда в этом случае это уже не медиатор, а итератор)) Но там очень много иерархических и взаимосвязанных по id структур( Id генерируются при вставке в бд автоматически).  Как быть с их удалением, вставкой?
Ну вот смотрите. У Вас имеется набор виджетов. Каждый виджет при изменении отправляет в медиатор событие, что изменилось: НАИМЕНОВАНИЕ_ПАРАМЕТРА, ЗНАЧЕНИЕ_ПАРАМЕТРА.

Медиатор, прекрасно представляя, собственно, от кого пришёл очередной посыл, создаёт объект класса состояния виджета для истории (стек), куда и заносит эту информацию. Соответственно, если хоть одно событие по какому-то виджету подобного рода медиатор получил, значит медиатор ставит этому виджету флаг - ИЗМЕНЁННЫЙ.

Далее, думаю, ясно.


Название: Re: Вопрос сохранения данных.
Отправлено: alexis031182 от Июнь 19, 2012, 14:18
К какому же существующему разделу на этом форуме  можно отнести эту тему?
Это конечно не в кладовой. "Общие вопросы" наверное единственный вариант.


Название: Re: Вопрос сохранения данных.
Отправлено: alexis031182 от Июнь 19, 2012, 14:20
)) не волнуйтесь, я знаю что такое медиатор. мне интересно как он реализован в контексте данной задачи.  классы, хранящие состояние виджетов знают о нем, он знает о них. вопрос. что он делает? и что собой представляют эти классы, хранящие состояние виджетов? по идее через медиатор они должны обмениваться сообщениями. какими именно сообщениями могут обмениваться ваши классы, хранящие состояние виджетов? зачем им вообще обмениваться сообщениями?
Медиатор хранит не только указатели на объекты виджетов, но и указатели на объекты классов состояний виджетов, которых, в случае необходимости, может быть своя, параллельная виджетам иерархия.


Название: Re: Вопрос сохранения данных.
Отправлено: alexis031182 от Июнь 19, 2012, 14:28
Вы быстрее задаёте вопросы, нежели чем я успеваю печатать ответы :)

вот я и справшиваю. как реализован ваш медиатор в контексте данной задачи.  классы, хранящие состояние виджетов знают о нем, он знает о них. вопрос. что он делает? и что собой представляют эти классы, хранящие состояние виджетов?
Никак нереализован, у меня другой медиатор, для других целей. Я лишь предложил своё виденье.

Класс состояния виджета - произвольный класс, содержащий в себе данные об изменённых параметрах виджета в определённый момент времени (на момент изменения).

Именно медиатор должен быть управлящим всего этого хозяйства.

по идее через медиатор они должны обмениваться сообщениями. какими именно сообщениями могут обмениваться ваши классы, хранящие состояние виджетов? зачем им вообще обмениваться сообщениями? если нужен обход, то это итератор, а не медиатор, а ваш медиатор я не представляю себе его никаак
А я не могу понять, при чём здесь итератор и какой-то обход :) Я постараюсь сформулировать более понятно идею и напишу чуть позже.


Название: Re: Вопрос сохранения данных.
Отправлено: nata267 от Июнь 19, 2012, 14:45
Вы быстрее задаёте вопросы, нежели чем я успеваю печатать ответы :)

вот я и справшиваю. как реализован ваш медиатор в контексте данной задачи.  классы, хранящие состояние виджетов знают о нем, он знает о них. вопрос. что он делает? и что собой представляют эти классы, хранящие состояние виджетов?
Никак нереализован, у меня другой медиатор, для других целей. Я лишь предложил своё виденье.

Класс состояния виджета - произвольный класс, содержащий в себе данные об изменённых параметрах виджета в определённый момент времени (на момент изменения).

Именно медиатор должен быть управлящим всего этого хозяйства.

по идее через медиатор они должны обмениваться сообщениями. какими именно сообщениями могут обмениваться ваши классы, хранящие состояние виджетов? зачем им вообще обмениваться сообщениями? если нужен обход, то это итератор, а не медиатор, а ваш медиатор я не представляю себе его никаак
А я не могу понять, при чём здесь итератор и какой-то обход :) Я постараюсь сформулировать более понятно идею и напишу чуть позже.

обход структуры виджетов или структуры ваших состояний виджетов, обход во время сохранения, чтобы вызвать запросы на обновление данных


Название: Re: Вопрос сохранения данных.
Отправлено: alexis031182 от Июнь 19, 2012, 15:07
обход структуры виджетов или структуры ваших состояний виджетов, обход во время сохранения, чтобы вызвать запросы на обновление данных
Ну так это же один раз по кнопке Сохранить, а не при каждом изменении каждого виджета.


Название: Re: Вопрос сохранения данных.
Отправлено: nata267 от Июнь 20, 2012, 13:56
в вопросе сохранения данных есть ещё такой момент как иерархические структуры связанные по parent_id. Если поле id autoincrement в базе данных. То при вставке дочерных надо знать id только что вставленного родителя. Допустим с обновлением и удалением более или менее все понятно. Но как решается данная проблема вставки иерархических структур?


Название: Re: Вопрос сохранения данных.
Отправлено: alexis031182 от Июнь 20, 2012, 14:02
...
То при вставке дочерных надо знать id только что вставленного родителя.
...
А в чём проблема? Любая БД поддерживает LastInsertId


Название: Re: Вопрос сохранения данных.
Отправлено: nata267 от Июнь 20, 2012, 14:13
...
То при вставке дочерных надо знать id только что вставленного родителя.
...
А в чём проблема? Любая БД поддерживает LastInsertId

допустим если обходить эту структуру сверху вниз то эта проблема решаема, а если есть объекты со связями многие ко многим. как с ними быть? Для этих связей создавать отдельные объекты? И сохранять их в последнюю очередь, те когда будут известны id вставляемых связываемых объектов?


Название: Re: Вопрос сохранения данных.
Отправлено: alexis031182 от Июнь 20, 2012, 14:37
допустим если обходить эту структуру сверху вниз то эта проблема решаема, а если есть объекты со связями многие ко многим. как с ними быть? Для этих связей создавать отдельные объекты? И сохранять их в последнюю очередь, те когда будут известны id вставляемых связываемых объектов?
Обычно в таких ситуациях связи всегда выделяют в отдельную таблицу. Тогда:
1. вставляются записи данных, получая через lastinsertid их индексы;
2. вставляются записи связей, которые и будут содержать id записей данных.


Название: Re: Вопрос сохранения данных.
Отправлено: nata267 от Июнь 20, 2012, 14:41
допустим если обходить эту структуру сверху вниз то эта проблема решаема, а если есть объекты со связями многие ко многим. как с ними быть? Для этих связей создавать отдельные объекты? И сохранять их в последнюю очередь, те когда будут известны id вставляемых связываемых объектов?
Обычно в таких ситуациях связи всегда выделяют в отдельную таблицу. Тогда:
1. вставляются записи данных, получая через lastinsertid их индексы;
2. вставляются записи связей, которые и будут содержать id записей данных.

а если в одном из связываемых объектов создать список указателей на другие связываемые объекты. Сохранить сначала их, а потом сохранить первый связываемый объект. Пройтись по списку указателей на связываемые объекты, у которых уже известны id и создать связи. Или даже хранить не указатели на объекты, а указатели на связи с объектами. и у связей тоже будут статусы deleted, modified


Название: Re: Вопрос сохранения данных.
Отправлено: nata267 от Июнь 20, 2012, 14:44
допустим если обходить эту структуру сверху вниз то эта проблема решаема, а если есть объекты со связями многие ко многим. как с ними быть? Для этих связей создавать отдельные объекты? И сохранять их в последнюю очередь, те когда будут известны id вставляемых связываемых объектов?
Обычно в таких ситуациях связи всегда выделяют в отдельную таблицу. Тогда:
1. вставляются записи данных, получая через lastinsertid их индексы;
2. вставляются записи связей, которые и будут содержать id записей данных.

а если в одном из связываемых объектов создать список указателей на другие связываемые объекты. Сохранить сначала их, а потом сохранить первый связываемый объект. Пройтись по списку указателей на связываемые объекты, у которых уже известны id и создать связи. Или даже хранить не указатели на объекты, а указатели на связи с объектами. и у связей тоже будут статусы deleted, modified

вопрос не в очередности, а в том как делать обход?? в какой структуре это хранить и как делать обход этой структуры в момент сохранения. в любом случае придется делать приоритет. то есть объекты одного типа сохраняются раньше объектов другого типа


Название: Re: Вопрос сохранения данных.
Отправлено: alexis031182 от Июнь 20, 2012, 14:55
Я думал Вы про БД спрашивали выше. Всё смешалось в доме Облонских.


Название: Re: Вопрос сохранения данных.
Отправлено: alexis031182 от Июнь 20, 2012, 15:00
вопрос не в очередности, а в том как делать обход??
Обход по идее с верхнего родительского уровня начинать надо.

в какой структуре это хранить и как делать обход этой структуры в момент сохранения.
Под "структурой" что Вы понимаете? У Вас есть дерево объектов. Родители со ссылками (указателями) на дочерние объекты. Зачем нужны какие-то дополнительные мегаобразования?

в любом случае придется делать приоритет. то есть объекты одного типа сохраняются раньше объектов другого типа
Здесь Вы уже на своей волне.


Название: Re: Вопрос сохранения данных.
Отправлено: nata267 от Июнь 27, 2012, 11:04
C одной табличкой бд все здорово получается и сохранение всех изменений и действия undo/redo, cut, copy, paste. но как только появляется связь с другой табличкой "многие ко многим" с undo/redo и сохранением всех действий  получается какая-то жесть... без undo/redo и с сохранением сразу в базу все получается. очень хочется плюнуть на это дело.


Название: Re: Вопрос сохранения данных.
Отправлено: alexis031182 от Июнь 27, 2012, 11:20
Бейтесь, не смотря ни на что. Попробуйте мыслить нестандартно. Или в конце концов просто отложите поиск решения на лучшее время, а пока займитесь другой тактической задачей. Иногда идеи приходят невзначай, провидение подскажет.

Мне кажется, что такая задача не имеет паттерного решения. Она индивидуальна в каждом конкретном приложении и исходит из его условий. Моё виденье решения этой задачи скорее всего не соответствует тому, что должно происходить в Вашем случае, а значит рекомендации с моей стороны попросту ни к чему не приведут. Впрочем, это Вы итак уже заметили.

Undo/redo, как очень справедливо отметил Игорь, весьма нетривиальная задача. Вполне вероятно, что со сложносоставными объектами она вообще не имеет решения. Точнее сказать, затраты на обслуживание объектов в "корзине" становятся столь высокими, что проще действительно "забить" на это дело. Суперуниверсализм не всегда достижим. Впрочем, сдаваться и опускать руки - последнее дело.


Название: Re: Вопрос сохранения данных.
Отправлено: Igors от Июнь 27, 2012, 11:33
C одной табличкой бд все здорово получается и сохранение всех изменений и действия undo/redo, cut, copy, paste. но как только появляется связь с другой табличкой "многие ко многим" с undo/redo и сохранением всех действий  получается какая-то жесть... без undo/redo и с сохранением сразу в базу все получается. очень хочется плюнуть на это дело.
Да, при "связках объектов" (даже без базы) undo часто получается исключительно трудным и требует затрат/кода во много раз превышающего само действие.

Бейтесь, не смотря ни на что. Попробуйте мыслить нестандартно. ....Суперуниверсализм не всегда достижим. Впрочем, сдаваться и опускать руки - последнее дело.
Слова-то хорошие, но подозреваю что без конкретного примера/задачи эффект (увы) все же нулевой  :)
Проблема в том что привести такой пример очень трудно. Или "все просто и все получается, какой чудесный паттерн" или др крайность - такая тонна специфики что понять человеку вне проекта нереально


Название: Re: Вопрос сохранения данных.
Отправлено: nata267 от Июнь 27, 2012, 11:54
C одной табличкой бд все здорово получается и сохранение всех изменений и действия undo/redo, cut, copy, paste. но как только появляется связь с другой табличкой "многие ко многим" с undo/redo и сохранением всех действий  получается какая-то жесть... без undo/redo и с сохранением сразу в базу все получается. очень хочется плюнуть на это дело.
Да, при "связках объектов" (даже без базы) undo часто получается исключительно трудным и требует затрат/кода во много раз превышающего само действие.

Бейтесь, не смотря ни на что. Попробуйте мыслить нестандартно. ....Суперуниверсализм не всегда достижим. Впрочем, сдаваться и опускать руки - последнее дело.
Слова-то хорошие, но подозреваю что без конкретного примера/задачи эффект (увы) все же нулевой  :)
Проблема в том что привести такой пример очень трудно. Или "все просто и все получается, какой чудесный паттерн" или др крайность - такая тонна специфики что понять человеку вне проекта нереально


У меня задача вроде бы и простая, но чето никак. суть в том что у меня есть окошко с QTreeView+QStandardItemModel. Дерево состоит из двух уровней. Первый уровень - это данные из одной таблицы. Второй уровень - данные из другой таблицы. Между этими табличками связь "многие-ко-многим". То есть если я добавляю дочерний узел, то эта запись должна пойти в базу и прицепиться к родительскому узлу. Для наглядности картинку с окошком прицепила. Вот если я убираю дочерние узлы, то реализуется все на раз-два. А сними начинается куча проблем. Дочерние узля кстати можно создавать и в окошке и выбирать ранее созданные из базы этих объектов (по тз было перетаскиванием, короче там ещё dragand drop замешан))), вот.


Название: Re: Вопрос сохранения данных.
Отправлено: alexis031182 от Июнь 27, 2012, 12:09
У меня задача вроде бы и простая, но чето никак. суть в том что у меня есть окошко с QTreeView+QStandardItemModel. Дерево состоит из двух уровней. Первый уровень - это данные из одной таблицы. Второй уровень - данные из другой таблицы. Между этими табличками связь "многие-ко-многим".
Для организации связи "многие-ко-многим" у Вас должна быть ещё одна таблица ссылок в БД.

То есть если я добавляю дочерний узел, то эта запись должна пойти в базу и прицепиться к родительскому узлу.
В этом случае в БД, в две таблицы нужно добавить по одной записи: одна запись, собственно, дочерний узел, а вторая запись - идентификатор этого узла, плюс идентификатор родительского узла в таблице ссылок.

Для наглядности картинку с окошком прицепила. Вот если я убираю дочерние узлы, то реализуется все на раз-два. А сними начинается куча проблем. Дочерние узля кстати можно создавать и в окошке и выбирать ранее созданные из базы этих объектов (по тз было перетаскиванием, короче там ещё dragand drop замешан))), вот.
Опишите более детально проблемы.


Название: Re: Вопрос сохранения данных.
Отправлено: nata267 от Июнь 27, 2012, 12:10
И еще когда рисую диаграммы, получается быстрее. Как только пишу код, начинаю вязнуть в проблемах интерфейса пользователя и не могу наглядно представить как все это работает. Это к тому что сначала нужно думать а потом делать).


Название: Re: Вопрос сохранения данных.
Отправлено: nata267 от Июнь 27, 2012, 12:11
У меня задача вроде бы и простая, но чето никак. суть в том что у меня есть окошко с QTreeView+QStandardItemModel. Дерево состоит из двух уровней. Первый уровень - это данные из одной таблицы. Второй уровень - данные из другой таблицы. Между этими табличками связь "многие-ко-многим".
Для организации связи "многие-ко-многим" у Вас должна быть ещё одна таблица ссылок в БД.

То есть если я добавляю дочерний узел, то эта запись должна пойти в базу и прицепиться к родительскому узлу.
В этом случае в БД, в две таблицы нужно добавить по одной записи: одна запись, собственно, дочерний узел, а вторая запись - идентификатор этого узла, плюс идентификатор родительского узла в таблице ссылок.

Для наглядности картинку с окошком прицепила. Вот если я убираю дочерние узлы, то реализуется все на раз-два. А сними начинается куча проблем. Дочерние узля кстати можно создавать и в окошке и выбирать ранее созданные из базы этих объектов (по тз было перетаскиванием, короче там ещё dragand drop замешан))), вот.
Опишите более детально проблемы.

естесственно это все есть. то что на картинке это уже выборка из бд. проблеммы опишу попозже. их куча и диаграммы классов которые есть скину)) да и вообще программа уже написана, правда там не все работает, хотелось улучшить и дописать нереализованный функционал)


Название: Re: Вопрос сохранения данных.
Отправлено: nata267 от Июнь 27, 2012, 12:34
Проблема №1:
Есть связываемые объекты это TestBlock и Task. Т.е. тестовые блоки и задания, которые к ним прицеплены.
Есть метод формы, в котором идет загрузка объектов из бд и добавление их в модель вьюхи.

Код:
void TestBlockEditor::setCourse(int courseId)
{
     m_courseId = courseId;
     m_testBlockView->model()->clearTestBlocks();

    // m_actionEdit->setEnabled(false);
    // m_actionCopy->setEnabled(false);
    // m_actionCut->setEnabled(false);
     m_actionDelete->setEnabled(false);

     TestBlockList testBlockList = TestBlock::load(courseId);
     foreach (TestBlock *tb, testBlockList) {
            m_testBlockView->model()->addTestBlock(tb);
            //connect(tb, SIGNAL(changed()), this, SLOT(slotTestBlockChanged()));
     }
}

Вот метод load объекта TestBlock, который возвращает список объектов TestBlock, для открытого проекта.
Код:
QList<TestBlock*> TestBlock::load(int courseId)
{
    QList<TestBlock*> list;

    QSqlQuery query;
    query.exec(QObject::tr("SELECT id FROM test_blocks WHERE course_id=%2").arg(courseId));
    while(query.next()) {
           int id = query.value(0).toInt();
           TestBlock *testBlock = new TestBlock(id);
           list.append(testBlock);
    }

    return list;
 }

Это только в случае без связей. Как добавить связи. Те объект TestBlock должен содержать указатели на объекты Task??
Как это реализовать не через одно место?? Загрузку и привязку объектов. До того как передавать их в модель вьюхи?


Название: Re: Вопрос сохранения данных.
Отправлено: alexis031182 от Июнь 27, 2012, 12:47
Встречный вопрос: зачем Вам нужно жёстко указывать связи между объектами, если модель сама по себе и предназначена для организации связей между объектами?


Название: Re: Вопрос сохранения данных.
Отправлено: nata267 от Июнь 27, 2012, 13:16
Встречный вопрос: зачем Вам нужно жёстко указывать связи между объектами, если модель сама по себе и предназначена для организации связей между объектами?

А как мне понять какие задания привязаны к каким тестовым блокам? Я думала хранить указатели на них. Т.е. допустим выбрать сначала все объекты одного типа для данного проекта, затем все объекты другого типа для данного проекта. Потом в объектах типа "тестовый блок" создать список указателей на объекты типа "задание". и тогда в QStandardItemModel генерировать дерево. и тогда у меня будут 2 глобальных списка объектов этих типов и для каждого объекта я думала поставить статусы, по которым будут производится обновление в базе данных(удаление обновление вставка). но это через одно место, а как вообще надо делать хз.


Название: Re: Вопрос сохранения данных.
Отправлено: nata267 от Июнь 27, 2012, 13:17
Встречный вопрос: зачем Вам нужно жёстко указывать связи между объектами, если модель сама по себе и предназначена для организации связей между объектами?

а вообще не очень поняла смысл вопроса?


Название: Re: Вопрос сохранения данных.
Отправлено: alexis031182 от Июнь 27, 2012, 13:45
А как мне понять какие задания привязаны к каким тестовым блокам?
Вот Вы получаете список тестовых блоков в функции TestBlock::load(). В макросе foreach, в этой функции Вы каждый тестовый блок добавляете сразу в модель. А почему бы не сделать здесь запрос к БД и получить список заданий, относящихся к этому тестовому блоку. И когда Вы добавите в модель текущий тестовый блок, тут же добавляйте в модель тестовые задания этого блока, и естественно с указанием родительского отношения.

Я думала хранить указатели на них. Т.е. допустим выбрать сначала все объекты одного типа для данного проекта, затем все объекты другого типа для данного проекта. Потом в объектах типа "тестовый блок" создать список указателей на объекты типа "задание". и тогда в QStandardItemModel генерировать дерево. и тогда у меня будут 2 глобальных списка объектов этих типов...
Зачем, если имеется модель, строить параллельную иерархию на указателях? Это на мой взгляд избыточно.

и для каждого объекта я думала поставить статусы, по которым будут производится обновление в базе данных(удаление обновление вставка). но это через одно место, а как вообще надо делать хз.
Ну сохранение факта того, что объект изменился действительно необходимо для того же отката изменений или для избежания избыточности при сохранении не изменившихся данных. Вопрос лишь в том, как лучше сделать. Здесь можно посмотреть в сторону паттернов, но если у Вас объекты используют сигнал/слоты, то неприятностей избежать не удастся.


Название: Re: Вопрос сохранения данных.
Отправлено: nata267 от Июнь 27, 2012, 13:59
А как мне понять какие задания привязаны к каким тестовым блокам?
Вот Вы получаете список тестовых блоков в функции TestBlock::load(). В макросе foreach, в этой функции Вы каждый тестовый блок добавляете сразу в модель. А почему бы не сделать здесь запрос к БД и получить список заданий, относящихся к этому тестовому блоку. И когда Вы добавите в модель текущий тестовый блок, тут же добавляйте в модель тестовые задания этого блока, и естественно с указанием родительского отношения.


Те вы хотите сказать что надо написать чтото типа:
Код:
     TestBlockList testBlockList = TestBlock::load(courseId);
     TaskList taskList;
     foreach (TestBlock *tb, testBlockList) {
            m_testBlockView->model()->addTestBlock(tb);
            //connect(tb, SIGNAL(changed()), this, SLOT(slotTestBlockChanged()));
           
            taskList.clear();
            taskList = Task::load(tb->id());
            foreach(Task task, taskList)
            {
                    m_testBlockView->model()->addTaskToTestBlock(task, tb);
                    //connect(task, SIGNAL(changed()), this, SLOT(slotTaskChanged()));
             }
     }

???


Название: Re: Вопрос сохранения данных.
Отправлено: nata267 от Июнь 27, 2012, 14:02
Да круто. И тогда все изменения будут храниться в модели, а при сохранении вносится в базу. Не сообразила сама, спасибо


Название: Re: Вопрос сохранения данных.
Отправлено: alexis031182 от Июнь 27, 2012, 14:04
Те вы хотите сказать что надо написать чтото типа:
...
Да, именно так.


Название: Re: Вопрос сохранения данных.
Отправлено: nata267 от Июнь 28, 2012, 15:53
Теперь сделала так. Все связи хранятся в модели QStandardItemModel. При удалении объектов (до сохранения) указатели на объекты и связи хранятся в командах, из модели удаляются. При отмене удаления снова добавляются в модель.

Это слот по кнопке удалить:

Код:
void TestBlockEditor::slotDelete()
{
    DbObject *selection = m_testBlockView->selectedDbObject();
    if (!selection)
        return;

    if(TestBlock *tb = dynamic_cast<TestBlock *>(selection)) {

        RemoveTestBlockCommand::TaskData taskData = m_testBlockView->model()->tasksOfTestBlock(tb);
       
        RemoveTestBlockCommand *cmd = new RemoveTestBlockCommand(this);
        cmd->init(tb, taskData);
        m_commandHistory->push(cmd);
    }

    if(Task *task = dynamic_cast<Task *>(selection)) {

        TestBlock *tb = m_testBlockView->model()->testBlockOfTask(task);
        if(!tb)
            return;
       
        RemoveTaskCommand *cmd = new RemoveTaskCommand(this);
        cmd->init(task, tb);
        m_commandHistory->push(cmd);
    }
}

Не нравятся dynamic_cast. Как от них избавится??

Это команда, удаляющая тестовый блок:

Код:
RemoveTestBlockCommand::RemoveTestBlockCommand(TestBlockEditor *editor):
      QUndoCommand(QObject::tr("Удалить тестовый блок")),
      m_editor(editor),
      m_testBlock(0)
{
}

void RemoveTestBlockCommand::init(TestBlock *tb, const TaskData &taskData)
{
    Q_ASSERT(m_testBlock == 0);
    m_testBlock = tb;
    m_taskData = taskData;
}

void RemoveTestBlockCommand::redo()
{
    m_editor->unmanageTestBlock(m_testBlock);
}

void RemoveTestBlockCommand::undo()
{
    m_editor->manageTestBlock(m_testBlock, m_taskData);
}

И методы manageTestBlock, unmanageTestBlock окошка, которые удаляют-добавляют элемент в модель

Код:
void TestBlockEditor::manageTestBlock(TestBlock *tb, const QList<Task*> &dataTask)
{
    QModelIndex index = m_testBlockView->model()->addTestBlock(tb);
    m_testBlockView->setExpanded(index, true);
    m_testBlockView->setCurrentIndex(index);
    //connect(tb, SIGNAL(changed()), this, SLOT(slotTestBlockChanged()));

    foreach(Task *task, dataTask)
    {
        m_testBlockView->model()->addTaskToTestBlock(task, tb);
        //connect(task, SIGNAL(changed()), this, SLOT(slotTaskChanged()));
    }
}

void TestBlockEditor::unmanageTestBlock(TestBlock *tb)
{
    //disconnect(tb, SIGNAL(changed()), this, SLOT(slotTestBlockChanged()));

    const QModelIndex idx = m_testBlockView->model()->findObject(tb);
    if (idx.isValid())
        m_testBlockView->model()->removeRow(idx.row());
}

То есть отмена действий работает. Теперь проблемы с общим сохранением( Если делать обход модели, то удаленных элементов в ней нет. НО для них можно вести отдельный список. Задание в этой форме не должны удаляться а только связи с тестовыми блоками. Получается нужно хранить ещё и список этих удаленных связей? А при добавлении задания (которые могут быть как новыми так и существующими), нужно добавлять не только связь но и заданиие если оно новое. Получается очень запутанно.  


Название: Re: Вопрос сохранения данных.
Отправлено: DmitryM от Июнь 28, 2012, 22:52
Для организации дерева использовал бы паттерн компоновщик (http://citforum.ru/SE/project/pattern/#3.1.5), т.к. использовал бы иерархию объектов.
Для откатов петтерн хранитель (http://citforum.ru/SE/project/pattern/p_2.shtml#3.2.10), и путь этим занимаются сами объекты в узлах/листьях дерева.
Сохранение всего этого дела, сделал бы через сериализацию в xml.


Название: Re: Вопрос сохранения данных.
Отправлено: nata267 от Июнь 29, 2012, 08:50
Для организации дерева использовал бы паттерн компоновщик (http://citforum.ru/SE/project/pattern/#3.1.5), т.к. использовал бы иерархию объектов.
Для откатов петтерн хранитель (http://citforum.ru/SE/project/pattern/p_2.shtml#3.2.10), и путь этим занимаются сами объекты в узлах/листьях дерева.
Сохранение всего этого дела, сделал бы через сериализацию в xml.


как понять через сериализацию в xml. у меня бд mysql


Название: Re: Вопрос сохранения данных.
Отправлено: DmitryM от Июнь 29, 2012, 11:07
Хранение деревьев в реляционных базах данных нетривиальная немного не тривиальная задача.
Одно из возможных решений использовать ORM(Object-relational mapping).


Название: Re: Вопрос сохранения данных.
Отправлено: nata267 от Июнь 29, 2012, 11:39
Хранение деревьев в реляционных базах данных нетривиальная немного не тривиальная задача.
Одно из возможных решений использовать ORM(Object-relational mapping).

это не дерево. а связь многие ко многим, но в проекте присутствуют и деревья, задача состоит в том чтобы сохранить проект целиком, со всеми изменениями вносимыми в структуру. изменения могут быть значительными и нет, поэтому целиком базу данных переписывать затратно. Надо как то следить за удалением-добавлением объектов и связями между ними.  То есть во первых получается что нужно загрузить все объекты проекта и связи между ними в оперативную память. И во вторых при каждом действии пользователя. Следить какие объекты и связи поменялись. Как их хранить и как за ними следить. Вот в чем вопрос?


Название: Re: Вопрос сохранения данных.
Отправлено: nata267 от Июнь 29, 2012, 11:48
Возможно, действительно нужно удалить все прежние данные и выгрузить данные в бд или xml из оперативной памяти.


Название: Re: Вопрос сохранения данных.
Отправлено: alexis031182 от Июнь 29, 2012, 11:58
Не очень понятно, зачем хранить в постоянной памяти (в той же БД) данные для undo. По идее, эта информация нужна лишь на время одной сессии работы приложения.


Название: Re: Вопрос сохранения данных.
Отправлено: nata267 от Июнь 29, 2012, 13:01
Не очень понятно, зачем хранить в постоянной памяти (в той же БД) данные для undo. По идее, эта информация нужна лишь на время одной сессии работы приложения.

храним полюбому в оперативной, вопрос в том как сохранять. ставить состояния (inserted, deleted, modified) объектов или стирать все данные по проекту и записывать все заново (т.е. во всех табличках по проекту project_id). я уже склоняюсь к последнему, так как со статусами замороченно. следить за ними по каждому действию пользователя


Название: Re: Вопрос сохранения данных.
Отправлено: alexis031182 от Июнь 29, 2012, 13:11
храним полюбому в оперативной, вопрос в том как сохранять. ставить состояния (inserted, deleted, modified) объектов или стирать все данные по проекту и записывать все заново (т.е. во всех табличках по проекту project_id). я уже склоняюсь к последнему, так как со статусами замороченно. следить за ними по каждому действию пользователя
А почему заморочено? У Вас элементы модели (объекты) имеют параметр, обозначающий статус. Для рисования во вьюхе этот параметр должен быть определяющим, должна ли модель отдавать ей для показа каждый конкретный элемент или не должна. И для общего сохранения в БД тоже самое, только значение этого параметра будет определять, следует ли удалить, модифицировать запись или оставить как есть.


Название: Re: Вопрос сохранения данных.
Отправлено: nata267 от Июнь 29, 2012, 13:14
храним полюбому в оперативной, вопрос в том как сохранять. ставить состояния (inserted, deleted, modified) объектов или стирать все данные по проекту и записывать все заново (т.е. во всех табличках по проекту project_id). я уже склоняюсь к последнему, так как со статусами замороченно. следить за ними по каждому действию пользователя
А почему заморочено? У Вас элементы модели (объекты) имеют параметр, обозначающий статус. Для рисования во вьюхе этот параметр должен быть определяющим, должна ли модель отдавать ей для показа каждый конкретный элемент или не должна. И для общего сохранения в БД тоже самое, только значение этого параметра будет определять, следует ли удалить, модифицировать запись или оставить как есть.

да, но только надо менять эти состояния при каждом действии пользователя, включая отмену и возврат и состояние не только самих объектов но и связей. у связей тоже могут быть свойства (например порядковый номер) и их тоже можно добавлять удалять. Очень много лишних действий получается


Название: Re: Вопрос сохранения данных.
Отправлено: alexis031182 от Июнь 29, 2012, 13:26
А что за связи между объектами, помимо отношения "Родитель - Ребёнок"?


Название: Re: Вопрос сохранения данных.
Отправлено: nata267 от Июнь 29, 2012, 13:47
А что за связи между объектами, помимо отношения "Родитель - Ребёнок"?

я же уже писала многие-ко-многим, то есть в проекте есть отдельно база тестовых блоков и отдельно база заданий. задания можно цеплять к разным тестовым блокам. или например есть темы, есть задания. заданиям можно назначать разные темы.


Название: Re: Вопрос сохранения данных.
Отправлено: alexis031182 от Июнь 29, 2012, 14:31
я же уже писала многие-ко-многим, то есть в проекте есть отдельно база тестовых блоков и отдельно база заданий. задания можно цеплять к разным тестовым блокам. или например есть темы, есть задания. заданиям можно назначать разные темы.
А как непосредственно в модели Вы реализовали эти связи? Например, храните несколько копий объектов задания, принадлежащего разным темам, или один объект задания, содержащий некие ссылки на темы, в которых это задание должно содержаться? В модели ведь дерево.


Название: Re: Вопрос сохранения данных.
Отправлено: nata267 от Июнь 29, 2012, 15:04
я же уже писала многие-ко-многим, то есть в проекте есть отдельно база тестовых блоков и отдельно база заданий. задания можно цеплять к разным тестовым блокам. или например есть темы, есть задания. заданиям можно назначать разные темы.
А как непосредственно в модели Вы реализовали эти связи? Например, храните несколько копий объектов задания, принадлежащего разным темам, или один объект задания, содержащий некие ссылки на темы, в которых это задание должно содержаться? В модели ведь дерево.

У меня один объект задания. Если он относится к нескольким тестовым блокам, то создаю дочерние узлы и помещаю указатель на это задание в каждый узел. При сохранении я сохраняю сначала задания, потом тестовые блоки, а в конце связи между ними. Все эти объекты я планирую зарегистрировать в одном объекте типа projectDataBase() ; В том числе связи как отдельный тип объектов


Название: Re: Вопрос сохранения данных.
Отправлено: nata267 от Июнь 29, 2012, 15:32
В дизайнере используется строитель, который  при выгрузке строит xml. Если провести параллель и сделать чтото, только вместо xml база данных.


Название: Re: Вопрос сохранения данных.
Отправлено: DmitryM от Июнь 29, 2012, 16:27
xml так же является базой данных  ;)
В дизайнере используется строитель, который  при выгрузке строит xml. Если провести параллель и сделать чтото, только вместо xml база данных.
тогда проще взять ORM, к примеру ODB (http://www.codesynthesis.com/products/odb/)


Название: Re: Вопрос сохранения данных.
Отправлено: Igors от Июнь 30, 2012, 02:42
Тема хорошая, "по делу", но увы, специфики слишком много. Пробовал вникнуть, но нереально, особенно для человека далекого от СУБД. Даже что такое тестовый блок - четко не представляю и.т.п. Плохо что нет поста где сосредоточены термины, описания - размазано на несколько. Лучше сформулировать задачу как бы "в пробирке", чтобы можно было сосредоточиться на принципиальных вещах без многочисленных технических деталей. Понятно что это гораздо легче советовать чем сделать, но так, мне пытаться обсуждать не понимая задачи - лучше промолчать


Название: Re: Вопрос сохранения данных.
Отправлено: nata267 от Июль 02, 2012, 08:41
xml так же является базой данных  ;)
В дизайнере используется строитель, который  при выгрузке строит xml. Если провести параллель и сделать чтото, только вместо xml база данных.
тогда проще взять ORM, к примеру ODB (http://www.codesynthesis.com/products/odb/)

а по быстродействтию что эффективнее записать в xml или в бд mysql??


Название: Re: Вопрос сохранения данных.
Отправлено: nata267 от Июль 02, 2012, 08:44
Тема хорошая, "по делу", но увы, специфики слишком много. Пробовал вникнуть, но нереально, особенно для человека далекого от СУБД. Даже что такое тестовый блок - четко не представляю и.т.п. Плохо что нет поста где сосредоточены термины, описания - размазано на несколько. Лучше сформулировать задачу как бы "в пробирке", чтобы можно было сосредоточиться на принципиальных вещах без многочисленных технических деталей. Понятно что это гораздо легче советовать чем сделать, но так, мне пытаться обсуждать не понимая задачи - лучше промолчать

"тестовые блоки" и "задания" - это сущности бд из моей задачи.


Название: Re: Вопрос сохранения данных.
Отправлено: DmitryM от Июль 03, 2012, 11:50
а по быстродействтию что эффективнее записать в xml или в бд??
Вот определение БД (http://ru.wikipedia.org/wiki/%D0%91%D0%B0%D0%B7%D0%B0_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85) где там эффективность записи?


Название: Re: Вопрос сохранения данных.
Отправлено: Dr.Vlad от Июль 03, 2012, 18:53
Почему нельзя по сигналу от виджета слать запрос (insert, update, delete) к БД и уже в таблицах менять эти данные. Зачем использовать посредника? Это костыль.

Вопрос в том, когда это изменение обрабатывать через запрос?
По закрытию виджета или же по изменению данных в виджете.

У нас в конторе используют xml тогда, когда до базы напрямую дотянуться нельзя. То есть, когда она на другом компе без сетевого доступа.


Название: Re: Вопрос сохранения данных.
Отправлено: nata267 от Август 10, 2012, 16:03
xml так же является базой данных  ;)
В дизайнере используется строитель, который  при выгрузке строит xml. Если провести параллель и сделать чтото, только вместо xml база данных.
тогда проще взять ORM, к примеру ODB (http://www.codesynthesis.com/products/odb/)

есть ли для с++ ORM на подобии NHibernate? делаем проект на С#, понравилась эта библиотека