2015-02-26 8 views
11

У меня есть объект, который я использую ColumnTransformer для связывания и извлечения значений:ColumnTransformer в спящем режиме

@Entity 
class BPoint { 
    @Id 
    private Integer id; 

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

} 

И дао:

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 Мануалы, как это:

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

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

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

+0

Почему бы вам не попробовать выполнить собственный SQL-код и результат преобразования с помощью 'ResultTransformer' – Amogh

+0

Я использую собственный sql на данный момент, однако я должен вычислить имена в sql вручную, так как таблица содержит почти 100 + столбцов. – hguser

+0

вы сказали, что собственный sql может быть выполнен, но результат не может быть правильно отображен. Что, если y ou написать 'ResultTransformer', чтобы отобразить его – Amogh

ответ

4

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

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 позволяет отображать собственные результаты запроса к сущностям.

+0

Возможно, я не сделал себе ясным, я не могу использовать' select * ..' в собственном запросе, если это так, hibernate не может сопоставить результирующий набор с сущностью, потому что значение ColumnTransformer не используются. – hguser

1

Вы можете создать собственный перехватчик и "исправить" SQL, чтобы заменить все «внутри (AsText (# ССЫЛКА)), как внутри (#REF)

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

+0

Звучит как решение, однако кажется, что я сделаю замену исходной строки для sql в 'onPrepareStatement', которая может быть ненадежной. – hguser

+0

Да, это действительная забота. Единственный способ, с помощью которого я могу сделать это надежно и исполненным образом, - расширить диалект и создать стандартную функцию SQLSQL и переопределить метод рендеринга. В этом методе вы получите строковое представление, и здесь вы можете сделать такую ​​же модификацию. Пожалуйста, проверьте, действительно ли это можно сделать для функции «внутри». – codedabbler

Смежные вопросы