Ссылки Spring Data REST для объектов, поступающих из ElasticSearch - PullRequest
0 голосов
/ 17 июня 2019

Я использую Spring Data REST, Spring Boot 2, Spring HATEOAS, ElasticSearch.

Это моя модель:

public class Document extends AbstractEntity {

    @NotNull
    @Column(nullable = false, columnDefinition = "DATE")
    private Instant date;

    //Define if the invoice/credit note are electronic
    @NotNull
    @Column(nullable = false, columnDefinition = "BIT DEFAULT 0")
    private boolean electronic;

    // Expected delivery date
    @Column(columnDefinition = "DATE")
    private Instant deliveryDate;

    @Column(nullable = false, updatable = false)
    private int year;

    @NotNull
    @Enumerated(EnumType.STRING)
    @Column(nullable = false, length = 30)
    private DocumentType type = DocumentType.SALES_INVOICE;


    @NotNull
    @Enumerated(EnumType.STRING)
    @ColumnDefault("'PENDING'")
    @Column(nullable = false, length = 30)
    private DocumentStatus status = DocumentStatus.PENDING;

    @NotNull
    @Enumerated(EnumType.STRING)
    @ColumnDefault("'OPEN'")
    @Column(nullable = false, length = 30)
    private DocumentDeliveryStatus deliveryStatus = DocumentDeliveryStatus.OPEN;

    ....
    ....
    ....

и строки документа

public class DocumentRow extends AbstractEntity {

    @NotNull
    @OnDelete(action = OnDeleteAction.CASCADE)
    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    private Document document;

    //used to keep rows sorted
    @Column(nullable = false, columnDefinition = "INT DEFAULT 1")
    private int index = 1;

    //Used to group lines of a document. Expecially useful in assembly orders to keep additional information about products like the relation to the right or left eye
    private String rowGroup;

    //The product's type. It's used also in conjunction with note to define when
    //the note represents a customer's frame for example
    @Column(length = 30)
    @Enumerated(EnumType.STRING)
    private ProductType productType;

    //Could be set also with a note to get info about the item even if it's not sold (customer's item for example)
    @JsonDeserialize(using = ProductUriDeserializer.class)
    @Any(fetch = FetchType.LAZY, metaDef = "ProductDocumentRowDef", metaColumn = @Column(name = "productGroup"))
    @AnyMetaDef(name = "ProductDocumentRowDef", metaType = "string", idType = "long", metaValues = {@MetaValue(value = "OL", targetEntity = OphthalmicLens.class),
            @MetaValue(value = "F", targetEntity = Frame.class), @MetaValue(value = "CL", targetEntity = ContactLens.class), @MetaValue(value = "GP", targetEntity = GenericProduct.class)})
    @JoinColumn(name = "product_id")
    private Product product;

    //Link to the parent document
    @JsonDeserialize(using = DocumentUriDeserializer.class)
    @ManyToOne(fetch = FetchType.LAZY)
    private Document linkedDocument;

    //Link to the parent document's row for example
    @JsonDeserialize(using = DocumentRowUriDeserializer.class)
    @ManyToOne(fetch = FetchType.LAZY)
    private DocumentRow linkedRow;

    //Useful if the foreign key is broken
    @Column(length = 50)
    private String productCode;

    // Row text description
    @Size(max = 255)
    @NotBlank
    @Column(nullable = false)
    private String description;

    // Reference to another document row (order/ddt/)
    @NotNull
    @Min(0)
    @Column(nullable = false)
    private int qty = 1;


    @NotNull
    @Min(value = 0)
    @ColumnDefault("0.000")
    @Column(nullable = false, scale = 3, columnDefinition = "DECIMAL(13,3)")
    private BigDecimal unitPrice = BigDecimal.ZERO;

    @Column(scale = 3, columnDefinition = "DECIMAL(13,3)")
    private BigDecimal purchaseUnitPrice;

    // (unit price * qty) - percentageDiscount% on that amount
    @NotNull
    @Min(value = 0)
    @ColumnDefault("0.000")
    @Column(nullable = false, scale = 3, columnDefinition = "DECIMAL(13,3)")
    private BigDecimal amount = BigDecimal.ZERO;

    @Min(value = 0)
    @Generated(value = GenerationTime.ALWAYS)
    @Column(columnDefinition = "DECIMAL(13,3) AS (purchaseUnitPrice*qty)")
    private BigDecimal purchaseAmount;

    @JsonDeserialize(using = TaxRateUriDeserializer.class)
    @ManyToOne(fetch = FetchType.EAGER)
    private TaxRate taxRate;

    // The total amount of taxes on taxable amount (unit price * qty) - percentageDiscount%
    @NotNull
    @Min(value = 0)
    @ColumnDefault("0.00")
    @Column(nullable = false, scale = 2, columnDefinition = "DECIMAL(12,2)")
    private BigDecimal taxAmount = BigDecimal.ZERO;

    // Total amount (amount+taxAmount)
    @Generated(value = GenerationTime.ALWAYS)
    @Column(columnDefinition = "DECIMAL(12,2) AS (amount+taxAmount)", scale = 2)
    private BigDecimal totalAmount;

    //says if the row is a note
    @NotNull
    @Column(nullable = false, columnDefinition = "BIT DEFAULT 0")
    private boolean note = false;

У меня есть суперкласс для продуктов:

@MappedSuperclass
public class Product extends AbstractEntity {

    @Column(nullable = false, unique = true, length = 50, updatable = false)
    private String searchKey;


    @NotBlank
    @Size(min = 4, max = 25)
    @Column(nullable = false, length = 30)
    private String sku;


