Собственные запросы Oracle, объявленные в репозиториях Spring: Hibernate возвращает коллекции BigDecimal вместо Long - PullRequest
0 голосов
/ 21 сентября 2018

Я использую Spring Boot 2.0.4, который поставляется с Hibernate 5.2.17, для работы с обширной базой данных Oracle 10, структура которой не находится под моим контролем.

У меня возникают досадные проблемы, когда я пытаюсь использовать собственный запрос, объявленный в Spring @Repository, для получения коллекции идентификаторов.Вот упрощенный составленный пример:

@Entity
@Table(name = "T_THING")
public class Thing {

    @Id
    @Column(name = "ID")    //Oracle type of column is NUMBER(12,0)
    private Long id;

    @Column(name = "NAME")
    private String name;

    //getters and setters
}

и

@Repository
public interface ThingRepository extends CrudRepository<Thing, Long> {

    @Query(value = "Select ID from T_THING where NAME = 'some'", nativeQuery = true)
    Long findSomething_1();                         //returns java.lang.Long

    @Query("Select t.id from Thing t where t.name ='some'")
    Set<Long> findSomething_2();                    //returns a Set with java.lang.Long

    @Query(value = "Select ID from T_THING where NAME = 'some'", nativeQuery = true)
    Set<Long> findSomething_3();                    //returns a Set with java.math.BigDecimal
}

Использование JPQL прекрасно работает, независимо от того, прошу ли я указать один идентификатор или коллекцию.Первый метод, использующий собственный запрос для одного идентификатора, также работает.

Третий метод использует тот же собственный запрос, что и первый, но он возвращает потенциально более одного идентификатора в наборе.Это также работает в том смысле, что вызывается БД и возвращаются правильные идентификаторы.Тем не менее, если я когда-либо попытаюсь использовать результирующий Set, то веселье наступит потому, что даже если я объявил его как Set, во время выполнения на самом деле это Set.

Я предполагаю, что в результате Hibernate автоматически переводит тип Oracleстолбца ID, число (12,0), в BigDecimal и вставляет значение во время выполнения, когда мой Set является просто простым Set.Я также могу придумать, как обойти эту проблему, внедрив сам репозиторий, вручную изменив тип и т. Д.

У меня такой вопрос: как мне настроить Spring или Hibernate, чтобы findSomething_3()выше будет работать в его нынешнем состоянии?

Поиск вокруг StackOverflow Я обнаружил некоторые намеки на то, что этот тип отображений определен в диалекте Hibernate, и я нашел это в том, который я использую (Oracle10gDialect):

protected void registerNumericTypeMappings() {
    registerColumnType( Types.BIT, "number(1,0)" );
    registerColumnType( Types.BIGINT, "number(19,0)" );
    registerColumnType( Types.SMALLINT, "number(5,0)" );
    registerColumnType( Types.TINYINT, "number(3,0)" );
    registerColumnType( Types.INTEGER, "number(10,0)" );

    registerColumnType( Types.FLOAT, "float" );
    registerColumnType( Types.DOUBLE, "double precision" );
    registerColumnType( Types.NUMERIC, "number($p,$s)" );
    registerColumnType( Types.DECIMAL, "number($p,$s)" );

    registerColumnType( Types.BOOLEAN, "number(1,0)" );
}

Однако, когда я попытался обойти свой собственный диалект, например,

public class MyDialect extends Oracle10gDialect {

    public MyDialect() {
        super();
        // I have no idea what this actually means
        registerColumnType(Types.BIGINT, "number(12,0)");
    }
}

, ничего не изменилось.

...