Как лучше хранить пары ключ значение в БД?

Рейтинг: 0Ответов: 2Опубликовано: 04.03.2025

У меня есть проект в виде маркетплейса, я пишу его на Java, с использованием Hibernate и Spring.

У меня есть сущности продавца, покупателя, продукта, заказа (order), корзины покупателя. У покупателя, продавца, и ордера есть поля в виде HashMap. В ней хранятся продукты (айди), в виде ключа, и их количество в качестве значения. Каким образом мне лучше хранить их в базе данных?

Нейронка предлагает вариант хранить их в качестве JSONB обьекта, то есть вложенная JSON-ка в другой JSON-ке. Но как я понял, Hibernate не умеет самостоятельно парсить мапу в JSON. Самому писать парсер не очень хочется, поэтому возникает вопрос, как еще можно эффективно мапы содержать в БД?

Ответы

▲ 1Принят

Использовать JSONB для хранения — это не самый лучший вариант. Поскольку не позволяет делать выборки тех же продуктов с помощью Hibernate. С другой стороны можно использовать Hibernate для мапинга коллекции продуктов в таблице, которая их использует. Для этого нужно

Использование @MapKeyColumn

Допустим, у нас есть сущность Order, и мы хотим отслеживать название и количество всех товаров в заказе. Итак, мы хотим ввести Map<Long, Integer> для Order, который будет сопоставлять product_id товара с его количеством:

@Entity
@Table(name = "orders")
public class Order {
@Id
@GeneratedValue
@Column(name = "id")
private Long id;

@ElementCollection
@CollectionTable(name = "order_product_mapping", 
joinColumns = {@JoinColumn(name = "order_id", referencedColumnName = "id")})
@MapKeyColumn(name = "product_id")
@Column(name = "qty")
private Map<Long, Integer> productQtyMap; 

// стандартные геттеры и сеттеры
}

Вам нужно указать Hibernate, где получить ключ и значение. Для ключа мы использовали @MapKeyColumn, указывая, что ключ Map — это столбец product_id нашей таблицы соединений order_product_mapping. Аналогично, @Column указывает, что значение Map соответствует столбцу qty таблицы соединений.

Кроме того, объект productQtyMap является мапой типа ключ-значение, поэтому мы должны использовать аннотацию @ElementCollection.

Помимо базовых объектов ключа-значения, объекты @Embeddable также могут использоваться в качестве значений Map аналогичным образом.

▲ 0

Hibernet умеет работать с мапами и jsonb. Пример кода -

@Column(name = "value")
@JdbcTypeCode(SqlTypes.JSON)
private Map<String, Object> value;

Где value в таблице БД это -

value   jsonb