Преобразование типов данных средствами JDBC Postgresql
Всем привет. У нас есть вендорское трехзвенное приложение :
- БД
- сeрвер приложений на Java (Spring + Tomcat + ORM Hibernate)
- клиентское приложение
Вендором заявлена поддержка как Oracle, так и Postgresql. (решается сменой DataSource в конфигурации в Tomcat)
При миграции на Postgresql столкнулись с хардкодом в java части, где есть запросы типа select count(*) или select 1 from ...
При этом такой код общий - и для Oracle и для Postgresql.
Далеe при обработке этих запросов вендор результат запросов явно приводит к BigDecimal. В Oracle срабатывает, в Postgresql дает ошибку приведения: java.math.BigInteger cannot be cast to java.math.BigDecimal
На текущий момент править java код мы не можем.
Собственно, вопросы
- Можно ли каким то образом задать на уровне БД, JDBC или Spring конвертацию по умолчанию integer в numeric, чтобы в java приезжал не integer, а уже numeric?
- Может кто то уже сталкивался с чем то подобным?
Интернет и нейросети советуют:
- поиграться с параметрами подключения JDBC - попробовал разное - без эффекта.
- прикрутить кастомный диалект на java - сделать свой jar, прописать в конфигах спринга - пока не получается, возможно из-за того, что конфигурация зашита в Java class без импорта конфига из xml
Либо кто то точно знает, что это нереально и решается только переписыванием кода Java?
(UPD) По первому вопросу: спросил в дискуссиях гитхаба под драйвером PgJDBC - там получил ответ, что параметрами драйвера типы нельзя переопределить По второму вопросу: в нашем приложении не предусмотрена конфигурация кроме то, что прописана в классах Java, соответственно не подложить кастомный диалект. Единственное решение - доработка исходного кода.
Ответы (1 шт):
Правильно ли я понимаю, что Вы везде используете getObject() в JDBC?
Если Вы будете менять oid'ы кастов в pg, то убьете базу - это очень опасно.
Если сделаете неявные преобразования bigint в numeric - это не поменяет типы, тк неявное преобразование срабатывает, например, при переполнении bigint, но если изменить cast на implicit, то "select count(*);" все равно будет давать bigint, и на стороне java ничего не изменится.
Единственно возможное - это сделать обертку на java, хотя бы jar с приведением всех числоподобных типов к bigdecimal
public static BigDecimal convertToBigDecimal(Object value) { if (value == null) { return null; } if (value instanceof BigDecimal) { return (BigDecimal) value; } else if (value instanceof BigInteger) { return new BigDecimal((BigInteger) value); } else if (value instanceof Integer) { return new BigDecimal((Integer) value); } else if (value instanceof Long) { return new BigDecimal((Long) value); } else if (value instanceof Double) { return BigDecimal.valueOf((Double) value); } else if (value instanceof Float) { return BigDecimal.valueOf((Float) value); } else if (value instanceof String) { return new BigDecimal((String) value); } else if (value instanceof Number) { // Для любых других числовых типов return new BigDecimal(value.toString()); } else { throw new IllegalArgumentException("Unsupported numeric type: " + value.getClass().getName() + " with value: " + value); } }Еще лучше, если это возможно и невозможно редактировать код проекта на java: Сделать обертку библиотки JDBC с используемым в Вашем проекте функционалом с одноименным названием (если функционала не так много в проекте), то есть есть функция с сигнатурой - берите сигнатуру и возвращаете то же, что и JDBC, но с причесанными типами в ретурне, например все типы с числами приведите к BigDecimal.
Или меняйте все запросы на явный каст в нумерик.