java criteria exist_如何从Hibernate Criteria API获取SQL(*不是*用于日志记录)

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值