JPA / Гибернация, перекрывающая столбцы PK и FK

#sql #postgresql #hibernate #jpa #foreign-keys

#sql #postgresql #гибернация #jpa #внешние ключи

Вопрос:

мы используем Postgres и JPA / Hibernate для импорта большого количества данных раз в две недели (~ 50-100 млн строк на импорт). Мы пытаемся разделить наши таблицы для каждого импорта, из-за чего мы сталкиваемся с некоторыми проблемами сопоставления столбцов PK / FK в режиме гибернации. По сути, это настройка на стороне SQL

 CREATE TABLE row (
import_timestamp timestamp,
id uuid,
PRIMARY KEY (import_timestamp, id)
) PARTITION BY LIST (import_timestamp);

CREATE TABLE row_detail (
import_timestamp timestamp,
id uuid,
row_id uuid,
PRIMARY KEY(import_timestamp, id),
CONSTRAINT row_detail_row_fk FOREIGN KEY (row_id, import_timestamp) REFERENCES row (id, import_timestamp)
) PARTITION BY LIST (import_timestamp);
  

и это на стороне Java:

 
@Entity(name = "row")
public class RowEntity {

    @EmbeddedId
    private PartitionedId id;

    @OneToMany(cascade = ALL, mappedBy = "row")
    private List<RowDetailEntity> details;
}

@Entity(name = "row_detail")
public class RowDetailEntity {

    @EmbeddedId
    private PartitionedId id;

    @ManyToOne
    @JoinColumns({
            @JoinColumn(name = "row_id", referencedColumnName = "id"),
            @JoinColumn(name = "importTimestamp", referencedColumnName = "importTimestamp")
    })
    private RowEntity row;
}

@Embeddable
public class PartitionedId implements Serializable {
    private Instant importTimestamp;
    private UUID id;
}
  

Затем Hibernate жалуется при загрузке, что:

 column: import_timestamp (should be mapped with insert="false" update="false")
  

Я могу отключить эту ошибку, выполнив то, что указано, но в этом мало смысла, потому что я вынужден устанавливать insertable=false и updatable=false для обоих @JoinColumn() s , что означало row_id бы, что он не заполняется при вставке.

Я мог бы пойти по этому @MapsId пути, но только если я дам row_detail таблице PK, которая включает все 3 свойства (import_timestamp, id, row_id), и я действительно не хочу или не нуждаюсь в этом.

Итак, вопрос в том, как мне заставить Hibernate понимать мои перекрывающиеся, но не полностью вложенные PK / FK?

Комментарии:

1. Я думаю, это @OneToMany(cascade = ALL, mappedBy = "row") следует исправить на @OneToMany(cascade = CascadeType.ALL, mappedBy = "fahrt")

2. просто игнорируйте RowDetailEntity, имеющий составной PK — идентификатор является UUID и поэтому гарантированно будет уникальным сам по себе. Использование RowDetailEntity только базового сопоставления идентификаторов в столбце ID упростит приложение для этого варианта использования.

3. @SternK да, проскользнуло, когда я упростил свои доменные модели для вопроса. На самом деле должно быть исправлено наоборот : private RowEntity row . Я отредактировал сообщение.

4. @Chris ну да, но проблема с разделением заключается в том, что вы не хотите выполнять запросы, в которых отсутствует столбец разделения. Так что любая форма SELECT * FROM row_detail WHERE id = '...' — плохая идея. Я должен включить AND import_timestamp = '...' , потому что postgres по существу сохраняет небольшой индекс для каждого раздела, а не один большой индекс для всех них. Поэтому, если бы я хотел найти что-то только по его «id», он не знал бы, в каком разделе искать, и должен был бы искать во всех из них или сканировать все, что не идеально.

5. ID — это конструкция, которую ваше приложение не должно знать или использовать. JPA нуждается в этом для идентификации, но пока вы избегаете findById и ссылок на эту сущность, ваше приложение может использовать составной ключ раздела для поиска. Фактически, у других поставщиков есть решения для разделения, так что вы можете моделировать свой объект только с помощью идентификатора и автоматически добавлять ключ разделения — я просто недостаточно хорошо знаю hibernate, чтобы сказать, может ли он это сделать. Что-то эквивалентное eclipse.org/eclipselink/documentation/2.5/jpa/extensions /…