기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.
3단계: 테이블, 인덱스 및 샘플 데이터 생성
중요
지원 종료 알림: 기존 고객은 2025년 7월 31일 지원이 종료될 QLDB 때까지 Amazon을 사용할 수 있습니다. 자세한 내용은 아마존 QLDB 원장을 Amazon Aurora SQL Postgre로 마이그레이션을
Amazon QLDB 원장이 활성화되고 연결을 수락하면 차량, 소유자 및 등록 정보에 대한 데이터를 위한 테이블 생성을 시작할 수 있습니다. 테이블과 인덱스를 생성한 후 데이터를 로드할 수 있습니다.
이 단계에서는 vehicle-registration
원장에 4개의 테이블을 생성합니다.
-
VehicleRegistration
-
Vehicle
-
Person
-
DriversLicense
또한 다음과 같은 인덱스를 생성합니다.
테이블 이름 | 필드 |
---|---|
VehicleRegistration |
VIN |
VehicleRegistration |
LicensePlateNumber |
Vehicle |
VIN |
Person |
GovId |
DriversLicense |
LicenseNumber |
DriversLicense |
PersonId |
샘플 데이터를 삽입할 때는 먼저 Person
테이블에 문서를 삽입합니다. 그런 다음 각 Person
문서에서 시스템이 할당한 id
를 사용하여 적절한 VehicleRegistration
및 DriversLicense
문서의 해당 필드를 채웁니다.
작은 정보
가장 좋은 방법은 문서의 시스템 할당 id
를 외래 키로 사용하는 것입니다. 고유 식별자로 사용할 필드 (예: 차량VIN) 를 정의할 수 있지만, 문서의 진정한 고유 식별자는 해당 필드입니다. id
이 필드는 문서의 메타데이터에 포함되며 커밋된 뷰(테이블의 시스텀 정의 뷰)에서 쿼리할 수 있습니다.
의 뷰에 대한 자세한 내용은 QLDB 을 참조하십시오핵심 개념. 메타데이터에 대해 자세히 알아보려면 문서 메타데이터 쿼리 섹션을 참조하세요.
샘플 데이터를 설정하려면
-
다음
.java
파일을 검토합니다. 이러한 모델 클래스는vehicle-registration
테이블에 저장하는 문서를 나타냅니다. Amazon Ion 형식으로 또는 Amazon Ion 형식에서 직렬화할 수 있습니다.참고
아마존 QLDB 문서의 상위 집합인 이온 형식으로 저장됩니다. JSON 따라서 Faster XML Jackson 라이브러리를 사용하여 데이터를 모델링할 수 있습니다JSON.
-
DriversLicense.java
/* * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: MIT-0 * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * software and associated documentation files (the "Software"), to deal in the Software * without restriction, including without limitation the rights to use, copy, modify, * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package software.amazon.qldb.tutorial.model; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import software.amazon.qldb.tutorial.model.streams.RevisionData; import java.time.LocalDate; /** * Represents a driver's license, serializable to (and from) Ion. */ public final class DriversLicense implements RevisionData { private final String personId; private final String licenseNumber; private final String licenseType; @JsonSerialize(using = IonLocalDateSerializer.class) @JsonDeserialize(using = IonLocalDateDeserializer.class) private final LocalDate validFromDate; @JsonSerialize(using = IonLocalDateSerializer.class) @JsonDeserialize(using = IonLocalDateDeserializer.class) private final LocalDate validToDate; @JsonCreator public DriversLicense(@JsonProperty("PersonId") final String personId, @JsonProperty("LicenseNumber") final String licenseNumber, @JsonProperty("LicenseType") final String licenseType, @JsonProperty("ValidFromDate") final LocalDate validFromDate, @JsonProperty("ValidToDate") final LocalDate validToDate) { this.personId = personId; this.licenseNumber = licenseNumber; this.licenseType = licenseType; this.validFromDate = validFromDate; this.validToDate = validToDate; } @JsonProperty("PersonId") public String getPersonId() { return personId; } @JsonProperty("LicenseNumber") public String getLicenseNumber() { return licenseNumber; } @JsonProperty("LicenseType") public String getLicenseType() { return licenseType; } @JsonProperty("ValidFromDate") public LocalDate getValidFromDate() { return validFromDate; } @JsonProperty("ValidToDate") public LocalDate getValidToDate() { return validToDate; } @Override public String toString() { return "DriversLicense{" + "personId='" + personId + '\'' + ", licenseNumber='" + licenseNumber + '\'' + ", licenseType='" + licenseType + '\'' + ", validFromDate=" + validFromDate + ", validToDate=" + validToDate + '}'; } }
-
Person.java
/* * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: MIT-0 * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * software and associated documentation files (the "Software"), to deal in the Software * without restriction, including without limitation the rights to use, copy, modify, * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package software.amazon.qldb.tutorial.model; import java.time.LocalDate; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import software.amazon.qldb.TransactionExecutor; import software.amazon.qldb.tutorial.Constants; import software.amazon.qldb.tutorial.model.streams.RevisionData; /** * Represents a person, serializable to (and from) Ion. */ public final class Person implements RevisionData { private final String firstName; private final String lastName; @JsonSerialize(using = IonLocalDateSerializer.class) @JsonDeserialize(using = IonLocalDateDeserializer.class) private final LocalDate dob; private final String govId; private final String govIdType; private final String address; @JsonCreator public Person(@JsonProperty("FirstName") final String firstName, @JsonProperty("LastName") final String lastName, @JsonProperty("DOB") final LocalDate dob, @JsonProperty("GovId") final String govId, @JsonProperty("GovIdType") final String govIdType, @JsonProperty("Address") final String address) { this.firstName = firstName; this.lastName = lastName; this.dob = dob; this.govId = govId; this.govIdType = govIdType; this.address = address; } @JsonProperty("Address") public String getAddress() { return address; } @JsonProperty("DOB") public LocalDate getDob() { return dob; } @JsonProperty("FirstName") public String getFirstName() { return firstName; } @JsonProperty("LastName") public String getLastName() { return lastName; } @JsonProperty("GovId") public String getGovId() { return govId; } @JsonProperty("GovIdType") public String getGovIdType() { return govIdType; } /** * This returns the unique document ID given a specific government ID. * * @param txn * A transaction executor object. * @param govId * The government ID of a driver. * @return the unique document ID. */ public static String getDocumentIdByGovId(final TransactionExecutor txn, final String govId) { return SampleData.getDocumentId(txn, Constants.PERSON_TABLE_NAME, "GovId", govId); } @Override public String toString() { return "Person{" + "firstName='" + firstName + '\'' + ", lastName='" + lastName + '\'' + ", dob=" + dob + ", govId='" + govId + '\'' + ", govIdType='" + govIdType + '\'' + ", address='" + address + '\'' + '}'; } }
-
VehicleRegistration.java
/* * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: MIT-0 * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * software and associated documentation files (the "Software"), to deal in the Software * without restriction, including without limitation the rights to use, copy, modify, * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package software.amazon.qldb.tutorial.model; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import software.amazon.qldb.TransactionExecutor; import software.amazon.qldb.tutorial.Constants; import software.amazon.qldb.tutorial.model.streams.RevisionData; import java.math.BigDecimal; import java.time.LocalDate; /** * Represents a vehicle registration, serializable to (and from) Ion. */ public final class VehicleRegistration implements RevisionData { private final String vin; private final String licensePlateNumber; private final String state; private final String city; private final BigDecimal pendingPenaltyTicketAmount; private final LocalDate validFromDate; private final LocalDate validToDate; private final Owners owners; @JsonCreator public VehicleRegistration(@JsonProperty("VIN") final String vin, @JsonProperty("LicensePlateNumber") final String licensePlateNumber, @JsonProperty("State") final String state, @JsonProperty("City") final String city, @JsonProperty("PendingPenaltyTicketAmount") final BigDecimal pendingPenaltyTicketAmount, @JsonProperty("ValidFromDate") final LocalDate validFromDate, @JsonProperty("ValidToDate") final LocalDate validToDate, @JsonProperty("Owners") final Owners owners) { this.vin = vin; this.licensePlateNumber = licensePlateNumber; this.state = state; this.city = city; this.pendingPenaltyTicketAmount = pendingPenaltyTicketAmount; this.validFromDate = validFromDate; this.validToDate = validToDate; this.owners = owners; } @JsonProperty("City") public String getCity() { return city; } @JsonProperty("LicensePlateNumber") public String getLicensePlateNumber() { return licensePlateNumber; } @JsonProperty("Owners") public Owners getOwners() { return owners; } @JsonProperty("PendingPenaltyTicketAmount") public BigDecimal getPendingPenaltyTicketAmount() { return pendingPenaltyTicketAmount; } @JsonProperty("State") public String getState() { return state; } @JsonProperty("ValidFromDate") @JsonSerialize(using = IonLocalDateSerializer.class) @JsonDeserialize(using = IonLocalDateDeserializer.class) public LocalDate getValidFromDate() { return validFromDate; } @JsonProperty("ValidToDate") @JsonSerialize(using = IonLocalDateSerializer.class) @JsonDeserialize(using = IonLocalDateDeserializer.class) public LocalDate getValidToDate() { return validToDate; } @JsonProperty("VIN") public String getVin() { return vin; } /** * Returns the unique document ID of a vehicle given a specific VIN. * * @param txn * A transaction executor object. * @param vin * The VIN of a vehicle. * @return the unique document ID of the specified vehicle. */ public static String getDocumentIdByVin(final TransactionExecutor txn, final String vin) { return SampleData.getDocumentId(txn, Constants.VEHICLE_REGISTRATION_TABLE_NAME, "VIN", vin); } @Override public String toString() { return "VehicleRegistration{" + "vin='" + vin + '\'' + ", licensePlateNumber='" + licensePlateNumber + '\'' + ", state='" + state + '\'' + ", city='" + city + '\'' + ", pendingPenaltyTicketAmount=" + pendingPenaltyTicketAmount + ", validFromDate=" + validFromDate + ", validToDate=" + validToDate + ", owners=" + owners + '}'; } }
-
Vehicle.java
/* * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: MIT-0 * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * software and associated documentation files (the "Software"), to deal in the Software * without restriction, including without limitation the rights to use, copy, modify, * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package software.amazon.qldb.tutorial.model; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import software.amazon.qldb.tutorial.model.streams.RevisionData; /** * Represents a vehicle, serializable to (and from) Ion. */ public final class Vehicle implements RevisionData { private final String vin; private final String type; private final int year; private final String make; private final String model; private final String color; @JsonCreator public Vehicle(@JsonProperty("VIN") final String vin, @JsonProperty("Type") final String type, @JsonProperty("Year") final int year, @JsonProperty("Make") final String make, @JsonProperty("Model") final String model, @JsonProperty("Color") final String color) { this.vin = vin; this.type = type; this.year = year; this.make = make; this.model = model; this.color = color; } @JsonProperty("Color") public String getColor() { return color; } @JsonProperty("Make") public String getMake() { return make; } @JsonProperty("Model") public String getModel() { return model; } @JsonProperty("Type") public String getType() { return type; } @JsonProperty("VIN") public String getVin() { return vin; } @JsonProperty("Year") public int getYear() { return year; } @Override public String toString() { return "Vehicle{" + "vin='" + vin + '\'' + ", type='" + type + '\'' + ", year=" + year + ", make='" + make + '\'' + ", model='" + model + '\'' + ", color='" + color + '\'' + '}'; } }
-
Owner.java
/* * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: MIT-0 * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * software and associated documentation files (the "Software"), to deal in the Software * without restriction, including without limitation the rights to use, copy, modify, * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package software.amazon.qldb.tutorial.model; import com.fasterxml.jackson.annotation.JsonProperty; /** * Represents a vehicle owner, serializable to (and from) Ion. */ public final class Owner { private final String personId; public Owner(@JsonProperty("PersonId") final String personId) { this.personId = personId; } @JsonProperty("PersonId") public String getPersonId() { return personId; } @Override public String toString() { return "Owner{" + "personId='" + personId + '\'' + '}'; } }
-
Owners.java
/* * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: MIT-0 * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * software and associated documentation files (the "Software"), to deal in the Software * without restriction, including without limitation the rights to use, copy, modify, * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package software.amazon.qldb.tutorial.model; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.List; /** * Represents a set of owners for a given vehicle, serializable to (and from) Ion. */ public final class Owners { private final Owner primaryOwner; private final List<Owner> secondaryOwners; public Owners(@JsonProperty("PrimaryOwner") final Owner primaryOwner, @JsonProperty("SecondaryOwners") final List<Owner> secondaryOwners) { this.primaryOwner = primaryOwner; this.secondaryOwners = secondaryOwners; } @JsonProperty("PrimaryOwner") public Owner getPrimaryOwner() { return primaryOwner; } @JsonProperty("SecondaryOwners") public List<Owner> getSecondaryOwners() { return secondaryOwners; } @Override public String toString() { return "Owners{" + "primaryOwner=" + primaryOwner + ", secondaryOwners=" + secondaryOwners + '}'; } }
-
DmlResultDocument.java
/* * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: MIT-0 * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * software and associated documentation files (the "Software"), to deal in the Software * without restriction, including without limitation the rights to use, copy, modify, * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package software.amazon.qldb.tutorial.qldb; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; /** * Contains information about an individual document inserted or modified * as a result of DML. */ public class DmlResultDocument { private String documentId; @JsonCreator public DmlResultDocument(@JsonProperty("documentId") final String documentId) { this.documentId = documentId; } public String getDocumentId() { return documentId; } @Override public String toString() { return "DmlResultDocument{" + "documentId='" + documentId + '\'' + '}'; } }
-
RevisionData.java
/* * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: MIT-0 * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * software and associated documentation files (the "Software"), to deal in the Software * without restriction, including without limitation the rights to use, copy, modify, * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package software.amazon.qldb.tutorial.model.streams; /** * Allows modeling the content of all revisions as a generic revision data. Used * in the {@link Revision} and extended by domain models in {@link * software.amazon.qldb.tutorial.model} to make it easier to write the {@link * Revision.RevisionDataDeserializer} that must deserialize the {@link * Revision#data} from different domain models. */ public interface RevisionData { }
-
RevisionMetadata.java
/* * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: MIT-0 * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * software and associated documentation files (the "Software"), to deal in the Software * without restriction, including without limitation the rights to use, copy, modify, * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package software.amazon.qldb.tutorial.qldb; import com.amazon.ion.IonInt; import com.amazon.ion.IonString; import com.amazon.ion.IonStruct; import com.amazon.ion.IonTimestamp; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.dataformat.ion.IonTimestampSerializers; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Date; import java.util.Objects; /** * Represents the metadata field of a QLDB Document */ public class RevisionMetadata { private static final Logger log = LoggerFactory.getLogger(RevisionMetadata.class); private final String id; private final long version; @JsonSerialize(using = IonTimestampSerializers.IonTimestampJavaDateSerializer.class) private final Date txTime; private final String txId; @JsonCreator public RevisionMetadata(@JsonProperty("id") final String id, @JsonProperty("version") final long version, @JsonProperty("txTime") final Date txTime, @JsonProperty("txId") final String txId) { this.id = id; this.version = version; this.txTime = txTime; this.txId = txId; } /** * Gets the unique ID of a QLDB document. * * @return the document ID. */ public String getId() { return id; } /** * Gets the version number of the document in the document's modification history. * @return the version number. */ public long getVersion() { return version; } /** * Gets the time during which the document was modified. * * @return the transaction time. */ public Date getTxTime() { return txTime; } /** * Gets the transaction ID associated with this document. * * @return the transaction ID. */ public String getTxId() { return txId; } public static RevisionMetadata fromIon(final IonStruct ionStruct) { if (ionStruct == null) { throw new IllegalArgumentException("Metadata cannot be null"); } try { IonString id = (IonString) ionStruct.get("id"); IonInt version = (IonInt) ionStruct.get("version"); IonTimestamp txTime = (IonTimestamp) ionStruct.get("txTime"); IonString txId = (IonString) ionStruct.get("txId"); if (id == null || version == null || txTime == null || txId == null) { throw new IllegalArgumentException("Document is missing required fields"); } return new RevisionMetadata(id.stringValue(), version.longValue(), new Date(txTime.getMillis()), txId.stringValue()); } catch (ClassCastException e) { log.error("Failed to parse ion document"); throw new IllegalArgumentException("Document members are not of the correct type", e); } } /** * Converts a {@link RevisionMetadata} object to a string. * * @return the string representation of the {@link QldbRevision} object. */ @Override public String toString() { return "Metadata{" + "id='" + id + '\'' + ", version=" + version + ", txTime=" + txTime + ", txId='" + txId + '\'' + '}'; } /** * Check whether two {@link RevisionMetadata} objects are equivalent. * * @return {@code true} if the two objects are equal, {@code false} otherwise. */ @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } RevisionMetadata metadata = (RevisionMetadata) o; return version == metadata.version && id.equals(metadata.id) && txTime.equals(metadata.txTime) && txId.equals(metadata.txId); } /** * Generate a hash code for the {@link RevisionMetadata} object. * * @return the hash code. */ @Override public int hashCode() { // CHECKSTYLE:OFF - Disabling as we are generating a hashCode of multiple properties. return Objects.hash(id, version, txTime, txId); // CHECKSTYLE:ON } }
-
QldbRevision.java
/* * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: MIT-0 * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * software and associated documentation files (the "Software"), to deal in the Software * without restriction, including without limitation the rights to use, copy, modify, * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package software.amazon.qldb.tutorial.qldb; import com.amazon.ion.IonBlob; import com.amazon.ion.IonStruct; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import software.amazon.qldb.tutorial.Constants; import software.amazon.qldb.tutorial.Verifier; import java.io.IOException; import java.util.Arrays; import java.util.Objects; /** * Represents a QldbRevision including both user data and metadata. */ public final class QldbRevision { private static final Logger log = LoggerFactory.getLogger(QldbRevision.class); private final BlockAddress blockAddress; private final RevisionMetadata metadata; private final byte[] hash; private final byte[] dataHash; private final IonStruct data; @JsonCreator public QldbRevision(@JsonProperty("blockAddress") final BlockAddress blockAddress, @JsonProperty("metadata") final RevisionMetadata metadata, @JsonProperty("hash") final byte[] hash, @JsonProperty("dataHash") final byte[] dataHash, @JsonProperty("data") final IonStruct data) { this.blockAddress = blockAddress; this.metadata = metadata; this.hash = hash; this.dataHash = dataHash; this.data = data; } /** * Gets the unique ID of a QLDB document. * * @return the {@link BlockAddress} object. */ public BlockAddress getBlockAddress() { return blockAddress; } /** * Gets the metadata of the revision. * * @return the {@link RevisionMetadata} object. */ public RevisionMetadata getMetadata() { return metadata; } /** * Gets the SHA-256 hash value of the revision. * This is equivalent to the hash of the revision metadata and data. * * @return the byte array representing the hash. */ public byte[] getHash() { return hash; } /** * Gets the SHA-256 hash value of the data portion of the revision. * This is only present if the revision is redacted. * * @return the byte array representing the hash. */ public byte[] getDataHash() { return dataHash; } /** * Gets the revision data. * * @return the revision data. */ public IonStruct getData() { return data; } /** * Returns true if the revision has been redacted. * @return a boolean value representing the redaction status * of this revision. */ public Boolean isRedacted() { return dataHash != null; } /** * Constructs a new {@link QldbRevision} from an {@link IonStruct}. * * The specified {@link IonStruct} must include the following fields * * - blockAddress -- a {@link BlockAddress}, * - metadata -- a {@link RevisionMetadata}, * - hash -- the revision's hash calculated by QLDB, * - dataHash -- the user data's hash calculated by QLDB (only present if revision is redacted), * - data -- an {@link IonStruct} containing user data in the document. * * If any of these fields are missing or are malformed, then throws {@link IllegalArgumentException}. * * If the document hash calculated from the members of the specified {@link IonStruct} does not match * the hash member of the {@link IonStruct} then throws {@link IllegalArgumentException}. * * @param ionStruct * The {@link IonStruct} that contains a {@link QldbRevision} object. * @return the converted {@link QldbRevision} object. * @throws IOException if failed to parse parameter {@link IonStruct}. */ public static QldbRevision fromIon(final IonStruct ionStruct) throws IOException { try { BlockAddress blockAddress = Constants.MAPPER.readValue(ionStruct.get("blockAddress"), BlockAddress.class); IonBlob revisionHash = (IonBlob) ionStruct.get("hash"); IonStruct metadataStruct = (IonStruct) ionStruct.get("metadata"); IonStruct data = ionStruct.get("data") == null || ionStruct.get("data").isNullValue() ? null : (IonStruct) ionStruct.get("data"); IonBlob dataHash = ionStruct.get("dataHash") == null || ionStruct.get("dataHash").isNullValue() ? null : (IonBlob) ionStruct.get("dataHash"); if (revisionHash == null || metadataStruct == null) { throw new IllegalArgumentException("Document is missing required fields"); } byte[] dataHashBytes = dataHash != null ? dataHash.getBytes() : QldbIonUtils.hashIonValue(data); verifyRevisionHash(metadataStruct, dataHashBytes, revisionHash.getBytes()); RevisionMetadata metadata = RevisionMetadata.fromIon(metadataStruct); return new QldbRevision( blockAddress, metadata, revisionHash.getBytes(), dataHash != null ? dataHash.getBytes() : null, data ); } catch (ClassCastException e) { log.error("Failed to parse ion document"); throw new IllegalArgumentException("Document members are not of the correct type", e); } } /** * Converts a {@link QldbRevision} object to string. * * @return the string representation of the {@link QldbRevision} object. */ @Override public String toString() { return "QldbRevision{" + "blockAddress=" + blockAddress + ", metadata=" + metadata + ", hash=" + Arrays.toString(hash) + ", dataHash=" + Arrays.toString(dataHash) + ", data=" + data + '}'; } /** * Check whether two {@link QldbRevision} objects are equivalent. * * @return {@code true} if the two objects are equal, {@code false} otherwise. */ @Override public boolean equals(final Object o) { if (this == o) { return true; } if (!(o instanceof QldbRevision)) { return false; } final QldbRevision that = (QldbRevision) o; return Objects.equals(getBlockAddress(), that.getBlockAddress()) && Objects.equals(getMetadata(), that.getMetadata()) && Arrays.equals(getHash(), that.getHash()) && Arrays.equals(getDataHash(), that.getDataHash()) && Objects.equals(getData(), that.getData()); } /** * Create a hash code for the {@link QldbRevision} object. * * @return the hash code. */ @Override public int hashCode() { // CHECKSTYLE:OFF - Disabling as we are generating a hashCode of multiple properties. int result = Objects.hash(blockAddress, metadata, data); // CHECKSTYLE:ON result = 31 * result + Arrays.hashCode(hash); return result; } /** * Throws an IllegalArgumentException if the hash of the revision data and metadata * does not match the hash provided by QLDB with the revision. */ public void verifyRevisionHash() { // Certain internal-only system revisions only contain a hash which cannot be // further computed. However, these system hashes still participate to validate // the journal block. User revisions will always contain values for all fields // and can therefore have their hash computed. if (blockAddress == null && metadata == null && data == null && dataHash == null) { return; } try { IonStruct metadataIon = (IonStruct) Constants.MAPPER.writeValueAsIonValue(metadata); byte[] dataHashBytes = isRedacted() ? dataHash : QldbIonUtils.hashIonValue(data); verifyRevisionHash(metadataIon, dataHashBytes, hash); } catch (IOException e) { throw new IllegalArgumentException("Could not encode revision metadata to ion.", e); } } private static void verifyRevisionHash(IonStruct metadata, byte[] dataHash, byte[] expectedHash) { byte[] metadataHash = QldbIonUtils.hashIonValue(metadata); byte[] candidateHash = Verifier.dot(metadataHash, dataHash); if (!Arrays.equals(candidateHash, expectedHash)) { throw new IllegalArgumentException("Hash entry of QLDB revision and computed hash " + "of QLDB revision do not match"); } } }
-
IonLocalDateDeserializer.java
/* * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: MIT-0 * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * software and associated documentation files (the "Software"), to deal in the Software * without restriction, including without limitation the rights to use, copy, modify, * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package software.amazon.qldb.tutorial.model; import com.amazon.ion.Timestamp; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import java.io.IOException; import java.time.LocalDate; /** * Deserializes [java.time.LocalDate] from Ion. */ public class IonLocalDateDeserializer extends JsonDeserializer<LocalDate> { @Override public LocalDate deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { return timestampToLocalDate((Timestamp) jp.getEmbeddedObject()); } private LocalDate timestampToLocalDate(Timestamp timestamp) { return LocalDate.of(timestamp.getYear(), timestamp.getMonth(), timestamp.getDay()); } }
-
IonLocalDateSerializer.java
/* * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: MIT-0 * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * software and associated documentation files (the "Software"), to deal in the Software * without restriction, including without limitation the rights to use, copy, modify, * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package software.amazon.qldb.tutorial.model; import com.amazon.ion.Timestamp; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.ser.std.StdScalarSerializer; import com.fasterxml.jackson.dataformat.ion.IonGenerator; import java.io.IOException; import java.time.LocalDate; /** * Serializes [java.time.LocalDate] to Ion. */ public class IonLocalDateSerializer extends StdScalarSerializer<LocalDate> { public IonLocalDateSerializer() { super(LocalDate.class); } @Override public void serialize(LocalDate date, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { Timestamp timestamp = Timestamp.forDay(date.getYear(), date.getMonthValue(), date.getDayOfMonth()); ((IonGenerator) jsonGenerator).writeValue(timestamp); } }
-
-
vehicle-registration
테이블에 삽입한 샘플 데이터를 나타내는 다음 파일(SampleData.java
)을 검토하세요.참고
-
이 클래스는 Ion 라이브러리를 사용하여 데이터를 Ion 형식으로 또는 Ion 형식에서 변환하는 도우미 메서드를 제공합니다.
-
이
getDocumentId
메서드는 접두사_ql_committed_
가 있는 테이블에 대한 쿼리를 실행합니다. 이는 테이블의 커밋된 보기를 쿼리하려는 것을 나타내는 예약된 접두사입니다. 이 뷰에서는 데이터가data
필드에 중첩되고 메타데이터는metadata
필드에 중첩됩니다.
-
-
다음 프로그램(
CreateTable.java
)을 컴파일하고 실행하여 앞서 언급한 테이블을 생성합니다.참고
이 프로그램은
TransactionExecutor
Lambda를execute
메서드에 전달하는 방법을 보여줍니다. 이 예제에서는 Lambda 표현식을 사용하여 단일 트랜잭션에서 여러CREATE TABLE
PartiQL 명령문을 실행합니다.execute
메서드는 암시적으로 트랜잭션을 시작하고 Lambda에서 모든 문을 실행한 다음 트랜잭션을 자동 커밋합니다. -
앞에서 설명한 대로 다음 프로그램(
CreateIndex.java
)을 컴파일하고 실행하여 테이블에 인덱스를 생성합니다. -
다음 프로그램(
InsertDocument.java
)을 컴파일하고 실행하여 샘플 데이터를 테이블에 삽입합니다.참고
-
이 프로그램은 파라미터화된 값을 사용하여
execute
메서드를 호출하는 방법을 보여줍니다. 실행하려는 PartiQL 문 외에도IonValue
유형의 데이터 파라미터를 전달할 수 있습니다. 명령문 문자열에서 물음표(?
)를 변수 자리 표시자로 사용하세요. -
INSERT
문이 성공하면 삽입된 각 문서의id
이 반환됩니다.
-
다음으로, SELECT
문을 사용하여 vehicle-registration
원장의 테이블에서 데이터를 읽을 수 있습니다. 4단계: 원장에서 테이블 쿼리로 이동합니다.