无法在休眠状态下保存实体

Posted

技术标签:

【中文标题】无法在休眠状态下保存实体【英文标题】:Can't save entity in hibernate 【发布时间】:2018-11-06 13:04:10 【问题描述】:

我创建了简单的 CRUD 服务。有 4 个实体:客户、提供商、产品、交易。

CustomerProvider 实体组成了具有以下结构的 id AppId

@Getter
@Setter
@Embeddable
@NoArgsConstructor
public class AppId implements Serializable 
    private String app;
    private String id;
    //...

这是我想要的业务逻辑: Providers 实体级联并创建 Product 实体。 当客户与提供商交易时,我需要创建实体Deal,它不会级联任何其他实体。 它只有涉及供应商、客户和交易产品的字段。

我创建了一些提供商和客户。 然后我尝试创建交易,但我得到了字段客户和提供商null

这是我的实体定义:


Provider:
@Entity
@Getter
@Setter
@ToString
@NoArgsConstructor
@Table(name = "provider")
public class Provider implements Serializable 

    @EmbeddedId
    @Column(name = "appid")
    private AppId appId;

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

    @Column(name = "firstname")
    private String firstName;

    @Column(name = "lastname")
    private String lastName;

    @Column(name = "latitude")
    private float latitude;

    @Column(name = "longitude")
    private float longitude;

    @Column(name = "work_date")
    private Date workDate;

    @ManyToMany(cascade = CascadeType.ALL)
    @JoinTable(name = "provider_product"
            , joinColumns = 
                @JoinColumn(name = "provider_app"),
                @JoinColumn(name = "provider_id")
            
            , inverseJoinColumns = @JoinColumn(name="product_id"))
    private Set<Product> products;

    @OneToMany(cascade = CascadeType.ALL)
    @JoinColumns(
            @JoinColumn(name = "app", referencedColumnName = "app", updatable = false, insertable = false),
            @JoinColumn(name = "id", referencedColumnName = "id", updatable = false, insertable = false)
    )
    private List<Deal> dealList = new ArrayList<>();


Customer:
@Entity
@Getter
@Setter
@ToString
@NoArgsConstructor
@Table(name = "customer")
public class Customer implements Serializable 

    @EmbeddedId
    @Column(name = "appid")
    private AppId appId;

    @Column(name = "firstname")
    private String firstName;

    @Column(name = "lastname")
    private String lastName;

    public Customer(AppId appId, String firstName, String lastName) 
        this.appId = appId;
        this.firstName = firstName;
        this.lastName = lastName;
    


Product:
@Entity
@Getter
@Setter
@ToString
@NoArgsConstructor
@Table(name = "product")
public class Product implements Serializable 

    @Id
    @GeneratedValue
    private long id;

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

    @Column(name = "cost")
    private long cost;


Deal:
@Entity
@Getter
@Setter
@ToString
@NoArgsConstructor
@Table(name = "deal")
public class Deal implements Serializable 

    @Id
    @GeneratedValue
    private long id;

    @ManyToOne
    @JoinColumns(
            @JoinColumn(name = "provider_app", referencedColumnName = "app", insertable = false, updatable = false),
            @JoinColumn(name = "provider_id", referencedColumnName = "id", insertable = false, updatable = false)
    )
    private Provider provider;

    @ManyToOne
    @JoinColumns(
            @JoinColumn(name = "customer_app", insertable = false, updatable = false),
            @JoinColumn(name = "customer_id", insertable = false, updatable = false)
    )
    private Customer customer;

    @ManyToMany
    @JoinTable(name = "deal_product"
            , joinColumns = @JoinColumn(name="deal_id", insertable = false, updatable = false)
            , inverseJoinColumns = @JoinColumn(name="product_id", insertable = false, updatable = false))
    private Set<Product> product;

    // deal is complete when provider entered deal id
    @Column(name = "closed")
    private boolean closed = false;

【问题讨论】:

为什么insertable = falseDeal 实体中有providercustomer 字段? @harsh 因为在创建 deal 实体时,您无法创建新的 providercustomerdeal 只有在之前创建了providercustomer 时才能创建。 请分享您创建和保存交易的代码,不看就很难说什么 @harsh 项目链接:github.com/oybek/shavuha-CRUD/tree/master/src/main/java/com/… 【参考方案1】:

通过删除customerprovider 实体中provider 字段的insertable = false,一切正常。

    
    "id": 5,
    "provider": 
        "appId": 
            "app": "vk",
            "id": "123"
        ,
        "name": null,
        "firstName": null,
        "lastName": null,
        "latitude": 0,
        "longitude": 0,
        "workDate": null,
        "products": null,
        "dealList": []
    ,
    "customer": 
        "appId": 
            "app": "vk",
            "id": "123"
        ,
        "firstName": null,
        "lastName": null
    ,
    "product": [
        
            "id": 2,
            "name": "Temp",
            "cost": 100
        
    ],
    "closed": false

我可以得到以下响应。

insertable = false 在字段上意味着当您保存实体时,您不会保存该字段的值,而是会在某处显式设置该字段。

insertable = true 并不意味着您将创建一个新的CustomerProvider,由CascadeType 处理

【讨论】:

它在创建不正确的交易时重写提供者实体

以上是关于无法在休眠状态下保存实体的主要内容,如果未能解决你的问题,请参考以下文章

电脑休眠怎么唤醒?

电脑的休眠和睡眠有啥区别

睡眠 休眠 关闭硬盘 分别是啥意思?

HTTP 状态 400 - 错误请求 - 休眠

无法同步数据库状态

@Transient 不能在休眠状态下工作