简体   繁体   中英

Orphan and child handling in JPA/Hibernate

My table-structure is as follows. I have sales , that contains one or more shipments . Each shipment consists of one or more batches . What i try to achieve is that when i save a sale that i have removed shipments from, the shipments gets deleted and the batches are orphaned.

I have the following classes (shortened for brevity):

@Entity
public class Sale {
    @Id
    String orderNumber;

    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "sale")
    List<Shipment> shipments;
}

@Entity
public class Shipment {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    Integer id;

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "sale_order_number")
    Sale sale;

    @OneToMany
    List<Batch> batches;
}

@Entity
public class Batch {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    Integer id;

    @ManyToOne
    Shipment shipment;
}

My problem is that when JPA (or hibernate?) tries to remove the orphaned shipment, it just sets all the properties of the shipment to NULL except the id.

Normally null-values is not allowed but i reconfigured the table just to see what it was trying to do in the database.

Per request, here is my database before, expected and actual results. I added some properties to the shipment table to clarify some issues:

sale
order_number
1

shipment
id  sale_order_number   amount  ref
1   1                   54      'foo'
2   1                   62      'bar'

batch
id  shipment_id
1   1
1   2
2   1
2   1
2   2

Then i post the sale for an update, with a list not containing the shipment with id 2, this is what i expect when i save:

sale
order_number
1

shipment
id  sale_order_number   amount  ref
1   1                   54      'foo'

batch
id  shipment_id
1   1
1   NULL
2   1
2   1
2   NULL

The actual output. I got a constraint violation so i allowed the properties to be NULL just to see what happened. The query succeeded afterwards but the result baffles me:

sale
order_number
1

shipment
id  sale_order_number   amount  ref
1   1                   54      'foo'
2   NULL                NULL    NULL

batch
id  shipment_id
1   1
1   NULL
2   1
2   1
2   NULL

I think you should also add orphan removal flag to batches list like that

@Entity
public class Shipment {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Integer id;

@ManyToOne
@JoinColumn(name = "sale_order_number")
Sale sale;

@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "shipment")
List<Batch> batches;
}

Also it's good if you are creating your database using script or any migration framework to add to the foreign key the attribute "OnDelete=Cascade"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM