Я использую 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)");
}
}
, ничего не изменилось.