Как получить спящий сгенерированный sql без псевдонимов - PullRequest
1 голос
/ 15 января 2020

Я работаю над функцией, которая с заданными критериями возвращает sql, но я получаю sql с псевдонимами критериев. Итак, есть ли способ сохранить исходные имена столбцов из базы данных вместо замены псевдонимом?

Функция:

    public String getReportSQL(Criteria criteria) {
        try {
            CriteriaImpl c = (CriteriaImpl) criteria;
            SessionImpl s = (SessionImpl)c.getSession();
            SessionFactoryImplementor factory = (SessionFactoryImplementor)s.getSessionFactory();
            String[] implementors = factory.getImplementors( c.getEntityOrClassName() );
            CriteriaLoader loader = new CriteriaLoader((OuterJoinLoadable)factory.getEntityPersister(implementors[0]),
                    factory, c, implementors[0], s.getLoadQueryInfluencers());

            Field f = OuterJoinLoader.class.getDeclaredField("sql");
            f.setAccessible(true);
            return (String) f.get(loader);
       } catch(Exception e){
           throw new RuntimeException(e);
       }
    }

Получено:

    select this_.CAR_KEY as CAR_11_0_ from DATABASE.CAR this_

Ожидается:

    select CAR_KEY from DATABASE.CAR

Заранее спасибо

Ответы [ 2 ]

1 голос
/ 15 января 2020

В общем случае вы не можете удалить псевдоним, сгенерированный hibernate.

Представьте, что у нас есть следующая сущность:

@Entity
@Table(name = "TEST_MESSAGE")
public class Message
{
   @Id
   @Column(name = "MSG_ID")
   private Long id;

   @Column(name = "MSG_TEXT")
   private String text;

   @ManyToOne
   @JoinColumn(name="MSG_PARENT_ID")
   private Message parent;

   ...
}

и следующий критерий запроса:

   CriteriaBuilder builder = session.getCriteriaBuilder();
   CriteriaQuery<Tuple> criteria = builder.createQuery(Tuple.class);
   Root<Message> root = criteria.from(Message.class);

   Path<Long> id = root.get("id");
   Path<Message> parent = root.get("parent");

   criteria.multiselect(id, parent);
   criteria.where( builder.equal( root.get("id"), 2) );
   List<Tuple> tuples = session.createQuery( criteria ).getResultList();

   ...

Hibernate сгенерирует для него следующее sql:

select
   message0_.MSG_ID as col_0_0_,
   message0_.MSG_PARENT_ID as col_1_0_,
   message1_.MSG_ID as MSG_ID1_0_,
   message1_.MSG_PARENT_ID as MSG_PARENT_ID3_0_,
   message1_.MSG_TEXT as MSG_TEXT2_0_ 
from TEST_MESSAGE message0_ 
inner join TEST_MESSAGE message1_ on message0_.MSG_PARENT_ID = message1_.MSG_ID 
where message0_.MSG_ID = 2

Как видите, если мы просто удалим все псевдонимы (message0_, message1_, ...) запроса будет недействительным. Эта статья проливает дополнительный свет на этот вопрос.

1 голос
/ 15 января 2020

Реализация Java по умолчанию для объявленного поля "sql" - это та, которую вы получаете, и я не думаю, что есть простой способ изменить ее так, как вы хотите.

Я предлагаю разобрать полученную строку.

return ((String) f.get(loader)).replaceAll("this_.", "").replaceAll("this_", "").replaceAll("( as \\w)\\w+", "")

Результат будет:

выбрать CAR_KEY из DATABASE.CAR

...