ColumnTransformer в спящем режиме

У меня есть Entity, для которого я использую ColumnTransformer для привязки и извлечения значений:

@Entity
class BPoint {
    @Id
    private Integer id;

    @ColumnTransformer(read = "astext(shape)", write = "toshape(?)")
    private Shape shape;

}

И dao:

class BPointDao {
    @Autowired
    private EntityManager em;

    @Override
    public Page<BPoint> findAll(Pageable pageable) {
        Query q = em.createQuery("from BPoint");
        List<BPoint> r = q.getResultList();
        int total = em.createQuery("select count(*)  from BPoint").getFirstResult();
        return new PageImpl(r, pageable, total);
    }
    @Override
    public Integer save(BPoint hbds) {
        em.persist(hbds);
        return hbds.getId();
    }
}

Это работает, однако, как только я должен выполнить какой-то запрос, который требует использования функций sql, я встречаю некоторые проблемы, возьмите этот действительный собственный sql, например:

select * from BPoint h where inside(h.shape, 100) = 1;

Сначала я попытался использовать hql следующим образом:

Query q = em.createNativeQuery("select astext(shape) from BPoint h where inside(h.shape, ?) = 1");

Однако я обнаружил, что сгенерированный sql содержит такие вещи, как

...... where inside(astext(h.shape),100).....

Кажется, что значение ColumnTransformer read используется в sql-функции inside, которая не ожидается.

Итак, я попытался использовать собственный SQL-запрос:

Query q = em.createNativeQuery("select * from BPoint h where inside(h.shape, ? = 1");

Не может быть выполнен sql, но результат не может быть правильно отображен.

Затем мне нужно добавить select fileds manualy следующим образом:

Query q = em.createNativeQuery("select id,astext(shape) from BPoint h where inside(h.shape, ? = 1");

Но как насчет того, есть ли у моей сущности много фидов, это больше 20? И как изменилось имя столбца?

Есть ли альтернативный метод для удовлетворения моих требований?

Ответ 1

Сначала попробуйте указать возвращаемый тип в свой собственный запрос:

Query q = em.createNativeQuery("select * from BPoint h where inside(h.shape, ? = 1", BPoint.clss);
List<BPoint> result = q.getResultList();

Или вы можете попробовать сделать это следующим образом:

Session session = em.unwrap(Session.class);
List<BPoint> points = (List<BPoint>) session.createSQLQuery("SELECT {h.*} FROM BPoint {h} WHERE inside({h}.shape, ? = 1")
    .addEntity("h", BPoint.class)
.list();

Специфичный API Hibernate позволяет сопоставлять результаты собственных запросов с Entities.

Ответ 2

Вы можете создать настраиваемый перехватчик и "исправить" SQL, чтобы заменить все "внутрь (astext (#REF)) как внутри (#REF)

Вам придется переопределить org.hibernate.Interceptor # onPrepareStatement (String sql). Аргумент ввода содержит sql, который вы можете изменить, как описано.