[Java] Vereinfachen Sie die Implementierung der Datenverlaufsverwaltung mit Reladomo

Was ist Reladomo?

reladomo-200.png Reladomo ist ein Java ORM-Framework, das von Goldman Sachs als OSS veröffentlicht wurde. Ich mag es, weil es eine charakteristische Funktion hat, die es einfach macht, den Änderungsverlauf in RDBMS zu verwalten.

In Reladomo können Java und DDL durch Definieren der Entität in XML generiert werden. Durch Nutzung der generierten API können Sie CRUD-Operationen für die entsprechenden Tabellen ausführen.

Was ist in diesem Artikel zu tun?

Dieses Mal werde ich kurz auf die grundlegenden Operationen von Reladomo, die Arten von Datenmodellen usw. eingehen.

Zu diesem Zeitpunkt ist es in Bezug auf das bitemporale Datenmodell (später beschrieben) einfacher zu verstehen, wenn man das tatsächliche Verhalten betrachtet. Ich möchte einen Blick auf eine Beispiel-REST-API in Kombination mit Spring Boot werfen. https://github.com/amtkxa/spring-boot-reladomo

Informationen zum Datenverlaufsmanagement von Reladomo

Um den Änderungsverlauf der Daten verfolgen zu können, müssen die Verlaufsdaten gespeichert werden. Zeit, die eine Bedeutung hat, sollte zusammen gespart werden.

Transaction Time, Vaild Time

Reladomo macht es einfach, zwei Mal zu verwalten, um den Datenänderungsverlauf zu verfolgen.

Datenmodell

Die folgenden vier Datenmodelle können berücksichtigt werden, je nachdem, ob Transaktionszeit und Vaild-Zeit verwendet werden oder nicht. Reladomo bietet Ihnen auch die Flexibilität, ein Datenmodell nach Entität auszuwählen.

Datenmodell Erläuterung
Snapshot-Datenmodell Es wird keine Zeitdimension unterstützt (keine Verlaufsverwaltung)
Transaktionszeitdatenmodell Es wird nur die Transaktionszeit unterstützt
Gültiges Zeitdatenmodell Nur gültige Zeit unterstützt
Bitemporales Datenmodell Unterstützt sowohl Vaild Time als auch Transaction Time

Verwenden Sie es tatsächlich (Transaktionszeitdatenmodell)

Lassen Sie uns zunächst das Transaktionszeitdatenmodell behandeln und die grundlegende Verwendung von Reladomo ansprechen.

Vorbereiten eines einfachen Domänenmodells

Da der Zweck darin besteht, die Funktion von Reladomo zu bestätigen, haben wir ein einfaches Domänenmodell erstellt, das möglich zu sein scheint. 50054750-b2e45800-0188-11e9-8aeb-fad5262e78d8.png

Erstellen Sie eine XML-Datei für das Reladomo-Objekt

Erstellen Sie zunächst eine XML-Datei, die die Objekte definiert, die den Tabellen in Ihrer Datenbank entsprechen.

Account.xml


<MithraObject xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              objectType="transactional"
              xsi:noNamespaceSchemaLocation="../config/mithraobject.xsd">
    <PackageName>com.amtkxa.springbootreladomosimple.domain.entity</PackageName>
    <ClassName>Account</ClassName>
    <DefaultTable>ACCOUNT</DefaultTable>

    <AsOfAttribute name="processingDate" fromColumnName="PROCESSING_DATE_FROM" toColumnName="PROCESSING_DATE_TO"
                   toIsInclusive="false"
                   isProcessingDate="true"
                   infinityDate="[com.gs.fw.common.mithra.util.DefaultInfinityTimestamp.getDefaultInfinity()]"
                   defaultIfNotSpecified="[com.gs.fw.common.mithra.util.DefaultInfinityTimestamp.getDefaultInfinity()]"
    />
    <Attribute name="accountId" javaType="int" columnName="ACCOUNT_ID" primaryKey="true"
               primaryKeyGeneratorStrategy="SimulatedSequence">
        <SimulatedSequence sequenceName="Account"
                           sequenceObjectFactoryName="com.amtkxa.springbootreladomosimple.infrastructure.util.ObjectSequenceObjectFactory"
                           hasSourceAttribute="false"
                           batchSize="1"
                           initialValue="1"
                           incrementSize="1"/>
    </Attribute>
    <Attribute name="customerId" javaType="int" columnName="CUSTOMER_ID" nullable="false"/>
    <Attribute name="balance" javaType="double" columnName="BALANCE"/>
