Java for Beginner
672 subscribers
541 photos
155 videos
12 files
827 links
Канал от новичков для новичков!
Изучайте Java вместе с нами!
Здесь мы обмениваемся опытом и постоянно изучаем что-то новое!

Наш YouTube канал - https://www.youtube.com/@Java_Beginner-Dev

Наш канал на RUTube - https://rutube.ru/channel/37896292/
Download Telegram
@ColumnTransformer в Hibernate / JPA

Аннотация @ColumnTransformer (из пакета org.hibernate.annotations) позволяет кастомизировать SQL-выражения для чтения (read) и записи (write) значений столбца в БД.

Используется, когда необходимо:
Применить функцию БД при загрузке (SELECT).
Преобразовать значение перед вставкой/обновлением (INSERT/UPDATE).
Работать с зашифрованными или вычисляемыми полями.


Аннотация принимает следующие атрибуты:

read (String):
SQL-выражение, применяемое при чтении значения из БД.
Может включать функции БД (например, decrypt, CAST, COALESCE).
Использует плейсхолдер ? для исходного значения столбца.


Пример:
@ColumnTransformer(read = "decrypt(credit_card_num, 'my_secret_key')")
private String creditCardNumber;


write (String):
SQL-выражение, применяемое при записи значения в БД.
Также использует плейсхолдер ? для нового значения.

Пример:
@ColumnTransformer(write = "encrypt(?, 'my_secret_key')")
private String password;


forColumn (String, опционально):
Указывает имя столбца, если оно отличается от имени поля в сущности.

Жизненный цикл и обработка

При загрузке сущности (SELECT)
Hibernate заменяет прямое обращение к столбцу на выражение из read.


Пример SQL:
SELECT decrypt(credit_card_num, 'my_secret_key') FROM users WHERE id = 1;


При сохранении (INSERT/UPDATE)
Значение поля преобразуется выражением из write.

Пример SQL:
INSERT INTO users (password) VALUES (encrypt('qwerty', 'my_secret_key'));


Нативные запросы
Если используется EntityManager.createNativeQuery(), @ColumnTransformer игнорируется (требуется ручное применение функций БД).

Механизмы Hibernate и интеграция

Генерация SQL
Обработка @ColumnTransformer происходит на этапе компиляции HQL в SQL (через ASTQueryTranslatorFactory).

Зависимость от диалекта БД
Выражения в read/write должны быть совместимы с диалектом БД (например, AES_ENCRYPT в MySQL, PGP_SYM_ENCRYPT в PostgreSQL).

Интеграция с JPA
Аннотация является Hibernate-специфичной и не входит в стандарт JPA.

Примеры использования

1. Шифрование данных
@Entity
public class User {
@Id
private Long id;

@ColumnTransformer(
read = "pgp_sym_decrypt(credit_card_num, 'secret_key')",
write = "pgp_sym_encrypt(?, 'secret_key')"
)
@Column(name = "credit_card_num")
private String creditCardNumber;
}


2. Преобразование типов
@ColumnTransformer(
read = "CAST(price AS decimal(10,2))",
write = "CAST(? AS varchar)"
)
private BigDecimal price;


3. Условные значения
@ColumnTransformer(
read = "COALESCE(status, 'DEFAULT')"
)
private String status;


Ограничения и настройки


Производительность

Сложные выражения могут замедлять запросы.

Поддержка в JPQL
В JPQL-запросах @ColumnTransformer не применяется (только в SQL, генерируемом Hibernate).

Альтернативы
Для сложной логики можно использовать:
@Convert (JPA 2.1).
Реализацию UserType в Hibernate.
Настройка через hibernate.xml
Нет глобальной настройки для
@ColumnTransformer — только через аннотации.

#Java #Training #Hard #Spring #Hibernate #ColumnTransformer