У меня есть одна из странных проблем, которые заставляют вас рычать. У меня есть (тоже странное) приложение Spring/Hibernate, предназначенное для управления базой данных следующим образом (я упростил некоторые вещи, поэтому не путайте, что в исходном коде упоминаются несколько разные таблицы/столбцы):Спящий режим: не удалять дочернюю коллекцию на родительском удалении
active_proxy_view table:
id | entity
<uuid> | <string containing json>
archive_proxy_view table:
id | entity
<uuid> | <string containing json>
track_reference table:
ref_type | ref_id | track_domain | track_type | track_id |
'proxy' | <uuid> | 'example.com' | 'customer' | '123' |
Сохранение двух таблиц является обязательным - мне нужно иметь как все время-историю/статистические запросы, так и запросы бизнес-значений только для вещей, которые сейчас активны, поэтому мне нужно постоянно устанавливать активные активные прокси. track_reference
таблица используется для поиска, так что я мог сделать запросы так:
SELECT p.id, p.entity FROM archive_proxy_view AS p
INNER JOIN track_reference AS t1 ON
t1.ref_id = p.id AND
t1.ref_type = 'proxy' AND
t1.track_domain = 'example.com' AND
t1.track_type = 'customer' AND
t1.track_id = '123'
INNER JOIN track_reference AS t2 ON
t2.ref_id = p.id AND
t2.ref_type = 'proxy' AND
t2.track_domain = 'example.com' AND
t2.track_type = 'campaign' AND
t2.track_id = 'halloween-2017'
(это может быть не 100% правильно, я не сырой опыт SQL в то время)
И вот проблема:
- Оба
active_proxy_view
иarchive_proxy_view
объекты наследуются от одного класса, который определяет@OneToMany
отношений O ntrack_reference
объект;@ManyToOne
использование не представляется возможным, потому что есть много сущностей, привязанные к отслеживанию, присвоенный track_reference
управляется отдельно (и это обязательно тоже)- мне нужно управлять видом отдельно от
track_reference
таблицы, но всякий раз, когда я говорю Hibernate, чтобы удалить объект отactive_proxy_view
стол, он убираетtrack_reference
объектов. Даже если я играю с каскадным значением аннотации, которое по умолчанию пусто (и, как я понимаю, это означает, что дочерние записи не следует удалять родителем). Однако есть вероятность, что я что-то пропустил. я также не смог взломать все это с помощью пользовательских
@SQLDeleteAll
, я до сих пор можно увидеть регулярные удалений в общем журнале:55 Query delete from tracking_reference where referenced_entity_id='13c6b55c-f9b7-4de7-8bd4-958d487e461c' and referenced_entity_type='proxy' and tracked_entity_type='agent' 55 Query delete from tracking_reference where referenced_entity_id='13c6b55c-f9b7-4de7-8bd4-958d487e461c' and referenced_entity_type='proxy' and tracked_entity_type='lead' 55 Query delete from tracking_reference where referenced_entity_id='13c6b55c-f9b7-4de7-8bd4-958d487e461c' and referenced_entity_type='proxy' and tracked_entity_type='source' 53 Query DELETE FROM `tracking_reference` WHERE `referenced_entity_type` = 'proxy' AND referenced_entity_id = '13c6b55c-f9b7-4de7-8bd4-958d487e461c' AND 1 = 0
Я использую Hibernate 5.2.3.Final через Spring 4.3.2. RELEASE/Spring Data JPA 1.10.2.RELEASE
TL; DR
Итак, возникает вопрос: как я могу запретить Hibernate удалять связанные объекты, когда родитель удален?
Исходный код для субъектов выглядит следующим образом:
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class ProxyViewEntryTemplate {
@Id
@NotNull
@Column(nullable = false)
private String id;
@NotNull
@Column
private String entity;
// some other columns
@OneToMany
@JoinColumn(name = TrackRef.REFERENCE_ID_COLUMN_NAME) // 'reference_entity_id`
@Where(clause = ProxyView.TRACK_WHERE_JOIN_CLAUSE) // `referenced_entity_type` = 'proxy'
@SQLDeleteAll(sql = ProxyView.TRACK_DELETE_ALL_QUERY) // DELETE FROM `tracking_reference` WHERE `referenced_entity_type` = 'proxy' AND referenced_entity_id = ? AND 1 = 0
private Collection<TrackingReference> track = new ArrayList<>();
// setters, getters, hashCode, equals
}
@Entity
@Table(name = "active_proxy")
public class ActiveProxyViewEntry extends ProxyViewEntryTemplate {}
@Entity
@Table(name = "tracking_reference")
@IdClass(TrackingReferenceId.class)
public class TrackingReference {
@Id
@Column(name = "tracked_entity_type", nullable = false)
@NotNull
private String trackedType;
@Id
@Column(name = "tracked_entity_domain", nullable = false)
private String trackedDomain;
@Id
@Column(name = "tracked_entity_id", nullable = false)
private String trackedId;
@Id
@Column(name = "referenced_entity_type", nullable = false)
@NotNull
private String referencedType;
@Id
@Column(name = "referenced_entity_id", nullable = false)
@NotNull
private String referencedId;
// setters, getters, hashCode, equals
}
Все это управляется с помощью Spring JPA Хранилища:
@NoRepositoryBean
public interface SuperRepository<E, ID extends Serializable> extends PagingAndSortingRepository<E, ID>,
JpaSpecificationExecutor<E> {
}
public interface ActiveProxyViewRepository extends SuperRepository<ActiveProxyViewEntry, String> {}
// the call for deletion
public CompletableFuture<Void> delete(ID id) {
...
descriptor.getRepository().delete(descriptor.getIdentifierConverter().convert(id));
...
}
// which is equal to
...
ActiveProxyViewRepository repository = descriptor.getRepository();
String uuidAsString = descriptor.getIdentifierConverter().convert(id);
repository.delete(uuidAsString);
...
Пожалуйста, укажите код, показывающий, как вы удаляете объект. – Naros
@ Naros сделано, хотя не уверен, что это поможет много – Etki