Gibt es eine Möglichkeit, die (zu generierende) SQL aus einem Ruhezustand abzurufen Criteria
?
Im Idealfall hätte ich so etwas wie:
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)
Die Idee wäre dann, das SQL als Teil einer riesigen 'MINUS'-Abfrage zu verwenden (ich muss die Unterschiede zwischen zwei identischen Schemas finden - identisch in der Struktur, nicht in den Daten - und das MINUS wird von Hibernate nicht unterstützt).
(Übrigens weiß ich, dass ich die SQL aus den Protokolldateien überprüfen kann)
Hier ist "ein anderer" Weg, um SQL zu erhalten:
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();
quelle
Für Benutzer von NHibernate ist dies ein Port des Codes von [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(); }
quelle
Wenn Sie Hibernate 3.6 verwenden, können Sie den Code in der akzeptierten Antwort (bereitgestellt von Brian Deterling) mit geringfügigen Änderungen verwenden:
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);
quelle
Ich mag dies, wenn Sie nur einige Teile der Abfrage erhalten möchten:
new CriteriaQueryTranslator( factory, executableCriteria, executableCriteria.getEntityOrClassName(), CriteriaQueryTranslator.ROOT_SQL_ALIAS) .getWhereCondition();
Zum Beispiel so etwas:
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;
quelle
Hier ist eine Methode, die ich verwendet und für mich gearbeitet habe
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 "); }
quelle
Für alle, die dies in einer einzelnen Zeile tun möchten (z. B. im Anzeige- / Sofortfenster, einem Überwachungsausdruck oder ähnlichem in einer Debug-Sitzung), wird Folgendes ausgeführt und die SQL "hübsch gedruckt":
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());
... oder hier ist eine leichter zu lesende Version:
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() );
Anmerkungen:
crit
. Wenn anders benannt, suchen und ersetzen .getEnabledFilters
eher verwendet alsgetLoadQueryInfluencers()
aus Gründen der Abwärtskompatibilität, da letzteres in einer späteren Version von Hibernate (3.5 ???) eingeführt wurde.quelle
Diese Antwort basiert auf der Antwort von user3715338 (mit einem kleinen korrigierten Rechtschreibfehler) und wird mit Michaels Antwort für Hibernate 3.6 gemischt - basierend auf der akzeptierten Antwort von Brian Deterling. Ich habe es dann (für PostgreSQL) um ein paar weitere Typen erweitert, die die Fragezeichen ersetzen:
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(">", " > "); }
quelle