Cannot shorten OneToMany relationship

Hi there!
In my kotlin SpringBoot application, I am using an Hibernate Core dependency to handle the persistence for my PostgreSQL db and I am experiencing a weird issue trying to remove an occurrence inside a one-to-many relationship.
Let me explain better…
I have two entities Batch and Order, linked by an one-to-many relationship (so one Batch consists of a list of placed orders, and an Order can belong to a single Batch).

This is how they are built:

@Entity
@Table(name = "batches")
data class Batch(
    @Id
    @GeneratedValue
    val id: UUID? = null,

    @LazyCollection(LazyCollectionOption.FALSE)
    @OneToMany(cascade = [CascadeType.MERGE], orphanRemoval = true)
    @JoinColumn(name = "batchId", nullable = false)
    var orders: List<Order>,

   ...
)
@Entity
@Table(name = "orders")
data class Order(
    @Id
    @GeneratedValue
    val id: UUID? = null,

    @Column(insertable = false, updatable = false)
    var batchId: UUID? = null,

   ...
)

This is the SQL script:

CREATE TABLE batches (
  id                        UUID                     NOT NULL PRIMARY KEY,
  ...
);

CREATE TABLE orders (
  id                        UUID                     NOT NULL PRIMARY KEY,
  batch_id                  UUID                     REFERENCES batches (id),
  ...
);
CREATE INDEX idx_orders_batch_id ON orders(batch_id);

And the following is the pseudo-code to do that:

fun shortenOrdersList(batch: Batch, ordersToBeRemoved: List<Order>): Batch {
  // unlinking orders from batch
  existingBatch.orders = existingBatch.orders - ordersToBeRemoved
  // updating the batch
  val updatedBatch = batchRepository.save(existingBatch)
  return updatedBatch
}

Now the issue…
Imagine having a batch B that is composed of 5 orders and then we want to remove an order X from this list, but keeping the order row in its table.
So, what I expect is that:

  • the batch’s orders list is shortened and it’s 4 orders long;
  • the order X is not related to the batch B anymore but it continues to exist in the Order table with field batchId as null.

Currently, the output of the shortenOrdersList function is a batch with the correct shortened order’s list (so, a list of 4 orders, in our example), but here comes the issue because when I try to fetch again the batch from the db…

val fetchedBatch = batchRepository.findById(batchId)

…I realize that the change has not been reflected into the db (so, in our example, the batch B still has a list of 5 orders and the order X still has the related batchId valued).

I tried to add a more step to the above function: updating each order to be removed with batchId=null but nothing.
The only solution I found is: for each order that needs to be unlinked from the batch, deleting it and storing it again with batchId=null. This works but seems to be an ugly workaround (old order id is lost, new id is created, etc).
Another workaround could be: creating a separate table, made of two columns (batch_id and order_id), where the relationship between batches and orders are handled by myself.

Is this something that any of you has already seen before? It seems very weird that Hibernate cannot allow to shorten a one-to-many relationship, maybe am I doing something wrong?

Thank you all!

First of all, your use of orphanRemoval would mean that a Order should be deleted once removed from a set, so you should use orphanRemoval = false. Apart from that, you are specifying that the batchId join column is not-nullable, so why do you expect that it will be set to null then?

orphanRemoval = false is right, I have overlooked it
the solution was setting nullable=true in the @JoinColumn annotation

thank you very much! solved!