如何将表名作为 Hibernate Template 查询的参数之一

7

显然,Hibernate模板查询将字符串参数“tableName”注入带引号的查询中。这将导致SQL语法语句错误。

如何将表名作为查询参数之一?

例如,以下代码由于表名而无法正常工作:

SQLQuery query = session.createSQLQuery("SELECT ID FROM :tableName");
query.setFlushMode(FlushMode.MANUAL);
query.setReadOnly(true);
query.setParameter("tableName", "STUDENT");
List<Object[]> list = query.list();
3个回答

5
表名不能在查询中作为参数化变量。
实际上,你想要实现的是构建一个字符串,用于构造查询语句:
SQLQuery query = session.createSQLQuery(getIdsQuery("STUDENT"));
...
private String getIdsQuery(String tableName) {
   return "SELECT ID FROM " + tableName;
}

缺乏对表名进行参数化的能力与Hibernate无关 - 数据库不支持它。而且支持它也没有意义。
绑定变量主要是为了提高性能。关键是您通过占位符将查询发送到数据库(通过jdbc驱动程序),这些占位符将在调用“相同”的查询时更改变量:
select id from STUDENT where name = ?

数据库将解析此查询,计算其成本,制定执行计划并对其进行缓存。后续调用查询将更快,因为跳过了所有这些步骤并使用缓存的执行计划
如果表名未知(参数化),数据库如何缓存语句和执行计划?如果不知道从哪里获取数据,则无法知道成本和最佳获取路径。
此外,如果不知道所引用的列是否实际存在于表中(如果表名是参数化的,则在语句解析时将不知道),则数据库将无法完全验证查询。

这就是我正在做的事情,但我仍然不明白为什么Hibernate不支持参数化表名。 :) - Q i
这个答案可能会导致 SQL 注入,这是一个非常容易被操纵的安全漏洞。这也是为什么参数不能用于表名的原因。 - Phil

0

你的HQL查询应该长这样:

Query query = session.createQuery("from Conversation as c where c.userConversation.id=:senderid and c.user1Conversation.id=:receiverid");

这里的Conversation是模型类名,'c'是别名,userConversation是我拥有的多对一映射。回答你的问题,你可以按照上述方式放置表名。请不要忘记设置查询参数。

另外,你不需要将FlushMode设置为手动,因为你只是在读取列表,甚至不需要在此之后调用session.flush。其次,为什么要为query.setParameter设置硬编码值?

更新

我刚刚看了你的帖子。你的SQL查询应该像这样:

select id,username from Conversation where id=1000;

上面只是一个例子,但“Conversation”仍然是表名。此外,您已将帖子标记为Hibernate,这就是我编写HQL查询的原因,因为我发现在HQL中做事情要容易得多。

0
Query query = session.createQuery(String.format("select id from %s", "Student"));

这与第一个答案相同(但使用了一些Java的帮助):您需要构造一个字符串作为查询参数


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接