Проблема формата ответа Spring Data Rest HAL с объектами отложенной инициализации в режиме гибернации

#spring-boot #hibernate #spring-data-jpa #spring-data-rest #hateoas

#spring-boot #переход в режим гибернации #spring-data-jpa #весна-данные-отдых #hateoas

Вопрос:

Технологический стек: Spring Boot (2.3.1.RELEASE), Spring Data JPA, Sprign Data Rest (3.3.1 RELEASE), Hibernate (5.4.17 Final), PostgreSQL. У меня есть родительская сущность ProductEntity :

 @Data
@Entity
@Table(name = "product")
@EntityListeners(AuditingEntityListener.class)
public class ProductEntity {

    @NotNull
    @Id
    @EqualsAndHashCode.Exclude
    @Type(type = "pg-uuid")
    @GeneratedValue(generator = "uuid2")
    @GenericGenerator(name = "uuid2", strategy = "uuid2")
    private UUID id;

    @JsonProperty("productType")
    @ToString.Exclude
    @OneToOne(mappedBy = "productEntity", cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true, optional = false)
    private ProductTypeEntity productTypeEntity;
}
  

Завершите дочернюю сущность ProductTypeEntity :

 @Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Entity
@Table(name = "product_type")
@JsonIgnoreProperties({"hibernateLazyInitializer"})
public class ProductTypeEntity extends BaseEntity implements RootAware<ProductEntity> {
    
    @NotBlank
    @Size(max = 255)
    private String type;

    @NotBlank
    @Size(max = 255)
    private String brand;

    @OneToOne(fetch = FetchType.LAZY, optional = false)
    @MapsId
    @JoinColumn(name = "id")
    @ToString.Exclude
    @EqualsAndHashCode.Exclude
    @JsonIgnore
    private ProductEntity productEntity;

    @Override
    public ProductEntity root() {
        return productEntity;
    }
}
  

Конец существует один репозиторий Spring Data REST ProductRepository :

 @RepositoryRestResource(collectionResourceRel = "products", path = "products")
public interface ProductRepository extends JpaRepository<ProductEntity, UUID> {

}
  

Основная проблема заключается в том, что я запрашиваю ПОЛУЧЕНИЕ http://localhost:8081/api/v1/products Я получаю дополнительное содержимое поля под ProductType, которое полностью избыточно и препятствует адекватному анализу ответа :

 {
    "_embedded": {
        "products": [
            {
                "productType": {
                    "content": {
                        "type": "type1",
                        "brand": "brand1"
                    }
                }
                "_links": {
                    "self": {
                        "href": "http://localhost:8081/api/v1/products/6b0e375e-4d2d-41af-b42f-989859652c81"
                    },
                    "productEntity": {
                        "href": "http://localhost:8081/api/v1/products/6b0e375e-4d2d-41af-b42f-989859652c81"
                    }
                }
            }
        ]
    },
    "_links": {
        "self": {
            "href": "http://localhost:8081/api/v1/products"
        },
        "profile": {
            "href": "http://localhost:8081/api/v1/profile/products"
        }
    },
    "page": {
        "size": 20,
        "totalElements": 1,
        "totalPages": 1,
        "number": 0
    }
}
  

Но когда я меняю productTypeEntity с ЛЕНИВОГО на НЕТЕРПЕЛИВЫЙ :

 @JsonProperty("productType")
@ToString.Exclude
@OneToOne(mappedBy = "productEntity", cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true, optional = false)
private ProductTypeEntity productTypeEntity;
  

Я получаю правильный ответ без поля содержимого:

 {
    "_embedded": {
        "products": [
            {
                "productType": {
                    "type": "type1",
                    "brand": "brand1",
                    "_links": {
                        "productEntity": {
                            "href": "http://localhost:8081/api/v1/products/6b0e375e-4d2d-41af-b42f-989859652c81"
                        }
                    }
                },
                "_links": {
                    "self": {
                        "href": "http://localhost:8081/api/v1/products/6b0e375e-4d2d-41af-b42f-989859652c81"
                    },
                    "productEntity": {
                        "href": "http://localhost:8081/api/v1/products/6b0e375e-4d2d-41af-b42f-989859652c81"
                    }
                }
            }
        ]
    },
    "_links": {
        "self": {
            "href": "http://localhost:8081/api/v1/products"
        },
        "profile": {
            "href": "http://localhost:8081/api/v1/profile/products"
        }
    },
    "page": {
        "size": 20,
        "totalElements": 1,
        "totalPages": 1,
        "number": 0
    }
}
  

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

Комментарии:

1. Когда вы ПОЛУЧИТЕ /api/v1/products , хотите ли вы включить значение из ProductType (если не под content ) или исключить?

2. @yejianfengblue Я хочу включить ProductType, но не в разделе content. Желаемый ответ — второй из перечисленных выше. Мне просто нужно на 100% быть уверенным в его природе и возможных последствиях.

3. Теперь, когда вы всегда хотите, чтобы продукт содержал значение ProductType, зачем устанавливать для выборки значение lazy?