Преобразование типов данных средствами JDBC Postgresql

Всем привет. У нас есть вендорское трехзвенное приложение :

  1. БД
  2. сeрвер приложений на Java (Spring + Tomcat + ORM Hibernate)
  3. клиентское приложение

Вендором заявлена поддержка как 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 код мы не можем. Собственно, вопросы

  1. Можно ли каким то образом задать на уровне БД, JDBC или Spring конвертацию по умолчанию integer в numeric, чтобы в java приезжал не integer, а уже numeric?
  2. Может кто то уже сталкивался с чем то подобным?

Интернет и нейросети советуют:

  1. поиграться с параметрами подключения JDBC - попробовал разное - без эффекта.
  2. прикрутить кастомный диалект на java - сделать свой jar, прописать в конфигах спринга - пока не получается, возможно из-за того, что конфигурация зашита в Java class без импорта конфига из xml

Либо кто то точно знает, что это нереально и решается только переписыванием кода Java?

(UPD) По первому вопросу: спросил в дискуссиях гитхаба под драйвером PgJDBC - там получил ответ, что параметрами драйвера типы нельзя переопределить По второму вопросу: в нашем приложении не предусмотрена конфигурация кроме то, что прописана в классах Java, соответственно не подложить кастомный диалект. Единственное решение - доработка исходного кода.


Ответы (1 шт):

Автор решения: Kseniya Sinickaya

Правильно ли я понимаю, что Вы везде используете getObject() в JDBC?

  1. Если Вы будете менять oid'ы кастов в pg, то убьете базу - это очень опасно.

  2. Если сделаете неявные преобразования bigint в numeric - это не поменяет типы, тк неявное преобразование срабатывает, например, при переполнении bigint, но если изменить cast на implicit, то "select count(*);" все равно будет давать bigint, и на стороне java ничего не изменится.

  3. Единственно возможное - это сделать обертку на 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);
         }
     }
    
  4. Еще лучше, если это возможно и невозможно редактировать код проекта на java: Сделать обертку библиотки JDBC с используемым в Вашем проекте функционалом с одноименным названием (если функционала не так много в проекте), то есть есть функция с сигнатурой - берите сигнатуру и возвращаете то же, что и JDBC, но с причесанными типами в ретурне, например все типы с числами приведите к BigDecimal.

  5. Или меняйте все запросы на явный каст в нумерик.

→ Ссылка