Java step by step (4): Hibernate and Bind Variables

关于在SQL语句中是用Bind Variables的重要性就不用多说了,最近在看代码的时候发现有一条比较耗时的SQL语句居然是在Java代码中动态拼接而成的。这条SQL语句之前也进行过一些简单的重写优化工作,在with语句中特别用到hint 了/*+materialize*/。之前认为这个hint在WITH语句中没有必要使用,Oracle应该会自动创建一个临时表用于with语句结果的存储,结果居然发现加不加这个hint差别还是蛮大的,最后就加上了这个hint. 

OK,回到正题上来。这个SQL需要接收的参数是一个动态的逗号分隔的字符串,放在in list中用的。很显然,如果用PL/SQL来写这个语句的话,是不能用如下的方式的....



---------------------------------------------------------------------------------

function test(p_list_of_names in varchar2)return ....

as

  select * 

  from ...

  where name in (p_list_of_names)

  ...

end;

--------------------------------------------------------------------------------
 


一般这种情况下用Pl/SQL方式的话,最简单的就是用动态SQL执行,但是很显然这个就会失去bind variables的优势,会造成SQL Hard Parse次数的增加。为了避免动态SQL, 一般我们会借助nested table来做,但是这样会造成执行计划的不准确。这个可以参见(http://www.cnblogs.com/fangwenyu/archive/2011/04/18/2020191.html).



不过貌似这个问题在Hibernate中很容易得到解决,SQL语句还是可以写成上面那样,只是在绑定参数的时候,传入一个数组就OK了。如下所示...

import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;

public class demo {

private String sql;

private NamedParameterJdbcTemplate jdbcTemplate;

public void setSql(final String sql) {
this.sql = sql;
}

public String getSql() {
return this.sql;
}

public List<XXX> retrieveResult(final String userId) {
Set
<String> userIds = combineUserIds(userId);

Map
<String, Object> params = new HashMap<String, Object>();
params.put(
"userIds", userIds);

List
<XXX> result = jdbcTemplate.query(this.getSql(), params,
new RowMapper<XXX>() {
public XXX mapRow(ResultSet rs, int line) throws SQLException {

....

 

这里面的SQL语句放在了XML文件中,用Spring IoC自动初始化...

<bean id="demo"class="demo">

<property name="sql" value="
select * from xxx where user_id in (:userIds)"/>
</bean>

  
 

在运行的时候,Hibernate会把:userIds替换成一些列的"?" placeholder (根据传进来数组的元素个数),这样也就可以使用绑定变量了。 

原文地址:https://www.cnblogs.com/fangwenyu/p/2128563.html