33
我做了这样的事使用Spring AOP所以我可以获取任何查询的sql,参数,错误和执行时间在应用程序中运行,无论是HQL,Criteria还是原生SQL。
这显然是脆弱的,不安全的,主题,在Hibernate等变化打破,但它说明,它可能得到的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);
包装在一个try/catch和使用整个事情风险自负。
2009-02-17 00:52:10
+0
将hibernate日志暂时重定向到字符串会不会更具可移植性? –
2011-08-15 13:28:12
+0
可能,但是如果多个线程同时执行SQL,可能很难确定哪条日志消息与您尝试捕获的SQL一起运行。使用onPrepareStatement的拦截器也会让你获得SQL,但是OP要求一种获得给定Criteria对象的SQL的方法。 –
2011-08-15 21:26:01
+1
有没有办法可以打印出SQL查询的参数? –
2013-05-11 12:51:06
35
这里的 “其他” 的方式来获得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();
2010-10-08 08:28:37
10
对于使用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();
}
2010-11-12 15:15:40
LiamV
7
如果您在使用Hibernate 3.6您可以使用公认的答案稍作修改的代码(由Brian 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);
2012-06-11 14:26:20
Michael
4
我,如果你W¯¯喜欢这个蚂蚁得到公正查询的某些部分:
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;
2012-11-09 11:58:54
Triqui
3
这里是我以前和我
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 ");
}
2016-03-02 20:53:46
fformigli
0
工作方法这个答案基于user3715338的回答(修正了一个小的拼写错误),并与Michael对Hibernate 3.6的回答混合在一起 - 基于Brian 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("", " > ");
}
2016-06-27 13:12:54
0
对于希望这样做在单个线(任何人都在显示/立即窗口,手表表达或以类似的例如调试会话),以下将这样做和“漂亮打印”的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()
);
注:
它假定Criteria对象被命名为crit。 如果命名不同,请执行搜索并替换。
它假定Hibernate版本低于3.3.2.GA,但早于4.0,以便使用BasicFormatterImpl“漂亮地打印”HQL。 如果使用其他版本,请参见this answer以了解如何修改。或者,也许只是完全删除漂亮的打印,因为它只是一个“很高兴有”。
它不输出用于如果该查询是参数化的实际参数值。
2017-10-17 11:04:46