복붙노트

[SQL] 최대 절전 모드 기준 API에서 SQL을 얻는 방법 (*하지 * 로깅)

SQL

최대 절전 모드 기준 API에서 SQL을 얻는 방법 (*하지 * 로깅)

하이버 네이트의 기준에서 (-생성에-) SQL을 얻을 수있는 쉬운 방법은 무엇입니까?

이상적으로 내가 좋아하는 뭔가를 할 것이다 :

Criteria criteria = session.createCriteria(Operator.class);

... build up the criteria ...
... and then do something like ...

String sql = criteria.toSql()

(But this of course does not exist)

아이디어는 거대한 'MINUS'쿼리의 일환으로 SQL을 사용하는 것 (그리고 MINUS는 최대 절전 모드를 지원하지 않습니다 나는이 동일한 스키마 사이의 차이를 찾을 필요 - - 구조가 동일하지 데이터를)

(BTW 나는 로그 파일에서 SQL을 확인할 수 있습니다 알고)

해결법

  1. ==============================

    1.나는 그것이 HQL, 기준, 또는 네이티브 SQL인지 응용 프로그램의 모든 쿼리 실행을위한 SQL, 매개 변수, 오류, 실행 시간을 잡을 수 있도록 나는 스프링 AOP를 사용하여이 같은 짓을했습니다.

    나는 그것이 HQL, 기준, 또는 네이티브 SQL인지 응용 프로그램의 모든 쿼리 실행을위한 SQL, 매개 변수, 오류, 실행 시간을 잡을 수 있도록 나는 스프링 AOP를 사용하여이 같은 짓을했습니다.

    이 깨지기 쉬운, 불안 등 최대 절전 모드의 변화와 휴식에 따라 분명하지만, 그것은 SQL을 얻을 수 있다는 설명 :

    CriteriaImpl c = (CriteriaImpl)query;
    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.getEnabledFilters());
    Field f = OuterJoinLoader.class.getDeclaredField("sql");
    f.setAccessible(true);
    String sql = (String)f.get(loader);
    

    자신의 위험에 시도 / 캐치 및 사용 전체 일을 바꿈.

  2. ==============================

    2.여기에 SQL을 얻을 수있는 "또 다른"방법이있다 :

    여기에 SQL을 얻을 수있는 "또 다른"방법이있다 :

    CriteriaImpl criteriaImpl = (CriteriaImpl)criteria;
    SessionImplementor session = criteriaImpl.getSession();
    SessionFactoryImplementor factory = session.getFactory();
    CriteriaQueryTranslator translator=new CriteriaQueryTranslator(factory,criteriaImpl,criteriaImpl.getEntityOrClassName(),CriteriaQueryTranslator.ROOT_SQL_ALIAS);
    String[] implementors = factory.getImplementors( criteriaImpl.getEntityOrClassName() );
    
    CriteriaJoinWalker walker = new CriteriaJoinWalker((OuterJoinLoadable)factory.getEntityPersister(implementors[0]), 
                            translator,
                            factory, 
                            criteriaImpl, 
                            criteriaImpl.getEntityOrClassName(), 
                            session.getLoadQueryInfluencers()   );
    
    String sql=walker.getSQLString();
    
  3. ==============================

    3.NHibernate에를 사용하는 경우, 이는 [RAM]의 코드 포트는

    NHibernate에를 사용하는 경우, 이는 [RAM]의 코드 포트는

    public static string GenerateSQL(ICriteria criteria)
        {
            NHibernate.Impl.CriteriaImpl criteriaImpl = (NHibernate.Impl.CriteriaImpl)criteria;
            NHibernate.Engine.ISessionImplementor session = criteriaImpl.Session;
            NHibernate.Engine.ISessionFactoryImplementor factory = session.Factory;
    
            NHibernate.Loader.Criteria.CriteriaQueryTranslator translator = 
                new NHibernate.Loader.Criteria.CriteriaQueryTranslator(
                    factory, 
                    criteriaImpl, 
                    criteriaImpl.EntityOrClassName, 
                    NHibernate.Loader.Criteria.CriteriaQueryTranslator.RootSqlAlias);
    
            String[] implementors = factory.GetImplementors(criteriaImpl.EntityOrClassName);
    
            NHibernate.Loader.Criteria.CriteriaJoinWalker walker = new NHibernate.Loader.Criteria.CriteriaJoinWalker(
                (NHibernate.Persister.Entity.IOuterJoinLoadable)factory.GetEntityPersister(implementors[0]),
                                    translator,
                                    factory,
                                    criteriaImpl,
                                    criteriaImpl.EntityOrClassName,
                                    session.EnabledFilters);
    
            return walker.SqlString.ToString();
        }
    
  4. ==============================

    4.당신은 최대 절전 모드 3.6를 사용하는 경우는 약간의 수정과 (브라이언 Deterling에서 제공) 허용 대답에 코드를 사용할 수 있습니다 :

    당신은 최대 절전 모드 3.6를 사용하는 경우는 약간의 수정과 (브라이언 Deterling에서 제공) 허용 대답에 코드를 사용할 수 있습니다 :

      CriteriaImpl c = (CriteriaImpl) criteria;
      SessionImpl s = (SessionImpl) c.getSession();
      SessionFactoryImplementor factory = (SessionFactoryImplementor) s.getSessionFactory();
      String[] implementors = factory.getImplementors(c.getEntityOrClassName());
      LoadQueryInfluencers lqis = new LoadQueryInfluencers();
      CriteriaLoader loader = new CriteriaLoader((OuterJoinLoadable) factory.getEntityPersister(implementors[0]), factory, c, implementors[0], lqis);
      Field f = OuterJoinLoader.class.getDeclaredField("sql");
      f.setAccessible(true);
      String sql = (String) f.get(loader);
    
  5. ==============================

    5.쿼리의 단지 일부를 얻으려면 나는이 좋아 :

    쿼리의 단지 일부를 얻으려면 나는이 좋아 :

    new CriteriaQueryTranslator(
        factory,
        executableCriteria,
        executableCriteria.getEntityOrClassName(), 
        CriteriaQueryTranslator.ROOT_SQL_ALIAS)
            .getWhereCondition();
    

    이 같은 인스턴스 일 경우 :

    String where = new CriteriaQueryTranslator(
        factory,
        executableCriteria,
        executableCriteria.getEntityOrClassName(), 
        CriteriaQueryTranslator.ROOT_SQL_ALIAS)
            .getWhereCondition();
    
    String sql = "update my_table this_ set this_.status = 0 where " + where;
    
  6. ==============================

    6.여기에 방법 내가 사용하고 나를 위해 일한다

    여기에 방법 내가 사용하고 나를 위해 일한다

    public static String toSql(Session session, Criteria criteria){
        String sql="";
        Object[] parameters = null;
        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.getEnabledFilters());
            Field f = OuterJoinLoader.class.getDeclaredField("sql");
            f.setAccessible(true);
            sql = (String)f.get(loader);
            Field fp = CriteriaLoader.class.getDeclaredField("traslator");
            fp.setAccessible(true);
            CriteriaQueryTranslator translator = (CriteriaQueryTranslator) fp.get(loader);
            parameters = translator.getQueryParameters().getPositionalParameterValues();
        }
        catch(Exception e){
            throw new RuntimeException(e);
        }
        if (sql !=null){
            int fromPosition = sql.indexOf(" from ");
            sql = "SELECT * "+ sql.substring(fromPosition);
    
            if (parameters!=null && parameters.length>0){
                for (Object val : parameters) {
                    String value="%";
                    if(val instanceof Boolean){
                        value = ((Boolean)val)?"1":"0";
                    }else if (val instanceof String){
                        value = "'"+val+"'";
                    }
                    sql = sql.replaceFirst("\\?", value);
                }
            }
        }
        return sql.replaceAll("left outer join", "\nleft outer join").replace(" and ", "\nand ").replace(" on ", "\non ");
    }
    
  7. ==============================

    7.한 줄에서이 작업을 수행하고자하는 사람의 경우 (예를 들어, 디스플레이 / 즉시 창, 디버그 세션에서 시계 발현 또는 유사한에서), 다음이 너무하고 "꽤 인쇄"는 SQL 할 것입니다 :

    한 줄에서이 작업을 수행하고자하는 사람의 경우 (예를 들어, 디스플레이 / 즉시 창, 디버그 세션에서 시계 발현 또는 유사한에서), 다음이 너무하고 "꽤 인쇄"는 SQL 할 것입니다 :

    new org.hibernate.jdbc.util.BasicFormatterImpl().format((new org.hibernate.loader.criteria.CriteriaJoinWalker((org.hibernate.persister.entity.OuterJoinLoadable)((org.hibernate.impl.CriteriaImpl)crit).getSession().getFactory().getEntityPersister(((org.hibernate.impl.CriteriaImpl)crit).getSession().getFactory().getImplementors(((org.hibernate.impl.CriteriaImpl)crit).getEntityOrClassName())[0]),new org.hibernate.loader.criteria.CriteriaQueryTranslator(((org.hibernate.impl.CriteriaImpl)crit).getSession().getFactory(),((org.hibernate.impl.CriteriaImpl)crit),((org.hibernate.impl.CriteriaImpl)crit).getEntityOrClassName(),org.hibernate.loader.criteria.CriteriaQueryTranslator.ROOT_SQL_ALIAS),((org.hibernate.impl.CriteriaImpl)crit).getSession().getFactory(),(org.hibernate.impl.CriteriaImpl)crit,((org.hibernate.impl.CriteriaImpl)crit).getEntityOrClassName(),((org.hibernate.impl.CriteriaImpl)crit).getSession().getEnabledFilters())).getSQLString());
    

    ... 또는 여기에 더 쉽게 버전을 읽을 수있다 :

    new org.hibernate.jdbc.util.BasicFormatterImpl().format(
      (new org.hibernate.loader.criteria.CriteriaJoinWalker(
         (org.hibernate.persister.entity.OuterJoinLoadable)
          ((org.hibernate.impl.CriteriaImpl)crit).getSession().getFactory().getEntityPersister(
            ((org.hibernate.impl.CriteriaImpl)crit).getSession().getFactory().getImplementors(
              ((org.hibernate.impl.CriteriaImpl)crit).getEntityOrClassName())[0]),
         new org.hibernate.loader.criteria.CriteriaQueryTranslator(
              ((org.hibernate.impl.CriteriaImpl)crit).getSession().getFactory(),
              ((org.hibernate.impl.CriteriaImpl)crit),
              ((org.hibernate.impl.CriteriaImpl)crit).getEntityOrClassName(),
              org.hibernate.loader.criteria.CriteriaQueryTranslator.ROOT_SQL_ALIAS),
         ((org.hibernate.impl.CriteriaImpl)crit).getSession().getFactory(),
         (org.hibernate.impl.CriteriaImpl)crit,
         ((org.hibernate.impl.CriteriaImpl)crit).getEntityOrClassName(),
         ((org.hibernate.impl.CriteriaImpl)crit).getSession().getEnabledFilters()
       )
      ).getSQLString()
    );
    

    노트:

  8. ==============================

    8.이 답변은 user3715338의 답변에 따라 (작은 맞춤법 오류 수정과) 및 최대 절전 모드 3.6 마이클의 대답과 혼합 - 브라이언 Deterling에서 허용 답변에 따라. 나는 다음 몇 가지 더 많은 종류가 questionmarks을 교체하는 (PostgreSQL을위한)를 확장 :

    이 답변은 user3715338의 답변에 따라 (작은 맞춤법 오류 수정과) 및 최대 절전 모드 3.6 마이클의 대답과 혼합 - 브라이언 Deterling에서 허용 답변에 따라. 나는 다음 몇 가지 더 많은 종류가 questionmarks을 교체하는 (PostgreSQL을위한)를 확장 :

    public static String toSql(Criteria criteria)
    {
        String sql = "";
        Object[] parameters = null;
        try
        {
            CriteriaImpl criteriaImpl = (CriteriaImpl) criteria;
            SessionImpl sessionImpl = (SessionImpl) criteriaImpl.getSession();
            SessionFactoryImplementor factory = sessionImpl.getSessionFactory();
            String[] implementors = factory.getImplementors(criteriaImpl.getEntityOrClassName());
            OuterJoinLoadable persister = (OuterJoinLoadable) factory.getEntityPersister(implementors[0]);
            LoadQueryInfluencers loadQueryInfluencers = new LoadQueryInfluencers();
            CriteriaLoader loader = new CriteriaLoader(persister, factory,
                criteriaImpl, implementors[0].toString(), loadQueryInfluencers);
            Field f = OuterJoinLoader.class.getDeclaredField("sql");
            f.setAccessible(true);
            sql = (String) f.get(loader);
            Field fp = CriteriaLoader.class.getDeclaredField("translator");
            fp.setAccessible(true);
            CriteriaQueryTranslator translator = (CriteriaQueryTranslator) fp.get(loader);
            parameters = translator.getQueryParameters().getPositionalParameterValues();
        }
        catch (Exception e)
        {
            throw new RuntimeException(e);
        }
        if (sql != null)
        {
            int fromPosition = sql.indexOf(" from ");
            sql = "\nSELECT * " + sql.substring(fromPosition);
    
            if (parameters != null && parameters.length > 0)
            {
                for (Object val : parameters)
                {
                    String value = "%";
                    if (val instanceof Boolean)
                    {
                        value = ((Boolean) val) ? "1" : "0";
                    }
                    else if (val instanceof String)
                    {
                        value = "'" + val + "'";
                    }
                    else if (val instanceof Number)
                    {
                        value = val.toString();
                    }
                    else if (val instanceof Class)
                    {
                        value = "'" + ((Class) val).getCanonicalName() + "'";
                    }
                    else if (val instanceof Date)
                    {
                        SimpleDateFormat sdf = new SimpleDateFormat(
                            "yyyy-MM-dd HH:mm:ss.SSS");
                        value = "'" + sdf.format((Date) val) + "'";
                    }
                    else if (val instanceof Enum)
                    {
                        value = "" + ((Enum) val).ordinal();
                    }
                    else
                    {
                        value = val.toString();
                    }
                    sql = sql.replaceFirst("\\?", value);
                }
            }
        }
        return sql.replaceAll("left outer join", "\nleft outer join").replaceAll(
            " and ", "\nand ").replaceAll(" on ", "\non ").replaceAll("<>",
            "!=").replaceAll("<", " < ").replaceAll(">", " > ");
    }
    
  9. from https://stackoverflow.com/questions/554481/how-to-get-sql-from-hibernate-criteria-api-not-for-logging by cc-by-sa and MIT license