</MithraObject>

Eine kurze Beschreibung jedes Attributs lautet wie folgt.

Element Erläuterung
PackageName Das Paket, zu dem das generierte Objekt gehört.
ClassName Der Klassenname des Objekts.
DefaultTable Die Tabelle, der das Objekt entspricht.
Attribute Objektattribute. Entspricht den in DefaultTable definierten Spalten der Tabelle.
AsOfAttribute Es entspricht der Spalte für die Verlaufsverwaltung, und der Zeitraum wird durch zwei Spalten von von bis bis dargestellt.
SimulatedSequence Sequenzwert, der zum Zeitpunkt von INSERT automatisch nummeriert wird.

Sie können auch auf mithraobject.xsd verweisen, um weitere Informationen zu den hier festgelegten Einstellungen zu erhalten.

Generierung von Java-Dateien

Aus der zuvor definierten XML-Datei können Sie eine Java-Datei für das entsprechende Objekt generieren.

Erstellen einer MithraClassList

MithraClassList.xml


<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Mithra xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="../config/mithraobject.xsd">
    <MithraObjectResource name="ObjectSequence"/>
    <MithraObjectResource name="Customer"/>
    <MithraObjectResource name="Account"/>
    <MithraObjectResource name="Transaction"/>
</Mithra>

Definition der gen-reladomo-Aufgabe

