Как реализовать удаление сущности, с фактическим её сохранением, но недоступностью для новых операций?

Возникла архитектурная проблема.

Имеется сущность Warehouse. Я пытаюсь реализовать функционал удаления этой сущности. Проблема в том, что после удаления она должна продолжать существовать (потому что она может быть важна для некоторых других сущностей), но не быть в то же время доступной для каких-то новых операций.

Например: грузовик привёз на склад товары. В программе создаётся сущность Order, которая ссылается на сущность Warehouse. После этого мы хотим удалить сущность Warehouse, потому что, допустим, этот склад расформировали, но нам всё так же важны сущности Order, поэтому мы не удаляем Warehouse, а делаем недоступным для формирования новых заказов.

Warehouse:

@Entity
@Table(name = "warehouses")
public class Warehouse {

    @Id
    private Integer id;

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

Order:

@Entity
@Table(name = "orders")
public class Order {

    @Id
    private Integer id;

    @ManyToOne
    @JoinColumn(name = "warehouse_id")
    private Warehouse warehouse;

    @Column(name = "amount")
    private Integer amount;
}

Есть несколько вариантов решения этой задачи и ни один меня не устраивает:

Сделать в Warehouse поле isActive и проверять его перед каждым запросом

Это неплохой вариант, но он очень сложный, потому что Warehouse связан не только с Order, но и ещё с десятком сущностей. Сейчас я делаю простой JPQL-запрос:

SELECT w FROM Warehouse w WHERE w.id=:id

и его придётся модернизировать:

SELECT w FROM Warehouse w WHERE w.id=:id AND w.isActive=TRUE

причём надо понимать, что у меня таких запросов много и во всех очень разные условия.

Создать сущность DeletedWarehouse

Эта сущность ничем не будет отличаться от обычной сущности Warehouse, зато она не будет участвовать в запросах нормальных, ещё не удалённых сущностей. То есть в таком запросе:

SELECT w FROM Warehouse w WHERE w.id=:id

никаких удалённых складов мы не получим. Мне нравится этот вариант, но возникает вопрос - а какие поля делать, например, в сущности Order? Можно вот так:

@Entity
@Table(name = "orders")
public class Order {

    @Id
    private Integer id;

    @ManyToOne
    @JoinColumn(name = "deleted_warehouse_id")
    private DeletedWarehouse deletedWarehouse;

    @ManyToOne
    @JoinColumn(name = "warehouse_id")
    private Warehouse warehouse;

    @Column(name = "amount")
    private Integer amount;
}

Тут одно из полей всегда будет null: либо warehouse, либо deletedWarehouse. Это выглядит не очень адекватно.

Идеальный вариант

Идеальным вариантом было бы сделать сущности ActiveWarehouse и DeletedWarehouse, наследовать их от одного интерфейса, Warehouse:

Warehouse:

public interface Warehouse {

    int getId();

    String getName();
}

и, соответственно, этот интерфейс использовать в качестве поля в сущностях, которым нужен Warehouse. Например, вот так:

@Entity
@Table(name = "orders")
public class Order {

    @Id
    private Integer id;

    @ManyToOne
    @JoinColumn(name = "warehouse_id")
    private Warehouse warehouse; // это интерфейс

    @Column(name = "amount")
    private Integer amount;
}

Ну и как-то должна подгружаться нужная имплементация: ActiveWarehouse или DeletedWarehouse, в зависимости от того, какая из этих сущностей не null. Это был бы просто идеальный вариант, но я очень сомневаюсь, что что-то подобное возможно.


Ответы (0 шт):