Как работать с интервальным типом данных PostgreSQL, используя jdbc/spring-jdbc, не используя PGInterval?

Типы данных даты и времени Java, как всем известно, нет необходимости сосредотачиваться на этом.

Однако когда я использую расширения на основе JDBC или Spring, такие как SimpleJdbcTemplate, для извлечения и хранения значений interval, какой тип Java следует использовать, если я не хочу использовать org.postgresql. класс util.PGInterval?

Этот класс является внутренним для драйвера PostgreSQL, поэтому его использование сделает код специфичным для БД. Я думаю, что должна быть возможность работать с интервалами независимо от БД, потому что это один из стандартных типов SQL.


person Danubian Sailor    schedule 04.01.2012    source источник
comment
Чтобы избежать зависимости от расширений, я обычно заканчиваю тем, что изменяю свой sql-запрос, чтобы он возвращал столбец String, а не пользовательский тип (если это возможно). Итак, в этом случае to_char(interval, formatString), затем используйте сопоставитель строк на стороне клиента, чтобы проанализировать и преобразовать полученную строку в соответствующий объект. Не самый элегантный, но часто простой.   -  person Glenn    schedule 19.01.2012


Ответы (1)


interval не является одним из стандартных типов JDBC, перечисленных в классе java.sql.Types. Я знаю, что если вы вызываете resultSet.getObject("interval_column"), это будет PGInterval при преобразовании, поэтому похоже, что драйвер PG JDBC может заставить вашу руку иметь дело с ним как таковым, если вы не сделаете то, что говорит Гленн, и не преобразуете его в строку, или, может быть, число в вашем SQL.

В нашем приложении мы используем JodaTime для всего нашего управления датами, и у нас есть написанный Hibernate Type, который преобразует наше свойство bean-компонента в PGInterval и из него, а также использует getObject и setObject для связи с JDBC. Я сомневаюсь, что этот код поможет вам справиться с тем, что вы ищете здесь, но я могу поделиться им с вами, если вам интересно.

ОБНОВЛЕНО: Вот класс Hibernate Type, который преобразует Joda Time в PGInterval. Я знаю, что это не ответ на вопрос, но первоначальный постер попросил пример кода.

package com.your.package.hibernate.types;

import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;

import org.hibernate.HibernateException;
import org.hibernate.usertype.UserType;
import org.joda.time.DurationFieldType;
import org.joda.time.Period;
import org.joda.time.ReadableDuration;
import org.joda.time.ReadablePeriod;
import org.postgresql.util.PGInterval;

public class JodaTimeDurationType
    implements UserType {

    public Class<?> returnedClass() {
        return ReadableDuration.class;
    }


    public int[] sqlTypes() {
        return new int[] {Types.OTHER};
    }


    public Object nullSafeGet(ResultSet resultSet, String[] names, Object owner)
        throws HibernateException, SQLException {

        try {
            final PGInterval pgi = (PGInterval)resultSet.getObject(names[0]);

            final int years = pgi.getYears();
            final int months = pgi.getMonths();
            final int days = pgi.getDays();
            final int hours = pgi.getHours();
            final int mins = pgi.getMinutes();
            final double secs = pgi.getSeconds();

            return new Period(years, months, 0, days, hours, mins, (int)secs, 0).toStandardDuration();

        }
        catch (Exception e) {
            return null;
        }
    }


    public void nullSafeSet(PreparedStatement statement, Object value, int index)
        throws HibernateException, SQLException {

        if (value == null) {
            statement.setNull(index, Types.OTHER);
        }
        else {
            final ReadablePeriod period = ((ReadableDuration)value).toPeriod();

            final int years = period.get(DurationFieldType.years());
            final int months = period.get(DurationFieldType.months());
            final int days = period.get(DurationFieldType.days());
            final int hours = period.get(DurationFieldType.hours());
            final int mins = period.get(DurationFieldType.minutes());
            final int secs = period.get(DurationFieldType.seconds());

            final PGInterval pgi = new PGInterval(years, months, days, hours, mins, secs);
            statement.setObject(index, pgi);
        }
    }


    public boolean equals(Object x, Object y)
        throws HibernateException {

        return x == y;
    }


    public int hashCode(Object x)
        throws HibernateException {
        return x.hashCode();
    }


    public Object deepCopy(Object value)
        throws HibernateException {
        return value;
    }


    public boolean isMutable() {
        return false;
    }


    public Serializable disassemble(Object value)
        throws HibernateException {
        throw new HibernateException("not implemented");
    }


    public Object assemble(Serializable cached, Object owner)
        throws HibernateException {
        throw new HibernateException("not implemented");
    }


    public Object replace(Object original, Object target, Object owner)
        throws HibernateException {
        throw new HibernateException("not implemented");
    }
}
person j.snyder    schedule 22.01.2012
comment
Если вы можете, вы можете опубликовать свой вспомогательный класс (ы) где-нибудь, например, в своем ответе здесь :) JodaTime может быть хорошим фондом общего класса для расширения поддержки JDBC Spring - person Danubian Sailor; 24.01.2012
comment
Пожалуйста, дайте мне образец класса DAO для использования класса JodaTimeDurationType - person ankit; 17.07.2018