Definieren Sie die Aufgabe "gen-reladomo" in "pom.xml". Diese Ant-Task verwendet den MithraGenerator, um eine Java-Datei basierend auf der``MithraClassList.xml`-Datei zu generieren.

pom.xml


<tasks>
    <property name="plugin_classpath" refid="maven.plugin.classpath"/>
    <taskdef name="gen-reladomo" classpath="plugin_classpath"
                classname="com.gs.fw.common.mithra.generator.MithraGenerator"/>
    <gen-reladomo
            xml="${project.basedir}/src/main/resources/reladomo/model/MithraClassList.xml"
            generateGscListMethod="true"
            generatedDir="${project.build.directory}/generated-sources/reladomo"
            nonGeneratedDir="${project.basedir}/src/main/java"
    />
</tasks>

Hier werden zwei Ausgabeziele durch "generateDir" und "nonGeneratedDir" definiert.

gen-reladomo Taskausführung

Die Task "gen-reladomo" generiert eine Java-Datei, z. B. durch Ausführen von "mvn clean install". generateDir generiert eine abstrakte Klasse, die jedes Mal neu erstellt wird, um XML-Änderungen zu folgen, und nonGeneratedDir erstellt eine konkrete Klasse, in der der Benutzer seine eigene Geschäftslogik hinzufügt. Die generierten Klassen und Abhängigkeiten sind wie folgt.

FireShot Capture 21 - spring-boot-relado_ - https___app.genmymodel.com_edit__alkjIAXvEemAl9N48If50Q#.png

Die hier generierte abstrakte Klasse enthält den größten Teil des Codes, der zum Ausführen von CRUD-Operationen für eine Entität erforderlich ist.

DDL-Generierung

Sie können DDL für von Reladomo unterstützte Datenbanken generieren. DDL scheint Tabellen, Indizes und externe Schlüssel zu unterstützen.

Definition der Aufgabe gen-reladomo-db

Definieren Sie die Aufgabe "gen-reladomo-db" in "pom.xml". Diese Ant-Task verwendet den MithraDbDefinitionGenerator, um eine DDL basierend auf der MithraClassList.xml-Datei zu generieren.

pom.xml


<tasks>
    <property name="plugin_classpath" refid="maven.plugin.classpath"/>
    <taskdef name="gen-reladomo-db" classpath="plugin_classpath"
                classname="com.gs.fw.common.mithra.generator.dbgenerator.MithraDbDefinitionGenerator"/>
    <gen-reladomo-db
            xml="${project.basedir}/src/main/resources/reladomo/model/MithraClassList.xml"
            generatedDir="${project.build.directory}/generated-resources/db"
            databaseType="postgres"/>
</tasks>

Ausführung der Aufgabe gen-reladomo-db

Die Task "gen-reladomo-db" generiert eine DDL, z. B. durch Ausführen von "mvn clean install". Die DDL, die generiert wurde, als "postgres" auf "databaseType" gesetzt wurde, hatte den folgenden Inhalt.

target/generated-resources/db/ACCOUNT.ddl


drop table if exists ACCOUNT;

create table ACCOUNT
(
    ACCOUNT_ID int not null,
    CUSTOMER_ID int not null,
    BALANCE float8,
    PROCESSING_DATE_FROM timestamp not null,
    PROCESSING_DATE_TO timestamp not null
);

target/generated-resources/db/ACCOUNT.idx


alter table ACCOUNT add constraint ACCOUNT_PK primary key (ACCOUNT_ID, PROCESSING_DATE_TO);

drop index if exists ACCOUNT_IDX0;
create index ACCOUNT_IDX0 on ACCOUNT(CUSTOMER_ID, PROCESSING_DATE_TO);

Bei der Verwaltung des Verlaufs mit Reladomo wird anscheinend keine Fremdschlüssel-DDL aus dem entsprechenden XML generiert. Übrigens scheint es, dass die hier generierte DDL nicht so verwendet wird, wie sie ist, sondern darauf basierend angepasst werden soll.

The DDLs generated by Reladomo are not meant to be used as is. They are merely meant to be a starting point for further customization. There are two common reasons to customize the generated DDLs. One is to add database specific clauses for specifying table spaces, schemas etc. Another is to add additional indices based on usage patterns seen in the application. Guided Tour Of Reladomo - 2.3. Database DDL Generation

Ich bin dankbar für die DDL-Generierungsfunktion.

Reladomo CRUD-Betrieb

CRUD (Create)

Registrierung eines einzelnen Datensatzes

Fügen Sie der von Reladomo generierten konkreten Klasse den folgenden Konstruktor hinzu.

Account.java


public Account(int customerId, double balance) {
    this(com.gs.fw.common.mithra.util.DefaultInfinityTimestamp.getDefaultInfinity());
    this.setCustomerId(customerId);
    this.setBalance(balance);
}

Versuchen Sie dann, den folgenden Code auszuführen.

MithraManagerProvider.getMithraManager().executeTransactionalCommand((tx) -> {
    Account account = new Account(1, 100);
    account.insert();
    return null;
});

Anschließend wurde der Datensatz in der Tabelle ACCOUNT der Verbindungsziel-DB registriert.

testdb=> select * from account;
 account_id | customer_id | balance |  processing_date_from  | processing_date_to
------------+-------------+---------+------------------------+---------------------
          1 |           1 |     100 | 2018-12-23 14:42:14.61 | 9999-12-01 23:59:00

Sequenzwertnummerierung

Da der nummerierte Sequenzwert auf "account_id" gesetzt ist, für den kein Wert gesetzt ist, wird er dort ergänzt. Wenn Sie Folgendes in die entsprechende Spalte von Account.xml eingeben, die zuvor definiert wurde, können Sie den Sequenzwert nummerieren.

Account.xml


    <Attribute name="accountId" javaType="int" columnName="ACCOUNT_ID" primaryKey="true"
               primaryKeyGeneratorStrategy="SimulatedSequence">
        <SimulatedSequence sequenceName="Account"
                           sequenceObjectFactoryName="com.amtkxa.springbootreladomosimple.infrastructure.util.ObjectSequenceObjectFactory"
                           hasSourceAttribute="false"
                           batchSize="1"
                           initialValue="1"
                           incrementSize="1"/>
    </Attribute>

Die in "Account.xml" angegebene "ObjectSequenceObjectFactory" wird separat erstellt.

ObjectSequenceObjectFactory.java


public class ObjectSequenceObjectFactory implements MithraSequenceObjectFactory {
  public MithraSequence getMithraSequenceObject(String sequenceName, Object sourceAttribute, int initialValue) {
    ObjectSequence objectSequence = ObjectSequenceFinder.findByPrimaryKey(sequenceName);
    if (objectSequence == null) {
      objectSequence = new ObjectSequence();
      objectSequence.setSimulatedSequenceName(sequenceName);
      objectSequence.setNextValue(initialValue);
      objectSequence.insert();
    }
    return objectSequence;
  }
}

Die zu nummerierenden Werte werden in der Tabelle OBJECT_SEQUENCE verwaltet, die auch die Metadaten in XML definiert.

ObjectSequence.xml


<MithraObject xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              objectType="transactional"
              xsi:noNamespaceSchemaLocation="../config/mithraobject.xsd">

    <PackageName>com.amtkxa.springbootreladomosimple.domain.entity</PackageName>
    <ClassName>ObjectSequence</ClassName>
    <DefaultTable>OBJECT_SEQUENCE</DefaultTable>

    <Attribute name="simulatedSequenceName" javaType="String" columnName="SEQUENCE_NAME" primaryKey="true" maxLength="64"/>
    <Attribute name="nextValue" javaType="long" columnName="NEXT_VALUE"/>

</MithraObject>
testdb=> select * from object_sequence;
 sequence_name | next_value
---------------+------------
 Account       |          2

Registrierung mehrerer Datensätze

Sie können auch mehrere Datensätze registrieren, indem Sie die von Reladomo generierte "AccountList" verwenden.

MithraManagerProvider.getMithraManager().executeTransactionalCommand((tx) -> {
    AccountList accountList = new AccountList();
    accountList.add(new Account(2, 200));
    accountList.add(new Account(3, 300));
    accountList.insertAll();
    return null;
});

Als ich diesen Code ausführte, wurden mehrere Datensätze registriert.

testdb=> select * from account where customer_id in (2, 3);
 account_id | customer_id | balance |  processing_date_from  | processing_date_to
------------+-------------+---------+------------------------+---------------------
          2 |           2 |     200 | 2018-12-23 15:10:37.92 | 9999-12-01 23:59:00
          3 |           3 |     300 | 2018-12-23 15:10:37.92 | 9999-12-01 23:59:00

CRUD (Read)

Der Suchvorgang verwendet die von Reladomo generierte Finder-Klasse.

Suchbedingungseinstellungen

Sie können eine Instanz der Klasse "Operation" mithilfe der Klasse "Finder" erstellen. Die Klasse "Operation" kann den Teil der ausgegebenen Abfrage festlegen, der die WHERE-Klausel sein wird.

Lassen Sie mich einige Beispiele geben.

// where NAME = 'tanaka'
Operation op1 = CustomerFinder.name().eq("tanaka");
// where NAME <> 'tanaka'
Operation op2 = CustomerFinder.name().notEq("tanaka");
// where NAME like 'tanaka%'
Operation op3 = CustomerFinder.name().startsWith("tanaka");
// where NAME like '%taro'
Operation op4 = CustomerFinder.name().endsWith("taro");
// where NAME like '%tanaka%'
Operation op5 = CustomerFinder.name().wildCardEq("*tanaka*");
// where CUSTOMER_ID < 3
Operation op6 = CustomerFinder.customerId().lessThan(3);

Zusätzlich zu den hier aufgeführten gibt es auch "isNull" und "enthält". Sie können Operations auch wie folgt verketten:

// where NAME like '%tanaka%' and CUSTOMER_ID < 3
Operation op = op5.and(op6);

1 Suche

Sie können einen einzelnen Datensatz erhalten, indem Sie "findOne" der Klasse "Finder" verwenden.

// select t0.ACCOUNT_ID,t0.CUSTOMER_ID,t0.BALANCE,t0.PROCESSING_DATE_FROM,t0.PROCESSING_DATE_TO from ACCOUNT t0 
// where  t0.ACCOUNT_ID = 1 and t0.PROCESSING_DATE_TO = '9999-12-01 23:59:00.000'
Account account = AccountFinder.findOne(AccountFinder.accountId().eq(1));

Die Bedingung der tatsächlich ausgegebenen Abfrage lautet "t0.PROCESSING_DATE_TO =" 9999-12-01 23: 59: 00.000 "und bezieht sich auf den Datensatz, der dem neuesten Verlauf entspricht.

Mehrfachsuche

Wenn Sie findMany der Finder-Klasse verwenden, können Sie mehrere Datensätze in List abrufen.

// select t0.CUSTOMER_ID,t0.NAME,t0.COUNTRY,t0.PROCESSING_DATE_FROM,t0.PROCESSING_DATE_TO from CUSTOMER t0
// where  t0.NAME like 'tanaka%' and t0.PROCESSING_DATE_TO = '9999-12-01 23:59:00.000'
CustomerList customerList = CustomerFinder.findMany(CustomerFinder.name().startsWith("tanaka"));

CRUD (Update)

Wenn Sie Änderungen an einem Objekt vornehmen, das mit der Klasse "Finder" abgerufen wurde, werden die Änderungen auch in der DB-Tabelle angezeigt. Ich habe die folgenden Daten vorbereitet, um das Verhalten zu überprüfen.

testdb=> select * from customer where customer_id = 7;
 customer_id |  name   | country |  processing_date_from  | processing_date_to
-------------+---------+---------+------------------------+---------------------
           7 | Pikachu | Japan   | 2018-12-23 19:36:07.06 | 9999-12-01 23:59:00

Pikachu wechselt zu Raichu. Angenommen, der folgende Code wird ausgeführt, um die Änderungen vorzunehmen.

MithraManagerProvider.getMithraManager().executeTransactionalCommand((tx) -> {
    Customer customer = CustomerFinder.findOne(CustomerFinder.customerId().eq(7));
    customer.setName("Raichu");
    return null;
});

Das Ausführungsergebnis ist wie folgt.

testdb=> select * from customer where customer_id = 7;
 customer_id |  name   | country |  processing_date_from  |   processing_date_to
-------------+---------+---------+------------------------+------------------------
           7 | Pikachu | Japan   | 2018-12-23 19:36:07.06 | 2018-12-23 19:46:13.91
           7 | Raichu  | Japan   | 2018-12-23 19:46:13.91 | 9999-12-01 23:59:00

Die tatsächlich ausgegebene Abfrage lautet wie folgt.

--Holen Sie sich die neuesten Verlaufsdaten
select t0.CUSTOMER_ID,t0.NAME,t0.COUNTRY,t0.PROCESSING_DATE_FROM,t0.PROCESSING_DATE_TO from CUSTOMER t0 
where  t0.CUSTOMER_ID = 7 and t0.PROCESSING_DATE_TO = '9999-12-01 23:59:00.000' FOR SHARE OF t0;

--Aktualisieren Sie den Gültigkeitszeitraum der neuesten Verlaufsdaten
update CUSTOMER set PROCESSING_DATE_TO = '2018-12-23 19:46:13.910'  
where CUSTOMER_ID = 7 AND PROCESSING_DATE_TO = '9999-12-01 23:59:00.000';

--Registrieren Sie die geänderten Daten als neuesten Verlauf
insert into CUSTOMER(CUSTOMER_ID,NAME,COUNTRY,PROCESSING_DATE_FROM,PROCESSING_DATE_TO) 
values (7,'Raichu','Japan','2018-12-23 19:46:13.910','9999-12-01 23:59:00.000');

CRUD (Delete)

Dies kann in der Tabelle wiedergegeben werden, indem das mit der Finder-Klasse erhaltene Objekt gelöscht wird. In diesem Fall ist das Verhalten für "delete ()", "terminate ()" und "purge ()" unterschiedlich. Verschieben wir es also einfach.

delete()

delete () kann für Objekte verwendet werden, die Reladomo nicht im Verlauf verwaltet (abhängig davon, ob XML über AsOfAttribute verfügt). Dadurch wird der Datensatz physisch aus der Tabelle gelöscht.

MithraManagerProvider.getMithraManager().executeTransactionalCommand((tx) -> {
    Transaction transaction = TransactionFinder.findOne(TransactionFinder.transactionId().eq(4));
    transaction.delete();
    return null;
});

Die tatsächlich ausgeführte Abfrage lautet wie folgt.

select t0.LOG_ID,t0.ACCOUNT_ID,t0.TRANSACTION_TYPE,t0.AMOUNT,t0.TRANSACTION_DATE from TRANSACTION t0 
where  t0.LOG_ID = 4 FOR SHARE OF t0;

delete from TRANSACTION where LOG_ID = 4;

terminate()

terminate () beendet den Verlauf von Objekten, die von Reladomo verwaltet werden. (Aufzeichnung als Geschichte bleibt) Die folgenden Daten wurden vorbereitet, um das Verhalten zu überprüfen.

testdb=> select * from customer where customer_id = 7;
 customer_id |  name   | country |  processing_date_from  |   processing_date_to
-------------+---------+---------+------------------------+------------------------
           7 | Pikachu | Japan   | 2018-12-23 19:36:07.06 | 2018-12-23 19:46:13.91
           7 | Raichu  | Japan   | 2018-12-23 19:46:13.91 | 9999-12-01 23:59:00

Führen Sie als Antwort diesen Code aus.

MithraManagerProvider.getMithraManager().executeTransactionalCommand((tx) -> {
    Customer customer = CustomerFinder.findOne(CustomerFinder.customerId().eq(7));
    customer.terminate();
    return null;
});

Dann wird das als "9999-12-01 23: 59: 00" in "process_date_to" registrierte Teil aktualisiert.

testdb=> select * from customer where customer_id = 7;
 customer_id |  name   | country |  processing_date_from  |   processing_date_to
-------------+---------+---------+------------------------+------------------------
           7 | Pikachu | Japan   | 2018-12-23 19:36:07.06 | 2018-12-23 19:46:13.91
           7 | Raichu  | Japan   | 2018-12-23 19:46:13.91 | 2018-12-23 22:10:36.68

Die tatsächlich ausgeführte Abfrage lautet wie folgt.

select t0.CUSTOMER_ID,t0.NAME,t0.COUNTRY,t0.PROCESSING_DATE_FROM,t0.PROCESSING_DATE_TO from CUSTOMER t0 
where  t0.CUSTOMER_ID = 7 and t0.PROCESSING_DATE_TO = '9999-12-01 23:59:00.000' FOR SHARE OF t0;

update CUSTOMER set PROCESSING_DATE_TO = '2018-12-23 22:10:36.680'  
where CUSTOMER_ID = 7 AND PROCESSING_DATE_TO = '9999-12-01 23:59:00.000';

purge()

purge () löscht den Verlauf des von Reladomo verwalteten Objekts.

MithraManagerProvider.getMithraManager().executeTransactionalCommand((tx) -> {
    Customer customer = CustomerFinder.findOne(CustomerFinder.customerId().eq(6));
    customer.purge();
    return null;
});

Die tatsächlich ausgeführte Abfrage lautet wie folgt.

select t0.CUSTOMER_ID,t0.NAME,t0.COUNTRY,t0.PROCESSING_DATE_FROM,t0.PROCESSING_DATE_TO from CUSTOMER t0
where  t0.CUSTOMER_ID = 6 and t0.PROCESSING_DATE_TO = '9999-12-01 23:59:00.000' FOR SHARE OF t0;

delete from CUSTOMER where CUSTOMER_ID = 6;

Tatsächlich verwenden (bitemporales Datenmodell)

Verwenden Sie eine Beispiel-REST-API, die mit einem bitemporalen Datenmodell in Kombination mit Spring Boot funktioniert. https://github.com/amtkxa/spring-boot-reladomo

Die Transaktionszeit und die Vaild-Zeit, die im bitemporalen Datenmodell verarbeitet werden, haben häufig das gleiche Timing. Hier werden wir jedoch den Fall verfolgen, in dem Sie den Vorteil der gleichzeitigen Verwaltung der beiden sehen können.

Ich habe bereits die grundlegende Verwendung von Reladomo erwähnt, daher werde ich die Teile vorstellen, die nicht viel behandelt werden.

1. Januar - Eröffnen Sie ein Konto mit einer Ersteinzahlung von 10.000 Yen

Der allererste Verlaufsdatensatz wurde registriert.

sampledb=> select * from account where account_id = 10;
 account_id | customer_id | balance | business_date_from  |  business_date_to   |  processing_date_from  | processing_date_to
------------+-------------+---------+---------------------+---------------------+------------------------+---------------------
         12 |           1 |   10000 | 2019-01-01 00:00:00 | 9999-12-01 23:59:00 | 2018-12-22 16:17:17.49 | 9999-12-01 23:59:00

17.-5000. Januar Yen Kaution

Angenommen, Sie könnten aufgrund von Problemen keine Einzahlung vornehmen. Daher ändert sich der Tabelleninhalt nicht.

20. Januar 200 Yen Einzahlung

Die Geschichte wurde aufgrund der Einzahlung von 20000 Yen gekürzt.

sampledb=> select * from account where account_id = 12 order by 4, 6;
 account_id | customer_id | balance | business_date_from  |  business_date_to   |  processing_date_from  |   processing_date_to
------------+-------------+---------+---------------------+---------------------+------------------------+------------------------
         12 |           1 |   10000 | 2019-01-01 00:00:00 | 9999-12-01 23:59:00 | 2018-12-22 16:33:09.54 | 2018-12-22 16:38:27.48
         12 |           1 |   10000 | 2019-01-01 00:00:00 | 2019-01-20 00:00:00 | 2018-12-22 16:38:27.48 | 9999-12-01 23:59:00
         12 |           1 |   30000 | 2019-01-20 00:00:00 | 9999-12-01 23:59:00 | 2018-12-22 16:38:27.48 | 9999-12-01 23:59:00

25. Januar - Feste 5000 Yen, die nicht eingezahlt werden konnten

Angenommen, der am 17. Januar eingezahlte Geldbetrag wurde am 25. Januar geändert. Wenn Sie in diesem Fall "incrementBalance ()" verwenden, um das Objekt zu aktualisieren, das durch Angabe des 17. Januar für business_date erfasst wurde, wird die entsprechende Tabelle auf den folgenden Inhalt aktualisiert.

sampledb=> select * from account where account_id = 12 order by 6, 4;
 account_id | customer_id | balance | business_date_from  |  business_date_to   |  processing_date_from  |   processing_date_to
------------+-------------+---------+---------------------+---------------------+------------------------+------------------------
         12 |           1 |   10000 | 2019-01-01 00:00:00 | 9999-12-01 23:59:00 | 2018-12-22 16:33:09.54 | 2018-12-22 16:38:27.48
         12 |           1 |   10000 | 2019-01-01 00:00:00 | 2019-01-20 00:00:00 | 2018-12-22 16:38:27.48 | 2018-12-22 16:45:31.94
         12 |           1 |   30000 | 2019-01-20 00:00:00 | 9999-12-01 23:59:00 | 2018-12-22 16:38:27.48 | 2018-12-22 16:45:31.94
         12 |           1 |   10000 | 2019-01-01 00:00:00 | 2019-01-17 00:00:00 | 2018-12-22 16:45:31.94 | 9999-12-01 23:59:00
         12 |           1 |   15000 | 2019-01-17 00:00:00 | 2019-01-20 00:00:00 | 2018-12-22 16:45:31.94 | 9999-12-01 23:59:00
         12 |           1 |   35000 | 2019-01-20 00:00:00 | 9999-12-01 23:59:00 | 2018-12-22 16:45:31.94 | 9999-12-01 23:59:00

Wir konnten bestätigen, dass der Saldo der zu ändernden historischen Daten aktualisiert werden konnte, während die historischen Daten vor der Änderung beibehalten wurden.

Schließlich

Nachdem ich Reladomo tatsächlich verwendet hatte, wurde mir klar, dass die Verwaltung des Datenverlaufs einfach zu realisieren ist. Insbesondere in Fällen, in denen Sie den Änderungsverlauf später für Audits usw. verfolgen möchten, können Sie anscheinend eine Verbesserung der Entwicklungseffizienz erwarten. Dies kann in vielen Situationen nützlich sein, wenn Sie mit der JVM-Sprache entwickeln.

Auswahl der Cache-Strategie für jede Entität, Multi-Threaded Matcher Loader (MTLoader) usw. Ich interessiere mich besonders für die Hochleistungsfunktionen von Reladomo Das möchte ich auch zu einem anderen Zeitpunkt untersuchen.

Materialien, die ich als Referenz verwendet habe

Als ich diesmal nachschlug, hatte ich das Gefühl, dass es viele englische Dokumente gab, aber alle waren von hoher Qualität.

Es gibt auch sehr leicht verständliche japanische Materialien, was sehr hilfreich war.

Recommended Posts

[Java] Vereinfachen Sie die Implementierung der Datenverlaufsverwaltung mit Reladomo
Berechnen Sie die Ähnlichkeitsbewertung von Zeichenketten mit JAVA
Geschichte der Java-Annotationen
CI die Architektur von Java / Kotlin-Anwendungen mit ArchUnit
Überwachen Sie den internen Status von Java-Programmen mit Kubernetes
Überprüfen Sie das Verhalten von Java Intrinsic Locks mit bpftrace
Die Geschichte von dto, dao-like mit Java, SQLite
Ersetzen Sie nur einen Teil des URL-Hosts durch Java
Die Geschichte der Erstellung einer Task-Management-Anwendung mit Swing, Java
[Java] Implementierung des Faistel-Netzwerks
Implementierung von XLPagerTabStrip mit TabBarController
Implementierung eines mathematischen Syntaxanalysators durch rekursive absteigende Syntaxanalysemethode (Java)
Die Falle, die die Standardimplementierung der Java 8-Schnittstelle mit sich bringt
Stellen Sie sicher, dass Sie das Java compareTo-Ergebnis mit 0 vergleichen
Java-Implementierung von Tri-Tree
Lesen Sie die Daten der Shizuoka Prefecture Point Cloud DB mit Java und erstellen Sie Luftbilder und Höhen-PNGs.
Lesen Sie die Daten der Shizuoka Prefecture Point Cloud DB mit Java und versuchen Sie, die Baumhöhe zu ermitteln.
Probieren Sie HelloWorld mit der Mindestkonfiguration von Heroku Java Spring-Boot aus
[Details] Implementierung von Consumer-Anwendungen mit der Kinesis Client Library für Java
Eine Geschichte über das Erreichen der League Of Legends-API mit JAVA
Der Suchtpunkt bei der Durchführung der Basisauthentifizierung mit Java URLConnection
Sehen Sie sich das Verhalten von Entitätsaktualisierungen mit Spring Boot + Spring Data JPA an
Überschreiben Sie den gleichnamigen Upload mit dem BOX SDK (Java).
Ist die von Ihnen verwendete Version von Elasticsearch mit Java 11 kompatibel?
[Java] Löschen Sie die Elemente von List
Filtern Sie die Schwankungen der Rohdaten
Folgen Sie dem Link mit Selen (Java)
[Java] Laufzeitdatenbereiche von JVM
Datenverwaltung von eigenen Büchern (Portfolio)
Der Ursprung von Java-Lambda-Ausdrücken
Implementierung einer ähnlichen Funktion in Java
Deklarieren Sie eine Methode mit einem Java-Rückgabewert mit dem Rückgabewert-Datentyp
Die Geschichte eines Game Launcher mit automatischer Ladefunktion [Java]
Dies und das der Implementierung der zeitlichen Beurteilung von Daten in Java
Überprüfen Sie den MX-Eintrag der E-Mail-Adresse mit Java und die Domain
[Java] Holen Sie sich MimeType aus dem Inhalt der Datei mit Apathce Tika [Kotlin]
Implementierung der Klonmethode für Java Record
Implementierung von DBlayer in Java (RDB, MySQL)
Holen Sie sich das Ergebnis von POST in Java
Erraten Sie das Java Persistence Framework 2017 (3) Reladomo
Überprüfen Sie den Inhalt des Java-Zertifikatspeichers
Überprüfen Sie den Inhalt der Parameter mit pry
Untersuchen Sie die Speichernutzung von Java-Elementen
[Java] Ermittelt den Tag eines bestimmten Tages
Anmerkung: [Java] Überprüfen Sie den Inhalt des Verzeichnisses
[Swift 5] Implementierung der Mitgliederregistrierung in Firebase
CICS-Java-Anwendung ausführen- (3) Build-Management mit Gradle
Vergleichen Sie Elemente eines Arrays (Java)
[Tag: 5] Ich habe die Grundlagen von Java zusammengefasst
Was sind die aktualisierten Funktionen von Java 13
Wie ist die Datenstruktur von ActionText?
Messen Sie einfach die Größe von Java-Objekten
CICS-Java-Anwendung ausführen- (2) Build-Management mit Maven
Rückblick auf die Grundlagen von Java
Ausgabe des Buches "Einführung in Java"
Über die Behandlung von BigDecimal (mit Reflexion)
Einführung eines automatisierten Java-Tests mit JUnit 5 + Gradle
Die Geschichte des Schreibens von Java in Emacs
Formatieren Sie den Inhalt von LocalDate mit DateTimeFormatter
[Java] Überprüfen Sie die Anzahl der Zeichen