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, который вы можете изменить, как описано.