在对引用非id字段的@ManytoOne字段进行当前操作之前,必须保存瞬态实例

时间:2019-06-19 15:33:17

标签: java hibernate spring-boot spring-data-jpa hibernate-mapping

我遇到了这个经典问题,但是我找不到任何人遇到完全相同的问题。

这是有问题的两个表

    Prices            OverrideCategory             
______________       __________________    
|id          |       |id              |
|bandId      |       |storeId         |
|sku         |       |priceCategory   |
|category    |       |overridePrice   |
|oldPrice    |       |reason          |
|newPrice    |       |author          |
|updateUTC   |       |updateUTC       |
______________       __________________

这就是我映射这两个表的方式。

@Entity
@Data
@NoArgsConstructor
@Table(name = "overrideCategory")
public class OverrideCategoryEntity extends Author {

    @Builder
    public OverrideCategoryEntity(@NotNull String reason, @NotNull String author, StoreEntity storeId, PricesEntity priceCategory, @NotNull BigDecimal overridePrice) {
        super(reason, author);
        this.storeId = storeId;
        this.priceCategory = priceCategory;
        this.overridePrice = overridePrice;
    }

    @JoinColumn(name = "storeId", nullable = false)
    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    private StoreEntity storeId;

    @JoinColumn(name = "priceCategory", referencedColumnName = "category", nullable = false)
    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    private PricesEntity priceCategory;

    @NotNull
    private BigDecimal overridePrice;
@Entity
@Data
@NoArgsConstructor
@Table(name = "prices")
public class PricesEntity extends Price {

    @Builder
    public PricesEntity(@NotNull BigDecimal oldPrice, @NotNull BigDecimal newPrice, BandsEntity bandId, @NotNull String sku, @NotNull String category) {
        super(oldPrice, newPrice);
        this.bandId = bandId;
        this.sku = sku;
        this.category = category;
    }

    @JoinColumn(name = "bandId", nullable = false)
    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    private BandsEntity bandId;

    @NotBlank
    private String sku;

    @NotBlank
    private String category;

这是我的控制人

@RestController
public class OverrideCategoryController {

    @Autowired
    private ModelMapper modelMapper;

    private final OverrideCategoryRepository repository;


    public OverrideCategoryController(OverrideCategoryRepository repository) {
        this.repository = repository;
    }

    @PostMapping("/categories")
    OverrideCategoryEntity newOverrideCategory(@RequestBody @Valid OverrideCategory overrideCategory) {
        OverrideCategoryEntity entity = modelMapper.map(overrideCategory, OverrideCategoryEntity.class);
        return repository.save(entity);
    }

这是我的存储库

public interface OverrideCategoryRepository extends JpaRepository<OverrideCategoryEntity, BigInteger> {

}

这是我用于端点的DTO

@Data
public class OverrideCategory extends Author {

    @NotNull
    private BigInteger storeId;

    @NotBlank
    private String priceCategory;

    @NotNull
    @Min(value = 0)
    private BigDecimal overridePrice;

}

这是我要发送的Json

{
    "storeId": 1,
    "priceCategory": "category",
    "overridePrice": 50.23,
    "reason": "reason",
    "author": "author"
}

这是我得到的错误

2019-06-19 15:39:07.850  WARN 27026 --- [nio-8118-exec-1] o.h.a.i.UnresolvedEntityInsertActions    : HHH000437: Attempting to save one or more entities that have a non-nullable association with an unsaved transient entity. The unsaved transient entity must be saved in an operation prior to saving these dependent entities.
    Unsaved transient entity: ([com.priceengine.domain.PricesEntity#<null>])
    Dependent entities: ([[com.priceengine.domain.OverrideCategoryEntity#<null>]])
    Non-nullable association(s): ([com.priceengine.domain.OverrideCategoryEntity.priceCategory])
2019-06-19 15:39:07.910 ERROR 27026 --- [nio-8118-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.TransientPropertyValueException: Not-null property references a transient value - transient instance must be saved before current operation : com.priceengine.domain.OverrideCategoryEntity.priceCategory -> com.priceengine.domain.PricesEntity; nested exception is java.lang.IllegalStateException: org.hibernate.TransientPropertyValueException: Not-null property references a transient value - transient instance must be saved before current operation : com.priceengine.domain.OverrideCategoryEntity.priceCategory -> com.priceengine.domain.PricesEntity] with root cause


org.hibernate.TransientPropertyValueException: Not-null property references a transient value - transient instance must be saved before current operation : com.priceengine.domain.OverrideCategoryEntity.priceCategory -> com.priceengine.domain.PricesEntity; nested exception is java.lang.IllegalStateException: org.hibernate.TransientPropertyValueException: Not-null property references a transient value - transient instance must be saved before current operation : com.priceengine.domain.OverrideCategoryEntity.priceCategory -> com.priceengine.domain.PricesEntity

prices表中有数据,我尝试了级联选项,我认为这可能是DTO与实体之间的映射,但是该映射适用于我拥有的其他表。其他表仅具有一个 @ManyToOne 批注,并且它们引用父表中的ID。

此表具有两个 @ManyToOne 关系,然后其中之一没有引用id,这是否有问题?

1 个答案:

答案 0 :(得分:0)

我能够通过更改实体的映射来解决问题。

@Entity
@Data
@NoArgsConstructor
@Table(name = "overrideCategory")
public class OverrideCategoryEntity extends Author {

    @Builder
    public OverrideCategoryEntity(@NotNull String reason, @NotNull String author, BigInteger storeId, String priceCategory, @NotNull BigDecimal overridePrice) {
        super(reason, author);
        this.storeId = storeId;
        this.priceCategory = priceCategory;
        this.overridePrice = overridePrice;
    }

    @JoinColumn(name = "storeId", insertable = false, updatable = false, nullable = false)
    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    private StoreEntity storeEntity;

    @JoinColumn(name = "priceCategory", referencedColumnName = "category", insertable = false, updatable = false, nullable = false)
    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    private PricesEntity pricesEntity;

    @Column(name = "priceCategory")
    private String priceCategory;

    @Column(name = "storeId")
    private BigInteger storeId;

    @NotNull
    private BigDecimal overridePrice;

我做了很多测试,并且一切正常,但是我认为这不是映射实体的正确方法。这样映射实体存在任何问题吗?