{"id":8277,"date":"2025-05-15T12:33:12","date_gmt":"2025-05-15T10:33:12","guid":{"rendered":"https:\/\/pomoc.comarch.pl\/cee\/?post_type=ht_kb&#038;p=8277"},"modified":"2025-06-03T13:49:34","modified_gmt":"2025-06-03T11:49:34","slug":"dziennik-zmian","status":"publish","type":"ht_kb","link":"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/dziennik-zmian\/","title":{"rendered":"Dziennik zmian"},"content":{"rendered":"<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_82_2 ez-toc-wrap-left counter-hierarchy ez-toc-counter ez-toc-custom ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Spis tre\u015bci<\/p>\n<span class=\"ez-toc-title-toggle\"><a href=\"#\" class=\"ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle\" aria-label=\"Prze\u0142\u0105cznik Spisu Tre\u015bci\"><span class=\"ez-toc-js-icon-con\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/span><\/a><\/span><\/div>\n<nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/dziennik-zmian\/#Wprowadzenie\" >Wprowadzenie<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/dziennik-zmian\/#Grupa_docelowa\" >Grupa docelowa<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/dziennik-zmian\/#Opis\" >Opis<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/dziennik-zmian\/#Interfejs_programistyczny\" >Interfejs programistyczny<\/a><ul class='ez-toc-list-level-4' ><li class='ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/dziennik-zmian\/#Aktywacja_dziennika_zmian\" >Aktywacja dziennika zmian<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/dziennik-zmian\/#Dynamiczne_obiekty_biznesowe\" >Dynamiczne obiekty biznesowe<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/dziennik-zmian\/#Zapytania_do_dziennika_zmian\" >Zapytania do dziennika zmian<\/a><ul class='ez-toc-list-level-5' ><li class='ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/dziennik-zmian\/#Obiekt_zapytania_JournalQuery\" >Obiekt zapytania: JournalQuery<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/dziennik-zmian\/#Zapytanie_zmienia_sie_indywidualnie\" >Zapytanie zmienia si\u0119 indywidualnie<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-10\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/dziennik-zmian\/#Zapytanie_podsumowujace_zmiany\" >Zapytanie podsumowuj\u0105ce zmiany<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-11\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/dziennik-zmian\/#Dostep_do_zmian\" >Dost\u0119p do zmian<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-12\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/dziennik-zmian\/#Przyklad_zapytania_do_dziennika_zmian\" >Przyk\u0142ad zapytania do dziennika zmian<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-13\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/dziennik-zmian\/#Lista_transferowa\" >Lista transferowa<\/a><ul class='ez-toc-list-level-5' ><li class='ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-14\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/dziennik-zmian\/#Rejestrowanie_listy_transferowej\" >Rejestrowanie listy transferowej<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-15\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/dziennik-zmian\/#Przyklad_kontrolera_CisTransferListController\" >Przyk\u0142ad kontrolera CisTransferListController<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-16\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/dziennik-zmian\/#Odpytywanie_listy_transferowej\" >Odpytywanie listy transferowej<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-17\" href=\"https:\/\/pomoc.comarch.pl\/cee\/index.php\/documentation\/dziennik-zmian\/#Przyklad_zapytania_o_liste_transferowa\" >Przyk\u0142ad zapytania o list\u0119 transferow\u0105<\/a><\/li><\/ul><\/li><\/ul><\/li><\/ul><\/nav><\/div>\n<h3 id=\"wprowadzenie\" ><span class=\"ez-toc-section\" id=\"Wprowadzenie\"><\/span>Wprowadzenie<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Dziennik zmian jest funkcj\u0105 dziennika dla historii zmiennych biznesowych i rejestruje zdarzenia dla jednostek biznesowych. Dla ka\u017cdej jednostki biznesowej i instancji bazy danych mo\u017cna okre\u015bli\u0107, czy zmiany powinny by\u0107 rejestrowane. Persistence service dba zatem nie tylko o informacje o zmianach dla jednostek biznesowych, ale tak\u017ce o wpisy w dzienniku zmian. Rejestrowane s\u0105 tylko pomy\u015blnie zako\u0144czone transakcje najwy\u017cszego poziomu.<\/p>\n<p>Dzi\u0119ki dziennikowi zmian, m.in. zmiany w danych podstawowych mog\u0105 by\u0107 w pe\u0142ni odnotowane, a tym samym mo\u017cliwe do weryfikacji. Dziennik zmian mo\u017ce by\u0107 aktywowany i przeszukiwany dla dowolnych jednostek biznesowych przy u\u017cyciu programowania dostosowuj\u0105cego.<\/p>\n<p>W przeciwie\u0144stwie do dziennika zmian, lista transfer\u00f3w rejestruje tylko, \u017ce instancja jednostki biznesowej zosta\u0142a zmieniona od czasu ostatniego przetworzenia tej instancji. Lista transferu mo\u017ce by\u0107 u\u017cywana w szczeg\u00f3lno\u015bci podczas wymiany danych z systemami zewn\u0119trznymi.<\/p>\n<h3 id=\"grupa-docelowa\" ><span class=\"ez-toc-section\" id=\"Grupa_docelowa\"><\/span>Grupa docelowa<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<ul>\n<li>Deweloper<\/li>\n<li>Konsultanci techniczni<\/li>\n<\/ul>\n<h3 id=\"opis\" ><span class=\"ez-toc-section\" id=\"Opis\"><\/span>Opis<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Dziennik zmian jest zintegrowany za po\u015brednictwem interfejsu programistycznego. Aby mo\u017cna by\u0142o korzysta\u0107 z dziennika zmian, rejestrowanie zmian dla ka\u017cdej jednostki biznesowej musi by\u0107 aktywowany przez program.<\/p>\n<p>Za ka\u017cdym razem, gdy zarejestrowana jednostka biznesowa lub jeden z jego podmiot\u00f3w zale\u017cnych jest zmieniany, wpisy s\u0105 zapisywane w dzienniku zmian. Istniej\u0105 nast\u0119puj\u0105ce rodzaje wpis\u00f3w:<\/p>\n<ul>\n<li><strong>Nowo\u015b\u0107<\/strong> &#8211; gdy tworzony jest nowy obiekt biznesowy, zapisywane s\u0105 wszystkie atrybuty nowego obiektu.<\/li>\n<\/ul>\n<ul>\n<li><strong>Zmiana<\/strong> &#8211; gdy obiekt biznesowy jest zmieniany, zmienione atrybuty s\u0105 zapisywane z ich starymi i nowymi warto\u015bciami.<\/li>\n<\/ul>\n<ul>\n<li><strong>Usuni\u0119cie<\/strong> &#8211; po usuni\u0119ciu obiektu biznesowego zapisywane s\u0105 wszystkie atrybuty usuni\u0119tego obiektu.<\/li>\n<\/ul>\n<p>Dla ka\u017cdego wpisu zapisywany jest u\u017cytkownik, kt\u00f3ry go utworzy\u0142 oraz czas, w kt\u00f3rym zosta\u0142 utworzony. Oznacza to, \u017ce mo\u017cna prze\u015bledzi\u0107 ca\u0142\u0105 histori\u0119 zmian jednostki biznesowej.<\/p>\n<p><a href=\"https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2025\/05\/rejestr-zmian.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-30569\" src=\"https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2025\/05\/rejestr-zmian.jpg\" alt=\"\" width=\"846\" height=\"414\" srcset=\"https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2025\/05\/rejestr-zmian.jpg 846w, https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2025\/05\/rejestr-zmian-300x147.jpg 300w, https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2025\/05\/rejestr-zmian-768x376.jpg 768w, https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2025\/05\/rejestr-zmian-50x24.jpg 50w, https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2025\/05\/rejestr-zmian-600x294.jpg 600w, https:\/\/pomoc.comarch.pl\/cee\/wp-content\/uploads\/2025\/05\/rejestr-zmian-320x157.jpg 320w\" sizes=\"auto, (max-width: 846px) 100vw, 846px\" \/><\/a><\/p>\n<p style=\"text-align: center;\">Przyk\u0142ad rejestrowania dziennika zmian<\/p>\n<p>W przyk\u0142adzie zam\u00f3wienie z jedn\u0105 pozycj\u0105 jest najpierw wprowadzane przez u\u017cytkownika X, nast\u0119pnie kolejna pozycja jest dodawana przez u\u017cytkownika Y, w kolejnym kroku zam\u00f3wienie jest usuwane przez u\u017cytkownika X.<\/p>\n<p>Dziennik zmian rejestruje wszystkie dost\u0119py do obiekt\u00f3w (<em>putObject<\/em>, <em>deleteObject<\/em>) za po\u015brednictwem <em>CisObjectManager<\/em>. Zmiany poprzez <em>putUpdateStatement<\/em> nie s\u0105 rejestrowane. <em>UpdateStatements<\/em> s\u0105 zwykle u\u017cywane tylko dla danych istotnych biznesowo podczas reorganizacji. Je\u015bli tabele s\u0105 zmieniane bezpo\u015brednio za pomoc\u0105 narz\u0119dzi bazy danych (SQL), zmiany nie s\u0105 rejestrowane.<\/p>\n<p>Gdy zmiany s\u0105 wprowadzane i usuwane, stary status zmienionego obiektu biznesowego jest r\u00f3wnie\u017c zapisywany w dzienniku zmian. Oznacza to, \u017ce mo\u017cna znale\u017a\u0107 niezarejestrowane zmiany.<\/p>\n<p>Tylko zawarto\u015b\u0107 monitorowanej jednostki biznesowej jest rejestrowana w dzienniku zmian. Jednostka biznesowa zazwyczaj odwo\u0142uje si\u0119 do innych jednostek biznesowych za po\u015brednictwem ich kluczy technicznych (cz\u0119sto identyfikator\u00f3w GUID). Je\u015bli te jednostki biznesowe, do kt\u00f3rych istniej\u0105 odniesienia, nie s\u0105 monitorowane, mog\u0105 zosta\u0107 w pewnym momencie usuni\u0119te. W takim przypadku klucz techniczny nie mo\u017ce by\u0107 ju\u017c rozwi\u0105zany.<\/p>\n<section class=\"document-alert-box example\"><div class=\"document-alert-title\">Przyk\u0142ad<\/div><div class=\"document-alert-content\">Je\u015bli zam\u00f3wienie sprzeda\u017cy jest monitorowane, ale partner ju\u017c nie, w\u00f3wczas relacja z klientem nie mo\u017ce by\u0107 ju\u017c rozwi\u0105zana, je\u015bli dany partner zosta\u0142 zreorganizowany.<\/div><\/section>\n<p>Je\u015bli monitowana jest jednostka biznesowa, nale\u017cy r\u00f3wnie\u017c monitorowa\u0107 najwa\u017cniejsze jednostki biznesowe odwo\u0142uj\u0105ce si\u0119 do tej jednostki. Dotyczy to w szczeg\u00f3lno\u015bci danych podstawowych, takich jak <em>Partnerzy<\/em> i <em>Artyku\u0142y<\/em>. Je\u015bli jednostka biznesowa, do kt\u00f3rego istnieje odwo\u0142anie, zostanie usuni\u0119ta, mo\u017cna j\u0105 r\u00f3wnie\u017c otworzy\u0107 za pomoc\u0105 dziennika zmian.<\/p>\n<p class=\"\" data-start=\"370\" data-end=\"471\">Je\u015bli monitoruje si\u0119 jednostk\u0119 biznesow\u0105 za pomoc\u0105 dziennika zmian, nale\u017cy zwr\u00f3ci\u0107 uwag\u0119 na to, \u017ce:<\/p>\n<ul data-start=\"473\" data-end=\"611\">\n<li class=\"\" data-start=\"473\" data-end=\"544\">\n<p class=\"\" data-start=\"475\" data-end=\"544\">dziennik zmian w okre\u015blonych przypadkach mo\u017ce sta\u0107 si\u0119 bardzo du\u017cy<\/p>\n<\/li>\n<\/ul>\n<ul>\n<li class=\"\" data-start=\"545\" data-end=\"611\">\n<p class=\"\" data-start=\"547\" data-end=\"611\">zapis dziennika zmian powoduje wi\u0119ksze obci\u0105\u017cenie bazy danych<\/p>\n<\/li>\n<\/ul>\n<p class=\"\" data-start=\"613\" data-end=\"829\">Dotyczy to w szczeg\u00f3lno\u015bci sytuacji, gdy dziennik zmian zostanie aktywowany dla obiekt\u00f3w biznesowych o bardzo du\u017cej liczbie obiekt\u00f3w lub gdy obiekty biznesowe charakteryzuj\u0105 si\u0119 bardzo wysok\u0105 cz\u0119stotliwo\u015bci\u0105 zmian.<\/p>\n<p class=\"\" data-start=\"831\" data-end=\"997\">Przed aktywowaniem dziennika zmian nale\u017cy upewni\u0107 si\u0119, \u017ce system jest w stanie przetworzy\u0107 dodatkowe dane w akceptowalnym czasie i przy akceptowalnym zu\u017cyciu pami\u0119ci.<\/p>\n<h3 id=\"interfejs-programistyczny\" ><span class=\"ez-toc-section\" id=\"Interfejs_programistyczny\"><\/span>Interfejs programistyczny<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Dziennik modyfikacji mo\u017ce by\u0107 kontrolowany przez <em>ModificationJournalManager<\/em>. Z kolei <em>ModificationJournalManager<\/em> mo\u017ce by\u0107 odpytywany przez <em>CisEnvironment<\/em>. <em>ModificationJournalManager<\/em> zawiera metody aktywacji lub dezaktywacji dziennika zmian dla jednostki biznesowej oraz kwerendy dziennika zmian.<\/p>\n<p>Korzystanie z interfejsu programistycznego <em>ModificationJournal<\/em> opisano w kolejnych rozdzia\u0142ach.<\/p>\n<h4 id=\"aktywacja-dziennika-zmian\" ><span class=\"ez-toc-section\" id=\"Aktywacja_dziennika_zmian\"><\/span>Aktywacja dziennika zmian<span class=\"ez-toc-section-end\"><\/span><\/h4>\n<p>Dziennik zmian mo\u017cna aktywowa\u0107 dla jednostek biznesowych za pomoc\u0105 aplikacji <em>Aktywacja dziennika zmian<\/em>. Ponadto dziennik zmian mo\u017cna r\u00f3wnie\u017c aktywowa\u0107 i dezaktywowa\u0107 za pomoc\u0105 aplikacji <em>CisModificationJournalManager<\/em>.<\/p>\n<p>Dziennik zmian jest aktywowany lub dezaktywowany dla jednostki biznesowej w bazie danych przy u\u017cyciu metody <em>setActive<\/em>.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">void setActive(byte[] databaseGuid, byte[] classGuid,\n\nboolean active);<\/pre>\n<p>Metoda <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">isActive<\/code> mo\u017ce by\u0107 u\u017cyta do zapytania, czy dziennik zmian dla jednostki biznesowej jest aktywny w bazie danych:<\/p>\n<p><code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">boolean isActive(byte[] databaseGuid, byte[] classGuid);<\/code><\/p>\n<section class=\"document-alert-box example\"><div class=\"document-alert-title\">Przyk\u0142ad<\/div><div class=\"document-alert-content\">Aktywacja dziennika zmian dla jednostki biznesowej <em>Partnerzy<\/em> w aktywnej bazie danych OLTP:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">CisEnvironment env = CisEnvironment.getInstance();\n\nCisModificationJournalManager mjm =\n\nenv.getModificationJournalManager();\n\nmjm.setActive(env.getDatabaseGuid(),Partner._classGuid,true);<\/pre>\n<p><\/div><\/section>\n<h4 id=\"dynamiczne-obiekty-biznesowe\" ><span class=\"ez-toc-section\" id=\"Dynamiczne_obiekty_biznesowe\"><\/span>Dynamiczne obiekty biznesowe<span class=\"ez-toc-section-end\"><\/span><\/h4>\n<p>Dynamiczne obiekty biznesowe albo rozszerzaj\u0105 istniej\u0105c\u0105 jednostk\u0119 biznesow\u0105, albo s\u0105 samodzielne i nie maj\u0105 do niej odniesienia. Aby zmiany w dynamicznych obiektach biznesowych by\u0142y rejestrowane, musi istnie\u0107 relacja mi\u0119dzy instancj\u0105 dynamicznego obiektu biznesowego a instancj\u0105 jednostki biznesowej.<\/p>\n<p>Dynamiczne obiekty biznesowe, kt\u00f3re zosta\u0142y utworzone jako rozszerzenia obiekt\u00f3w, takie jak pola zdefiniowane przez u\u017cytkownika i charakterystyki artyku\u0142\u00f3w, maj\u0105 relacj\u0119 z dok\u0142adnie jedn\u0105 jednostk\u0105 biznesow\u0105. Natomiast dynamiczne obiekty biznesowe, kt\u00f3re s\u0105 przywo\u0142ywane z jednostki biznesowej za po\u015brednictwem identyfikatora GUID, nie maj\u0105 tej relacji.<\/p>\n<p>Je\u015bli dynamiczny obiekt biznesowy nie ma relacji z jednostk\u0105 biznesow\u0105, w\u00f3wczas za pomoc\u0105 metody <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">void set_entityKey(byte[] entityTimeDependentKey)<\/code> mo\u017cna ustanowi\u0107 t\u0119 relacj\u0119. Je\u015bli jednostka biznesowa jest zale\u017cna od czasu, nale\u017cy ustawi\u0107 czasowy klucz g\u0142\u00f3wny w dynamicznym obiekcie biznesowym, w przeciwnym razie nale\u017cy ustawi\u0107 normalny klucz g\u0142\u00f3wny. W ten sam spos\u00f3b mo\u017cna r\u00f3wnie\u017c ustawi\u0107 <em>InstanceString<\/em> dla dynamicznego obiektu biznesowego:<\/p>\n<p><code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">void set_instanceString(String instanceString)<\/code><\/p>\n<p>Klucz jednostki biznesowej i <em>InstanceString<\/em> musz\u0105 by\u0107 ustawione na instancji dynamicznego obiektu biznesowego, zanim instancja zostanie przes\u0142ana do <em>Transaction Manager<\/em> za pomoc\u0105 <em>putObject<\/em>.<\/p>\n<h4 id=\"zapytania-do-dziennika-zmian\" ><span class=\"ez-toc-section\" id=\"Zapytania_do_dziennika_zmian\"><\/span>Zapytania do dziennika zmian<span class=\"ez-toc-section-end\"><\/span><\/h4>\n<p>Dziennik zmian mo\u017ce by\u0107 przeszukiwany poprzez <em>ModificationJournalManager<\/em>. Zmiany w dzienniku zmian mog\u0105 by\u0107 podsumowane dla ka\u017cdej instancji jednostki biznesowej lub ka\u017cda zmiana mo\u017ce by\u0107 wyprowadzana indywidualnie.<\/p>\n<p>Zmiany w instancji jednostki biznesowej s\u0105 zwracane w obiektach klasy <em>JournalEntity<\/em>.<\/p>\n<h5 id=\"obiekt-zapytania-journalquery\" ><span class=\"ez-toc-section\" id=\"Obiekt_zapytania_JournalQuery\"><\/span>Obiekt zapytania: JournalQuery<span class=\"ez-toc-section-end\"><\/span><\/h5>\n<p>Obiekt klasy <em>JournalQuery<\/em> mo\u017ce zosta\u0107 utworzony przez <em>ModificationJournalManager<\/em> przy u\u017cyciu metody <em>createJournalQuery<\/em>. Klasa <em>JournalQuery<\/em> zawiera parametry zapytania do dziennika zmian. Aby ograniczy\u0107 zapytanie do dziennika zmian do odpowiedniego parametru zapytania, nale\u017cy u\u017cy\u0107 nazw sta\u0142ych. nale\u017cy u\u017cy\u0107 klasy <em>com.cisag.pgm.objsearch.SelectionSupport<\/em> do ustawienia <em>Selection-Strin<\/em>g dla parametru zapytania.<\/p>\n<h5 id=\"zapytanie-zmienia-sie-indywidualnie\" ><span class=\"ez-toc-section\" id=\"Zapytanie_zmienia_sie_indywidualnie\"><\/span>Zapytanie zmienia si\u0119 indywidualnie<span class=\"ez-toc-section-end\"><\/span><\/h5>\n<p>Je\u015bli ka\u017cda zmiana jest odpytywana indywidualnie, <em>JournalEntity<\/em> jest tworzony dla ka\u017cdej zmiany i zwracany indywidualnie (zmiany nie s\u0105 grupowane). Nale\u017cy otworzy\u0107 transakcj\u0119 na bazie danych, z kt\u00f3rej ma zosta\u0107 pobra\u0107 dziennik zmian. Nast\u0119pnie mo\u017cna za pomoc\u0105 metody Nast\u0119pnie mo\u017cna u\u017cy\u0107 metody<\/p>\n<p><code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">CisIterator retrieveJournalEntities(JournalQuery query);<br \/>\n<\/code><\/p>\n<p>mo\u017cna pobra\u0107 dziennik zmian dla zapytania <em>JournalQuery<\/em>. Podczas pobierania dziennika zmian transakcja musi pozosta\u0107 otwarta. Po wys\u0142aniu zapytania do dziennika zmian nale\u017cy najpierw zamkn\u0105\u0107 iterator, a nast\u0119pnie, je\u015bli to konieczne, transakcj\u0119.<\/p>\n<h5 id=\"zapytanie-podsumowujace-zmiany\" ><span class=\"ez-toc-section\" id=\"Zapytanie_podsumowujace_zmiany\"><\/span>Zapytanie podsumowuj\u0105ce zmiany<span class=\"ez-toc-section-end\"><\/span><\/h5>\n<p class=\"\" data-start=\"0\" data-end=\"457\">Je\u015bli zmiany s\u0105 pobierane w formie podsumowanej, w\u00f3wczas wszystkie zmiany danej instancji jednostki biznesowej s\u0105 zapisywane w <em>JournalEntity<\/em>. Dzi\u0119ki temu mo\u017cliwe jest przeprowadzenie szczeg\u00f3\u0142owej analizy historii zmian obiektu. Wad\u0105 tego podej\u015bcia jest fakt, \u017ce pe\u0142na instancja jednostki biznesowej wraz ze wszystkimi zmianami jest \u0142adowana do pami\u0119ci g\u0142\u00f3wnej.<\/p>\n<p class=\"\" data-start=\"459\" data-end=\"585\">Aby zapyta\u0107 o dziennik zmian, konieczne jest otwarcie transakcji w bazie danych. Nast\u0119pnie mo\u017cna skorzysta\u0107 z metody:<\/p>\n<p><code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">Collection retrieveJournalEntities(JournalQuery query);<br \/>\n<\/code><\/p>\n<p class=\"\" data-start=\"639\" data-end=\"784\">pozwalaj\u0105cej pobra\u0107 dziennik zmian dla okre\u015blonego zapytania <em>JournalQuery<\/em>. Po zako\u0144czeniu pobierania dziennika zmian nale\u017cy zamkn\u0105\u0107 transakcj\u0119.<\/p>\n<p class=\"\" data-start=\"786\" data-end=\"897\">Ze wzgl\u0119d\u00f3w historycznych dost\u0119pne s\u0105 jeszcze nast\u0119puj\u0105ce metody zapyta\u0144, jednak nie zaleca si\u0119 ich stosowania.<\/p>\n<p>Za pomoc\u0105 metod:<\/p>\n<p><code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">Collection retrieveJournalEntities(byte[] databaseGuid, byte[] key,<br \/>\n<\/code><\/p>\n<p><code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\"> Date from, Date until);<\/code><\/p>\n<p><code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\"><br \/>\nCollection retrieveJournalEntities(byte[] databaseGuid, byte[] key,<br \/>\n<\/code><\/p>\n<p><code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">Date validFrom,<br \/>\nDate from, <\/code><\/p>\n<p><code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">Date until);<\/code><\/p>\n<p class=\"\" data-start=\"368\" data-end=\"534\">mo\u017cna pobra\u0107 dziennik zmian dla okre\u015blonej jednostki biznesowej przy u\u017cyciu klucza g\u0142\u00f3wnego jednostki biznesowej (key) w okre\u015blonym przedziale czasowym (from &lt;= t &lt; until).<\/p>\n<p class=\"\" data-start=\"536\" data-end=\"616\">Alternatywnie, dziennik zmian mo\u017cna r\u00f3wnie\u017c pobra\u0107 za pomoc\u0105 <em>InstanceString<\/em>:<\/p>\n<p data-start=\"536\" data-end=\"616\"><code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">Collection retrieveJournalEntitysByInstanceString(<br \/>\n<\/code><\/p>\n<p data-start=\"536\" data-end=\"616\"><code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">byte[] databaseGuid, byte[] entityClassGuid,<br \/>\n<\/code><\/p>\n<p data-start=\"536\" data-end=\"616\"><code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">String instanceSelectionString,<br \/>\n<\/code><\/p>\n<p data-start=\"536\" data-end=\"616\"><code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">String changeTimeSelectionString,<br \/>\n<\/code><\/p>\n<p data-start=\"536\" data-end=\"616\"><code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">String entityUpdateTypeSelectionString);<\/code><\/p>\n<div class=\"flex max-w-full flex-col grow\">\n<div class=\"min-h-8 text-message relative flex w-full flex-col items-end gap-2 text-start break-words whitespace-normal [.text-message+&amp;]:mt-5\" dir=\"auto\" data-message-author-role=\"assistant\" data-message-id=\"d834ddd4-3658-4907-9a6b-e36f33b2e021\" data-message-model-slug=\"gpt-4o\">\n<div class=\"flex w-full flex-col gap-1 empty:hidden first:pt-[3px]\">\n<div class=\"markdown prose dark:prose-invert w-full break-words light\">\n<p class=\"\" data-start=\"842\" data-end=\"937\">Do obliczania <em>Selection-Strings<\/em> nale\u017cy u\u017cy\u0107 klasy <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">com.cisag.pgm.objsearch.SelectionSupport<\/code>.<\/p>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<h5 id=\"dostep-do-zmian\" ><span class=\"ez-toc-section\" id=\"Dostep_do_zmian\"><\/span>Dost\u0119p do zmian<span class=\"ez-toc-section-end\"><\/span><\/h5>\n<p>Dla ka\u017cdej zmienionej instancji jednostki biznesowej istnieje obiekt klasy <em>JournalEntity<\/em>, z kt\u00f3rego mo\u017cna wyszukiwa\u0107 wszystkie zmiany w danej instancji. Metody zapyta\u0144 do dziennika zmian zwracaj\u0105 obiekty tej klasy. U\u017cywaj\u0105c metody:<\/p>\n<p><code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">JournalChange[] getChanges();<\/code><\/p>\n<p>Czas zmiany i zmieniaj\u0105cy si\u0119 u\u017cytkownik mog\u0105 by\u0107 wyszukiwane dla ka\u017cdej zmiany w jednostce biznesowej. Ka\u017cdy wpis w zwr\u00f3conej tablicy identyfikuje jedn\u0105 zmian\u0119. Indeks w tej tablicy jest nast\u0119pnie wykorzystywany do uzyskania dost\u0119pu do odpowiedniej zmiany.<\/p>\n<p>Klasa <em>JournalObject<\/em> zawiera zmienione warto\u015bci obiektu biznesowego. Zmiany mog\u0105 by\u0107 wprowadzane bezpo\u015brednio do obiektu jednostki biznesowej przy u\u017cyciu klasy:<\/p>\n<p><code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">JournalObject getEntity();<\/code><\/p>\n<p>Zmiany w zale\u017cno\u015bciach mo\u017cna pobra\u0107 za pomoc\u0105 metody:<\/p>\n<p><code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">JournalObject[] getObjects(byte[] classGuid);<\/code><\/p>\n<p><em>ClassGuids<\/em> zale\u017cno\u015bci i jednostki biznesowej mo\u017cna sprawdzi\u0107 za pomoc\u0105 metody:<\/p>\n<p><code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">CisSet getClassGuids();<\/code><\/p>\n<p>Zmiany instancji obiektu biznesowego s\u0105 zarz\u0105dzane w obiektach klasy <em>JournalObject<\/em>. \u015acie\u017cki atrybut\u00f3w obiektu biznesowego mog\u0105 by\u0107 zmieniane za pomoc\u0105 funkcji:<\/p>\n<p><code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">Set getAttributePaths();<\/code><\/p>\n<p>Parts nie s\u0105 zwracane jako obiekty z\u0142o\u017cone. Atrybuty Parts s\u0105 wyzwalane, tj. \u015bcie\u017cki atrybut\u00f3w do kolumn pierwotnych s\u0105 okre\u015blane tak jak w OQL. Wyj\u0105tkiem s\u0105 <em>SpecialParts<\/em> wymienione w klasie <em>ColumnTyp<\/em>. Warto\u015b\u0107 atrybutu jest okre\u015blana za pomoc\u0105 \u015bcie\u017cki atrybutu przy u\u017cyciu funkcji<\/p>\n<p><code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">ChangedValue getChangedValue(String attributePath,<br \/>\n<\/code><\/p>\n<p><code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">int changeIndex);<\/code><\/p>\n<p>Parametr <em>changeIndex<\/em> odpowiada indeksowi z metody <em>JournalEntity:getChanges()<\/em>. W przypadku atrybut\u00f3w, kt\u00f3re nie uleg\u0142y zmianie w indeksie zmian, zwracana jest warto\u015b\u0107 <em>null<\/em>.<\/p>\n<p>Rodzaj zmiany ca\u0142ego obiektu biznesowego jest okre\u015blany przez metod\u0119:<\/p>\n<p><code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">short[] getUpdateTypes();<\/code><\/p>\n<p>Sta\u0142e znajduj\u0105 si\u0119 w klasie <em>UpdateType<\/em> i maj\u0105 nast\u0119puj\u0105ce znaczenie:<\/p>\n<table style=\"width: 100%; height: 279px;\">\n<thead>\n<tr style=\"height: 23px;\">\n<td style=\"height: 23px; border-style: outset;\" width=\"180\"><strong>Sta\u0142a<\/strong><\/td>\n<td style=\"height: 23px; border-style: outset;\" width=\"361\"><strong>Opis<\/strong><\/td>\n<\/tr>\n<\/thead>\n<tbody>\n<tr style=\"height: 70px;\">\n<td style=\"height: 70px; border-style: outset;\" width=\"180\">DELETE<\/td>\n<td style=\"height: 70px; border-style: outset;\" width=\"361\">Obiekt biznesowy zosta\u0142 usuni\u0119ty podczas zmiany. Zawarto\u015b\u0107 usuni\u0119tego obiektu biznesowego znajduje si\u0119 w starych warto\u015bciach atrybutu (Time.OLD).<\/td>\n<\/tr>\n<tr style=\"height: 70px;\">\n<td style=\"height: 70px; border-style: outset;\" width=\"180\">INSERT<\/td>\n<td style=\"height: 70px; border-style: outset;\" width=\"361\">Obiekt biznesowy zosta\u0142 zarejestrowany podczas zmiany. Zawarto\u015b\u0107 nowego obiektu biznesowego jest zawarta w nowych warto\u015bciach atrybutu (Time.NEW).<\/td>\n<\/tr>\n<tr style=\"height: 70px;\">\n<td style=\"height: 70px; border-style: outset;\" width=\"180\">UPDATE<\/td>\n<td style=\"height: 70px; border-style: outset;\" width=\"361\">Obiekt biznesowy zosta\u0142 zmieniony podczas modyfikacji. Zmienione atrybuty s\u0105 dost\u0119pne z warto\u015bci\u0105 przed (Time.OLD) i po (Time.OLD) zmianie.<\/td>\n<\/tr>\n<tr style=\"height: 46px;\">\n<td style=\"height: 46px; border-style: outset;\" width=\"180\">NOT_MODIFIED<\/td>\n<td style=\"height: 46px; border-style: outset;\" width=\"361\">Obiekt nie zosta\u0142 zmieniony. \u017badne warto\u015bci atrybut\u00f3w nie s\u0105 dost\u0119pne.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Stare i nowe warto\u015bci atrybutu s\u0105 przechowywane w obiektach klasy <em>ChangedValue<\/em>. Klasa ta posiada specjalne funkcje zapyta\u0144 dla ka\u017cdego typu danych (UpdateType), np:<\/p>\n<p><code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">byte getByte(short time);<\/code><\/p>\n<p>W przypadku zapytania o warto\u015b\u0107 nale\u017cy okre\u015bli\u0107, czy wymagana jest stara czy nowa warto\u015b\u0107 (<em>Time<\/em>). Typ danych (<em>ColumnType<\/em>) starej lub nowej warto\u015bci mo\u017cna okre\u015bli\u0107 za pomoc\u0105 metody:<\/p>\n<p><code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">short getType(short time);<\/code><\/p>\n<h4 id=\"przyklad-zapytania-do-dziennika-zmian\" ><span class=\"ez-toc-section\" id=\"Przyklad_zapytania_do_dziennika_zmian\"><\/span>Przyk\u0142ad zapytania do dziennika zmian<span class=\"ez-toc-section-end\"><\/span><\/h4>\n<article class=\"text-token-text-primary w-full\" dir=\"auto\" data-testid=\"conversation-turn-24\" data-scroll-anchor=\"true\">\n<div class=\"text-base my-auto mx-auto py-5 [--thread-content-margin:--spacing(4)] @[37rem]:[--thread-content-margin:--spacing(6)] @[72rem]:[--thread-content-margin:--spacing(16)] px-(--thread-content-margin)\">\n<div class=\"[--thread-content-max-width:32rem] @[34rem]:[--thread-content-max-width:40rem] @[64rem]:[--thread-content-max-width:48rem] mx-auto flex max-w-(--thread-content-max-width) flex-1 text-base gap-4 md:gap-5 lg:gap-6 group\/turn-messages focus-visible:outline-hidden\" tabindex=\"-1\">\n<div class=\"group\/conversation-turn relative flex w-full min-w-0 flex-col agent-turn\">\n<div class=\"relative flex-col gap-1 md:gap-3\">\n<div class=\"flex max-w-full flex-col grow\">\n<div class=\"min-h-8 text-message relative flex w-full flex-col items-end gap-2 text-start break-words whitespace-normal [.text-message+&amp;]:mt-5\" dir=\"auto\" data-message-author-role=\"assistant\" data-message-id=\"eb5464db-7349-4c1f-8669-403d1a437767\" data-message-model-slug=\"gpt-4o\">\n<div class=\"flex w-full flex-col gap-1 empty:hidden first:pt-[3px]\">\n<div class=\"markdown prose dark:prose-invert w-full break-words light\">\n<p class=\"\" data-start=\"0\" data-end=\"92\">Poni\u017cej przedstawiono przyk\u0142adowy uproszczony program pokazuj\u0105cy, jak mo\u017cna zapyta\u0107 o dziennik zmian:<\/p>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/article>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">void processOptions() {\n\n\u2026\n\nCisModificationJournalManager mjm =\n\nenv.getModificationJournalManager();\n\n \n\n\/\/ create journal query\n\nJournalQuery query = mjm.createJournalQuery();\n\nquery.setSelection(JournalQuery.ENTITY_CLASS_GUID,\n\nSelectionSupport.\n\ntoGuidSelection(Parner._class)) ;\n\n \n\n\/\/ retrieve changed entity\n\nCollection entities =\n\njm.retrieveJournalEntities(query);\n\n \n\n\/\/ iterate over each changed entity\n\nfor (Iterator i=entities.iterator(); i.hasNext();) {\n\nJournalEntity entity = (JournalEntity)i.next();\n\n \n\n\/\/ process changes of each entity\n\nJournalChange[] changes = entity.getChanges();\n\nfor (int l=0; l&lt;changes.length; l++) {\n\n \n\n\/\/ process all changed business objects\n\nfor (CisBytesIterator j=entity.getClassGuids().iterator();\n\nj.hasNext();) {\n\nbyte[] classGuid = j.next();\n\nJournalObject objects[] = entity.getObjects(classGuid);\n\nfor (int k=0; k&lt;objects.length; k++) {\n\nprocessJournalObject(objects[k],l);\n\n}\n\n}\n\n}\n\n}\n\n\u2026\n\n}\n\n \n\nvoid processJournalObject(JournalObject object, int changeIndex) {\n\n\u2026\n\nswitch (object.getUpdateTypes()[changeIndex]) {\n\ncase UpdateType.DELETE:\n\n\u2026\n\n}\n\n \n\n\/\/ iterate all attributes\n\nfor (Iterator i= object.getAttributePaths().iterator();\n\ni.hasNext();) {\n\nString attributePath = (String)i.next();\n\n \n\n\/\/ check whether the attribute was changed\n\nChangedValue value =\n\nobject.getChangedValue(attributePath,changeIndex);\n\nif (value==null) {\n\ncontinue;\n\n}\n\n \n\n\/\/ display changed values\n\nswitch (object.getUpdateTypes()[changeIndex]) {\n\ncase UpdateType.DELETE:\n\nprocessValue(\n\ngetValueString(value,\n\nCisModificationJournalManager.Time.OLD));\n\nbreak;\n\ncase UpdateType.INSERT:\n\nprocessValue(\n\ngetValueString(value,\n\nCisModificationJournalManager.Time.NEW));\n\nbreak;\n\ncase UpdateType.UPDATE:\n\nprocessValue(\n\ngetValueString(value,\n\nCisModificationJournalManager.Time.OLD));\n\nprocessValue(\n\ngetValueString(value,\n\nCisModificationJournalManager.Time.NEW));\n\nbreak;\n\n}\n\n}\n\n}\n\n \n\nString getValueString(ChangedValue value, short time) {\n\nswitch (value.getType(time)) {\n\ncase ColumnType.BINARY:\n\nreturn ByteArrayUtility.toHex(value.getBytes(time));\n\ncase ColumnType.BLOB:\n\nreturn \u201cBLOB\u201d;\n\ncase CisModificationJournalManager.ColumnType.BOOLEAN:\n\nreturn Boolean.toString(value.getBoolean(time));\n\n\u2026\n\n}\n\n}<\/pre>\n<h4 id=\"lista-transferowa\" ><span class=\"ez-toc-section\" id=\"Lista_transferowa\"><\/span>Lista transferowa<span class=\"ez-toc-section-end\"><\/span><\/h4>\n<p>Lista transferowa rejestruje, czy jednostka biznesowa lub instancja zale\u017cna zosta\u0142a utworzona, usuni\u0119ta lub zmodyfikowana. W przeciwie\u0144stwie do dziennika zmian, lista transfer\u00f3w nie rejestruje, jak\u0105 zawarto\u015b\u0107 ma instancja obiektu biznesowego ani kt\u00f3ra z tych tre\u015bci zosta\u0142a zmieniona i w jaki spos\u00f3b. Podczas rejestrowania listy transfer\u00f3w kontroler <em>CisTransferListController<\/em> okre\u015bla, kt\u00f3re zmiany s\u0105 rejestrowane na li\u015bcie transfer\u00f3w.<\/p>\n<section class=\"document-alert-box example\"><div class=\"document-alert-title\">Przyk\u0142ad<\/div><div class=\"document-alert-content\">Zam\u00f3wienie sprzeda\u017cy ma zosta\u0107 przes\u0142ane do systemu zewn\u0119trznego, gdy zostanie onjo ca\u0142kowicie dostarczone i zafakturowane. Kontroler <em>CisTransferListController<\/em> okre\u015bla, \u017ce zmiany s\u0105 rejestrowane tylko wtedy, gdy atrybuty <em>deliveryState<\/em> i <em>invoicingState<\/em> maj\u0105 warto\u015b\u0107 <em>COMPLETE<\/em>.<\/div><\/section>\n<p>Lista transferowa mo\u017ce by\u0107 tworzona tylko dla obiekt\u00f3w biznesowych, kt\u00f3rych klucz g\u0142\u00f3wny sk\u0142ada si\u0119 z jednego lub dw\u00f3ch identyfikator\u00f3w GUID.<\/p>\n<p>Nale\u017cy pami\u0119ta\u0107, \u017ce lista transferowa monitoruje tylko zmiany w jednostkach biznesowych po aktywacji. Ponadto zmiany za pomoc\u0105 OQL (Update, Insert lub Delete) nie s\u0105 rejestrowane przez te list\u0119. W wielu przypadkach konieczne jest zatem r\u0119czne przeprowadzenie pe\u0142nej synchronizacji danych, np. z systemem zewn\u0119trznym, niezale\u017cnie od listy transferowej.<\/p>\n<h5 id=\"rejestrowanie-listy-transferowej\" ><span class=\"ez-toc-section\" id=\"Rejestrowanie_listy_transferowej\"><\/span>Rejestrowanie listy transferowej<span class=\"ez-toc-section-end\"><\/span><\/h5>\n<p><em>CisTransferListControlle<\/em> zarz\u0105dza rejestrowaniem listy transfer\u00f3w dla jednego lub wi\u0119cej obiekt\u00f3w biznesowych. Dla ka\u017cdego przypadku u\u017cycia listy transfer\u00f3w, nale\u017cy zarejestrowa\u0107 pochodn\u0105 instancj\u0119 klasy <em>CisTransferListController<\/em> w hooku <em>com.cisag.pgm.appserver.hook.TransferListRegistryHook<\/em> definicji hook contract <em>com.cisag.pgm.appserver.Server<\/em>.<\/p>\n<p>Ka\u017cdy <em>CisTransferListController<\/em> jest jednoznacznie identyfikowany przez sw\u00f3j typ. Wszystkie u\u017cywane typy s\u0105 zarejestrowane w ValueSet <em>com.cisag.app.general.TransferListType<\/em>. Je\u015bli zostanie opracowany nowy <em>CisTransferListController<\/em>, nowy wpis musi zosta\u0107 dodany do tego ValueSet.<\/p>\n<p>Alternatywnie, <em>CisTransferListController<\/em> mo\u017ce by\u0107 jednoznacznie identyfikowany przez podtyp. Podtyp jest nazw\u0105 dowolnego logicznego typu danych, kt\u00f3ry powinien by\u0107 u\u017cywany tylko do rejestracji kontrolera. Pierwotny typ logicznego typu danych nie jest oceniany. Dzi\u0119ki zastosowaniu podtypu mo\u017cna bezkonfliktowo zarejestrowa\u0107 kontroler listy transfer\u00f3w. Podtypy umo\u017cliwiaj\u0105 w szczeg\u00f3lno\u015bci rejestracj\u0119 kontroler\u00f3w listy transfer\u00f3w w aplikacjach.<\/p>\n<p>W konstruktorze <em>CisTransferListController<\/em> definiowany jest typ lub podtyp oraz obiekty biznesowe monitorowane przez ten kontroler. Dla ka\u017cdego monitorowanego obiektu biznesowego odpowiednia instancja klasy wewn\u0119trznej <em>CisTransferListController.Entity<\/em> lub <em>CisTransferListController.Dependent<\/em> musi zosta\u0107 przekazana do metody <em>addEntity<\/em> lub <em>addDependent<\/em> w konstruktorze.<\/p>\n<p>Metoda <em>isToBeRecorded<\/em> jednostki biznesowej lub dependent okre\u015bla, czy zmiana w monitorowanej jednostce biznesowej jest zapisywana na li\u015bcie transfer\u00f3w. Je\u015bli metoda ta zwr\u00f3ci warto\u015b\u0107:<\/p>\n<ul>\n<li><strong> true <\/strong>&#8211; zmiana zostanie zapisana na li\u015bcie transfer\u00f3w<\/li>\n<li><strong>false<\/strong> &#8211; zmiana nie jest rejestrowana.<\/li>\n<\/ul>\n<p class=\"\" data-start=\"2101\" data-end=\"2134\">Metoda otrzymuje dwa parametry:<\/p>\n<ul data-start=\"2135\" data-end=\"2234\">\n<li class=\"\" data-start=\"2135\" data-end=\"2183\">\n<p class=\"\" data-start=\"2137\" data-end=\"2183\"><strong data-start=\"2137\" data-end=\"2145\">old\u2026<\/strong> &#8211; stan przed zmian\u0105<\/p>\n<\/li>\n<li class=\"\" data-start=\"2184\" data-end=\"2234\">\n<p class=\"\" data-start=\"2186\" data-end=\"2234\"><strong data-start=\"2186\" data-end=\"2194\">new\u2026<\/strong> &#8211; stan zmieniony w ramach transakcji<\/p>\n<\/li>\n<\/ul>\n<p class=\"\" data-start=\"2236\" data-end=\"2328\">Dzi\u0119ki temu mo\u017cna dok\u0142adnie prze\u015bledzi\u0107, jakie dane zosta\u0142y zmienione w ramach transakcji.<\/p>\n<p>Je\u015bli instancja obiektu biznesowego zosta\u0142a usuni\u0119ta, nie mo\u017cna jej ju\u017c otworzy\u0107 podczas analizy listy transfer\u00f3w. Dlatego w li\u015bcie transfer\u00f3w mo\u017cna zapisa\u0107 kr\u00f3tk\u0105 sekwencj\u0119 znak\u00f3w jako odniesienie, aby mo\u017cna by\u0142o zidentyfikowa\u0107 usuni\u0119te instancje, np. dla system\u00f3w zewn\u0119trznych.<\/p>\n<p>Metoda <em>getReference<\/em> jednostki biznesowej lub dependent mo\u017ce opcjonalnie zwraca\u0107 ci\u0105g znak\u00f3w w celu identyfikacji zmienionego obiektu. Identyfikacja powinna by\u0107 sta\u0142a dla obiektu i nie powinna si\u0119 zmienia\u0107 w zale\u017cno\u015bci od statusu obiektu. W wi\u0119kszo\u015bci przypadk\u00f3w klucz biznesowy jest odpowiedni\u0105 identyfikacj\u0105. Metoda jest wywo\u0142ywana po metodzie <em>isToBeRecorded<\/em> za ka\u017cdym razem, gdy zmiana ma zosta\u0107 zarejestrowana. Nie trzeba zatem ponownie implementowa\u0107 kontroli z metody <em>isToBeRecorded<\/em> w metodzie <em>getReference<\/em>. W ramach metod <em>isToBeRecorded<\/em> i <em>getReference<\/em> nie wolno zmienia\u0107 przeniesionych instancji obiekt\u00f3w biznesowych, ani wykonywa\u0107 z\u0142o\u017conych oblicze\u0144 lub dost\u0119pu do bazy danych. Poniewa\u017c metoda ta jest wywo\u0142ywana przy ka\u017cdej zmianie monitorowanego obiektu biznesowego, czas jej dzia\u0142ania mo\u017ce mie\u0107 wp\u0142yw na wydajno\u015b\u0107 ca\u0142ego systemu. Podczas analizy listy transfer\u00f3w nale\u017cy przeprowadza\u0107 z\u0142o\u017cone kontrole.<\/p>\n<p>Instancja obiektu biznesowego jest identyfikowana za pomoc\u0105 klucza g\u0142\u00f3wnego. Zale\u017cno\u015b\u0107 czasowa nie jest brana pod uwag\u0119 na li\u015bcie transfer\u00f3w. Oznacza to, \u017ce podczas odpytywania listy transfer\u00f3w nie jest ju\u017c mo\u017cliwe \u015bledzenie, kt\u00f3ra wersja instancji jednostki biznesowej zosta\u0142a zmieniona.<\/p>\n<p>Metoda <em>isActive<\/em> okre\u015bla, czy zapis listy transfer\u00f3w dla kontrolera <em>CisTransferListController<\/em> jest aktywny w bazie danych. Wynik tej metody musi zosta\u0107 obliczony na podstawie dostosowania bazy danych. Metoda ta jest wywo\u0142ywana tylko po uruchomieniu serwera aplikacji lub w przypadku zmiany ustawie\u0144.<\/p>\n<h5 id=\"przyklad-kontrolera-cistransferlistcontroller\" ><span class=\"ez-toc-section\" id=\"Przyklad_kontrolera_CisTransferListController\"><\/span>Przyk\u0142ad kontrolera CisTransferListController<span class=\"ez-toc-section-end\"><\/span><\/h5>\n<p>Kontroler <em>OrderTransferListController<\/em> rejestruje utworzenie lub usuni\u0119cie instancji jednostki biznesowej <em>Order<\/em> oraz zmiany atrybutu <em>state<\/em>.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">public class OrderTransferListController extends\n\nCisTransferListController {\n\n \n\npublic class OrderEntity extends Entity&lt;Order&gt; {\n\nOrderDataEntity() {\n\nsuper(Order.class);\n\n}\n\n \n\npublic boolean isToBeRecorded(\n\nOrder oldEntity, Order newEntity) {\n\nif (oldEntity!=null &amp;&amp; newEntity!=null) {\n\nreturn oldEntity.getState()!=\n\nnewEntity.getState();\n\n} else {\n\nreturn true;\n\n}\n\n}\n\n \n\npublic String getReference(\n\nOrder oldEntity, Order newEntity) {\n\nif (oldEntity!=null) {\n\nreturn oldEntity.getNumber();\n\n} else {\n\nreturn newEntity.getNumber();\n\n}\n\n}\n\n}\n\n \n\npublic class OrderDetailDependent\n\nextends Dependent&lt;OrderDetail,Order&gt; {\n\n \n\nOrderDetailDependent() {\n\nsuper(OrderDetail.class);\n\n}\n\n \n\npublic boolean isToBeRecorded(\n\nOrderDetail oldDependent, OrderDetail newDependent) {\n\nOrder oldEntity, Order newEntity) {\n\nif (oldDependent!=null &amp;&amp; newDependent!=null) {\n\nreturn oldDependent.getState()!=\n\nnewDependent.getState();\n\n} else {\n\nreturn true;\n\n}\n\n}\n\n}\n\n \n\n \n\npublic OrderTransferListController() {\n\nsuper(TransferListType.ORDER_CONTROLLER);\n\naddEntity(new OrderEntity());\n\naddDependent(new OrderDetailDependent());\n\n}\n\n \n\npublic boolean isActive(byte[] databaseGuid) {\n\nboolean result;\n\n\u2026\n\nsm.getConfiguredValues(\n\ndatabaseGuid,\n\nORDER_FUNCTION_NAME);\n\n\u2026\n\nreturn result;\n\n}\n\n}<\/pre>\n<p>W przypadku u\u017cycia podtypu zamiast typu, nale\u017cy wprowadzi\u0107 logiczny typ danych com.my.app.general.<em>OrderTransferListController<\/em>, i zmieni\u0107 konstruktor kontrolera w nast\u0119puj\u0105cy spos\u00f3b:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">public OrderTransferListController() {\n\nsuper(\"com.my.app.general.OrderTransferListController\");\n\naddEntity(new OrderEntity());\n\n}<\/pre>\n<p>Kontroler mo\u017cna zarejestrowa\u0107 w nast\u0119puj\u0105cy spos\u00f3b w implementacji definicji hook contract <em>com.cisag.pgm.appserver.Server<\/em>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">Class MyTranferListRegistry implements TransferListRegistryHook {\n\npublic void initialize(TransferListRegistry registry) {\n\nregistry.add(new OderTransferListController());\n\n}\n\n}<\/pre>\n<h5 id=\"odpytywanie-listy-transferowej\" ><span class=\"ez-toc-section\" id=\"Odpytywanie_listy_transferowej\"><\/span>Odpytywanie listy transferowej<span class=\"ez-toc-section-end\"><\/span><\/h5>\n<p>Lista transferowa mo\u017ce zosta\u0107 pobrana za pomoc\u0105 metody <em>retrieveTransferListEntries<\/em> z klasy <em>CisModificationJournalManagers<\/em>. Aby uzyska\u0107 sp\u00f3jny i sta\u0142y stan listy transferowej, konieczne jest wygenerowanie nowego numeru sekwencji za pomoc\u0105 metody <em>newTransferListSequence\u00a0<\/em>Wszystkie nowe wpisy na li\u015bcie transferowej s\u0105 nast\u0119pnie rejestrowane pod tym numerem. Nowy numer sekwencyjny jest przesy\u0142any podczas odpytywania listy transferowej. Metoda <em>retrieveTransferListEntries<\/em> zwraca jedynie te wpisy, kt\u00f3re zosta\u0142y zapisane z numerem sekwencji starszym ni\u017c przekazany.<\/p>\n<p>Wpisy na li\u015bcie transfer\u00f3w s\u0105 reprezentowane przez wewn\u0119trzn\u0105 klas\u0119 <em>CisModificationJournalManager.TransferListEntry<\/em>. Maksymalnie jeden <em>TransferListEntry<\/em> jest zwracany dla ka\u017cdej instancji jednostki biznesowej, niezale\u017cnie od tego, jak cz\u0119sto by\u0142 on zmieniany.<\/p>\n<p>Je\u015bli &#8222;TransferListEntry&#8221; zosta\u0142 pomy\u015blnie przetworzony, zmiana jest usuwana za pomoc\u0105 metody &#8222;delete&#8221;. W ten spos\u00f3b &#8222;TransferListEntry&#8221; jest usuwany z transakcji, kt\u00f3ra by\u0142a otwarta w momencie jego wywo\u0142ania. Wpis jest faktycznie usuwany tylko wtedy, gdy transakcja zostanie &#8222;zatwierdzona&#8221;. Je\u015bli wpis nie zostanie usuni\u0119ty, pojawi si\u0119 ponownie w wynikach przy nast\u0119pnym wywo\u0142aniu &#8222;retrieveTransferListEntries&#8221;.<\/p>\n<p>Odniesienie mo\u017cna sprawdzi\u0107 za pomoc\u0105 metody &#8222;getReference&#8221; w &#8222;TransferListEntry&#8221;. Je\u015bli powi\u0105zana jednostka biznesowa lub jednostka zale\u017cna nie zaimplementowa\u0142a metody &#8222;getReference&#8221;, w\u00f3wczas &#8222;getReference&#8221; zwraca &#8222;pusty ci\u0105g&#8221; w &#8222;TransferListEntry&#8221;.<\/p>\n<p>Odniesienie mo\u017cna ustawi\u0107 za pomoc\u0105 metody &#8222;setReference&#8221; na &#8222;TransferListEntry&#8221;. Na przyk\u0142ad mo\u017cna u\u017cy\u0107 odniesienia do zapisania kodu b\u0142\u0119du ostatniego nieudanego transferu lub licznika liczby nieudanych pr\u00f3b.<\/p>\n<p>Je\u015bli lista transfer\u00f3w jest odpytywana w stosunkowo kr\u00f3tkich odst\u0119pach czasu, nie ma sensu generowanie nowego numeru sekwencji przed ka\u017cdym zapytaniem. Metoda &#8222;existsTransferListEntry&#8221; mo\u017ce by\u0107 u\u017cyta do sprawdzenia, czy wpisy istniej\u0105 dla jednostki biznesowej.<\/p>\n<h5 id=\"przyklad-zapytania-o-liste-transferowa\" ><span class=\"ez-toc-section\" id=\"Przyklad_zapytania_o_liste_transferowa\"><\/span>Przyk\u0142ad zapytania o list\u0119 transferow\u0105<span class=\"ez-toc-section-end\"><\/span><\/h5>\n<p>Zapytanie i przetwarzenie wszystkich nowo zmienionych instancji <em>OrderTransferListController<\/em>.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">CisModificationJournalManager mjm =\n\nenv.getModificationJournalManager();\n\nint newSequence = mjm.newTransferListSequence(\n\nenv.getDatabaseGuid(),\n\n\u201ccom.my.app.general.OrderTransferListController\u201d);\n\nfor (\n\nIterator&lt;CisModificationJournalManager.TransferListEntry&gt;\n\ni =mjm.retrieveTransferListEntries(\n\n\u201ccom.my.app.general.OrderTransferListController\u201d,\n\nOrder._classGuid, newSequence);\n\ni.hasNext();)\n\n{\n\nCisModificationJournalManager.TransferListEntry entry =\n\ni.next();\n\ntm.beginNew()\n\ntry {\n\nOrder order = (Order)\n\nom.getObject(entry.getPrimaryKey());\n\nif (order==null) {\n\nSystem.out.println(\n\n\u201cOrder \u201c+entry.getReference()+\u201d deleted\u201d);\n\n}\n\n\u2026\n\nentry.delete();\n\ntm.commit();\n\n} catch (RuntimeException ex) {\n\ntm.rollback();\n\n\u2026\n\n}\n\n}<\/pre>\n","protected":false},"author":28,"comment_status":"closed","ping_status":"closed","template":"","format":"standard","meta":{"footnotes":""},"class_list":["post-8277","ht_kb","type-ht_kb","status-publish","format-standard","hentry","ht_kb_category-interfejsy-techniczne"],"_links":{"self":[{"href":"https:\/\/pomoc.comarch.pl\/cee\/index.php\/wp-json\/wp\/v2\/ht_kb\/8277","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/pomoc.comarch.pl\/cee\/index.php\/wp-json\/wp\/v2\/ht_kb"}],"about":[{"href":"https:\/\/pomoc.comarch.pl\/cee\/index.php\/wp-json\/wp\/v2\/types\/ht_kb"}],"author":[{"embeddable":true,"href":"https:\/\/pomoc.comarch.pl\/cee\/index.php\/wp-json\/wp\/v2\/users\/28"}],"replies":[{"embeddable":true,"href":"https:\/\/pomoc.comarch.pl\/cee\/index.php\/wp-json\/wp\/v2\/comments?post=8277"}],"version-history":[{"count":8,"href":"https:\/\/pomoc.comarch.pl\/cee\/index.php\/wp-json\/wp\/v2\/ht_kb\/8277\/revisions"}],"predecessor-version":[{"id":32384,"href":"https:\/\/pomoc.comarch.pl\/cee\/index.php\/wp-json\/wp\/v2\/ht_kb\/8277\/revisions\/32384"}],"wp:attachment":[{"href":"https:\/\/pomoc.comarch.pl\/cee\/index.php\/wp-json\/wp\/v2\/media?parent=8277"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}