    @Size(min = 9, max = 30)
    //@Pattern(regexp = "[0-9]+")
    @Column(nullable = true, length = 30)
    private String barcode;

    // produttore/supplier
    @NotBlank
    @Size(max = 255)
    @Column(nullable = false)
    private String manufacturer;

    @Size(max = 30)
    private String lineCode;

    //commercial name/family name
    @Size(max = 255)
    private String lineDescription;

    //@NotBlank
    @Size(max = 255)
    @Column(nullable = false)
    private String description;

и конкретных таблиц:

@Data
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Frame extends Product {

    @NotBlank
    @Column(nullable = false)
    private String model;

    @Size(max = 30)
    private String colorCode;

    @Size(max = 100)
    private String colorDescription;

    @Min(value = 20)
    @Max(value = 100)
    private Integer caliber;

У меня есть собственный контроллер для получения строк документа:

@Api(tags = "Document Entity")
@RepositoryRestController
@PreAuthorize("isAuthenticated()")
@Log4j2
public class DocumentController {

 @GetMapping(path = "/documents/{id}/rows")
    public ResponseEntity<?> getRows(@PathVariable(value = "id") long id, Pageable pageable, Locale locale,
                                     PersistentEntityResourceAssembler resourceAssembler) {
        return new ResponseEntity<PagedResources<?>>(
                pagedResourcesAssembler.toResource(documentRepository.rows(id, pageable), resourceAssembler), HttpStatus.OK);
    }

Когда я пытаюсь получить свой ресурс с помощью GET http://localhost:8082/api/v1/documents/15/rows?page=0&size=10, я получаю в ответ:

{
    "_embedded": {
        "documentRows": [
            {
                "sid": "fd822eb2-8206-44b5-9115-ae83755626e0",
                "createdBy": "system",
                "createdDate": "2019-06-11T10:37:52.593Z",
                "lastModifiedDate": "2019-06-11T10:37:52.593Z",
                "lastModifiedBy": "system",
                "createdByName": null,
                "lastModifiedByName": null,
                "index": 1,
                "rowGroup": null,
                "productType": "FRAME",
                "product": {
                    "sid": "1d0d0dba-097e-43cd-a441-66ec319d4b0b",
                    "createdBy": "system",
                    "createdDate": "2019-06-07T18:21:24.466Z",
                    "lastModifiedDate": "2019-06-07T18:21:24.466Z",
                    "lastModifiedBy": "system",
                    "createdByName": null,
                    "lastModifiedByName": null,
                    "searchKey": "GLOBAL_FR002_AL00101_IT",
                    "sku": "AL00101",
                    "barcode": "8029224592933",
                    "manufacturer": "AVM",
                    "lineCode": "ALS",
                    "lineDescription": "AVM 1959",
                    "description": "AVM AVM 1959 AL00101 01 53□17 140 Vista",
                    "purchasePrice": 18,
                    "salesPrice": 40.984,
                    "taxRate": 22,
                    "preset": true,
                    "discontinued": false,
                    "trial": false,
                    "imageUrl": "https://api.testapp.com/api/v1/avm/AL00101/image?size=big",
                    "thumbUrl": "https://api.testapp.com/api/v1/avm/AL00101/image?size=small",
                    "model": "AL00101",
                    "colorCode": "01",
                    "colorDescription": null,
                    "caliber": 53,
                    "bridge": 17,
                    "arm": 140,
                    "sphere": null,
                    "type": "GLASSES",
                    "material": "ACETATE",
                    "gender": "MAN",
                    "productType": "FRAME"
                },
                "productVariant": null,
                "project": null,
                "productCode": "GLOBAL_FR002_AL00101_IT",
                "description": "AVM AVM 1959 AL00101 01 53□17 140 Vista",
                "qty": 1,
                "reservedQty": 0,
                "acceptedQty": 0,
                "shippedQty": 0,
                "receivedQty": 0,
                "qtyToShip": 1,
                "unitPrice": 33.59,
                "purchaseUnitPrice": 18,
                "percentageDiscount": 0,
                "amount": 33.59,
                "purchaseAmount": 18,
                "taxAmount": 7.39,
                "totalAmount": 40.98,
                "note": false,
                "stsTaxDeductionCategory": null,
                "_links": {
                    "self": {
                        "href": "http://localhost:8082/api/v1/documentRows/22"
                    },
                    "documentRow": {
                        "href": "http://localhost:8082/api/v1/documentRows/22{?projection}",
                        "templated": true
                    },
                    "taxRate": {
                        "href": "http://localhost:8082/api/v1/documentRows/22/taxRate"
                    },
                    "document": {
                        "href": "http://localhost:8082/api/v1/documentRows/22/document{?projection}",
                        "templated": true
                    },
                    "linkedRow": {
                        "href": "http://localhost:8082/api/v1/documentRows/22/linkedRow{?projection}",
                        "templated": true
                    },
                    "linkedDocument": {
                        "href": "http://localhost:8082/api/v1/documentRows/22/linkedDocument{?projection}",
                        "templated": true
                    }
                }
            }
        ]
    },
    "_links": {
        "self": {
            "href": "http://localhost:8082/api/v1/documents/15/rows?page=0&size=10"
        }
    },
    "page": {
        "size": 10,
        "totalElements": 1,
        "totalPages": 1,
        "number": 0
    }
}

Как видите, продукт показан inline .Я должен сказать, что мои продукты получены из ElasticSearch, а не из Mysql.На ES они извлекаются с использованием String searchKey , а не по их длинному идентификатору.

Я переопределяю ProductRepository, но ничего не происходит.Я хотел бы иметь URL вместо продукта.Любая подсказка будет оценена.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...