@ColumnTransformer в Hibernate / JPA
Аннотация @ColumnTransformer (из пакета org.hibernate.annotations) позволяет кастомизировать SQL-выражения для чтения (read) и записи (write) значений столбца в БД.
Используется, когда необходимо:
Применить функцию БД при загрузке (SELECT).
Преобразовать значение перед вставкой/обновлением (INSERT/UPDATE).
Работать с зашифрованными или вычисляемыми полями.
Аннотация принимает следующие атрибуты:
read (String):
SQL-выражение, применяемое при чтении значения из БД.
Может включать функции БД (например, decrypt, CAST, COALESCE).
Использует плейсхолдер ? для исходного значения столбца.
Пример:
write (String):
SQL-выражение, применяемое при записи значения в БД.
Также использует плейсхолдер ? для нового значения.
Пример:
forColumn (String, опционально):
Указывает имя столбца, если оно отличается от имени поля в сущности.
Жизненный цикл и обработка
При загрузке сущности (SELECT)
Hibernate заменяет прямое обращение к столбцу на выражение из read.
Пример SQL:
При сохранении (INSERT/UPDATE)
Значение поля преобразуется выражением из write.
Пример SQL:
Нативные запросы
Если используется EntityManager.createNativeQuery(), @ColumnTransformer игнорируется (требуется ручное применение функций БД).
Механизмы Hibernate и интеграция
Генерация SQL
Обработка @ColumnTransformer происходит на этапе компиляции HQL в SQL (через ASTQueryTranslatorFactory).
Зависимость от диалекта БД
Выражения в read/write должны быть совместимы с диалектом БД (например, AES_ENCRYPT в MySQL, PGP_SYM_ENCRYPT в PostgreSQL).
Интеграция с JPA
Аннотация является Hibernate-специфичной и не входит в стандарт JPA.
Примеры использования
1. Шифрование данных
2. Преобразование типов
3. Условные значения
Ограничения и настройки
Производительность
Сложные выражения могут замедлять запросы.
Поддержка в JPQL
В JPQL-запросах @ColumnTransformer не применяется (только в SQL, генерируемом Hibernate).
Альтернативы
Для сложной логики можно использовать:
@Convert (JPA 2.1).
Реализацию UserType в Hibernate.
Настройка через hibernate.xml
Нет глобальной настройки для @ColumnTransformer — только через аннотации.
#Java #Training #Hard #Spring #Hibernate #ColumnTransformer
Аннотация @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