You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ibatis.apache.org by "Sebastian Fiorentini (JIRA)" <ib...@incubator.apache.org> on 2009/02/20 20:15:01 UTC

[jira] Issue Comment Edited: (IBATIS-480) support the parameter('#') in the replace string('$') and the result column of result map(class) not existed in select statement.

    [ https://issues.apache.org/jira/browse/IBATIS-480?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12675420#action_12675420 ] 

sebastian.fiorentini edited comment on IBATIS-480 at 2/20/09 11:14 AM:
-----------------------------------------------------------------------

I've achieved 2), ie. allowing select's to return less columns than the mapping expects by modifying only one class. This is a recurring usecase in our projects since we can model the entire domain model and code the selects and only involving the intended columns on some queries.

The solution is in ResultMap class (ibatis 2.3.4.726) and BaseResultMap (ibatis 2.3.0) into the getResults() method.

previous to this line:

    for (int i = 0; i < getResultMappings().length; i++) {

add:

    ResultSetMetaData rsmd=rs.getMetaData();
    HashSet<String> columnasRS=new HashSet<String>();
    for (int i=1;i<=rsmd.getColumnCount();i++){
    	columnasRS.add(rsmd.getColumnName(i));
    }

and

below to the

    for (int i = 0; i < getResultMappings().length; i++) {
      ResultMapping mapping = (ResultMapping) getResultMappings()[i];

add:

      //Ver si la columna existe en la metadata
      if (!columnasRS.contains(mapping.getColumnName())){
    	  System.out.println("No existe la columna "+mapping.getColumnName()+". Salteando!");
      }
      else{
      ...
      existing code
      }


      was (Author: sebastian.fiorentini):
    I've achieved 2), ie. allowing select's to return less columns than the mapping expects by modifying ResultMap class (in ibatis 2.3.4.726). This is a recurring usecase in our project's since we can model the entire domain model and code the selects and involving the intended columns on some queries and the other columns on other columns.

The solution is in ResultMap class in getResults() method.

previous to this line:

    for (int i = 0; i < getResultMappings().length; i++) {

add:

    ResultSetMetaData rsmd=rs.getMetaData();
    HashSet<String> columnasRS=new HashSet<String>();
    for (int i=1;i<=rsmd.getColumnCount();i++){
    	columnasRS.add(rsmd.getColumnName(i));
    }

and

below to the

    for (int i = 0; i < getResultMappings().length; i++) {
      ResultMapping mapping = (ResultMapping) getResultMappings()[i];

add:

      //Ver si la columna existe en la metadata
      if (!columnasRS.contains(mapping.getColumnName())){
    	  System.out.println("No existe la columna "+mapping.getColumnName()+". Salteando!");
      }
      else{
      ...
      existing code
      }

  
> support the parameter('#') in the replace string('$') and the result column of result map(class) not existed in select statement.
> ---------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: IBATIS-480
>                 URL: https://issues.apache.org/jira/browse/IBATIS-480
>             Project: iBatis for Java
>          Issue Type: Improvement
>          Components: SQL Maps
>    Affects Versions: 2.3.0
>         Environment: iBatis 2.3.0
>            Reporter: KwonKee Lim
>            Priority: Minor
>         Attachments: BasicResultMap.java, DynamicSql.java
>
>
> 1. support the parameter('#') in the replace string('$') 
> in the following sqlmap 
> 	<typeAlias alias="Test" type="...model.impl.TestImpl"/>
> 	<resultMap id="TestResult" class="Test">
> 		<result column="COL1" jdbcType="VARCHAR" property="COL1" javaType="String"/>
> 		<result column="COL2" jdbcType="VARCHAR" property="COL2" javaType="String"/>
> 		<result column="COL3" jdbcType="DECIMAL" property="COL3" javaType="long" nullValue="0"/>
> 		<result column="COL4" jdbcType="DECIMAL" property="COL4" javaType="long" nullValue="0"/>
> 	</resultMap>
> 	<select id="getTestsBySQL" parameterClass="Map" resultMap="TestResult">
> 		SELECT COL1,COL2,COL3
> 		FROM Test
> 		WHERE 
> 		$SQL$
> 		<isPropertyAvailable property="COL2" prepend="AND ">COL2 = #COL2#</isPropertyAvailable>
> 	</select>
> if the replace string '$SQL$' is 'COL1=#COL1#', the result sql string is '... WHERE COL1=#COL1#' .. ' .
> The sql exception occured , because the '#COL1#' in 'COL1=#COL1#'  not replaced  to '?'. 
> That is, the parameter('#') is not supperted in dynamic sql('$').
> My idea is that modify the "com.ibatis.sqlmap.engine.mapping.sql.dynamic.DynamicSql" class 's processBodyChildren method for dynamic sql('$').
>   private void processBodyChildren(RequestScope request, SqlTagContext ctx, Object parameterObject, Iterator localChildren, PrintWriter out) {
>     while (localChildren.hasNext()) {
>       SqlChild child = (SqlChild) localChildren.next();
>       if (child instanceof SqlText) {
>         SqlText sqlText = (SqlText) child;
>         String sqlStatement = sqlText.getText();
>         // CUSTOMIZE for support '#' in '$' by kklim 2007-12-26 <== here
>         // if the '$' is included , parsing one more.
>         if (SimpleDynamicSql.isSimpleDynamicSql(sqlStatement)) {
>         	sqlStatement = new SimpleDynamicSql(delegate, sqlStatement).getSql(request, parameterObject);
>         	sqlText.setPostParseRequired(true);
>         }
>         // CUSTOMIZE end
>        ...
> What do you think about this idea?
> 2. support the result column of result map(class) not existed in select statement.
> In the above sql map, the select statement's column is missing the column 'COL4', but the result map present the column 'COL4'.
> In case, The select statement 's columns in runtime is defined. a column presented by the result map is able to be missed.
> My idea is that modify the "com.ibatis.sqlmap.engine.mapping.result.BasicResultMap" class.
> 1) define the member variable for cached the resultsetmetadata's column(s)
>   // CUSTOMIZE does not exist column in resultmap for result set
>   private ThreadLocal rsmd = new ThreadLocal();
> 2) to initialize the the resultsetmetadata's column(s), modify the "getResults" method
>     // CUSTOMIZE initialize the columns of the resultset
>     if(rsmd.get() == null){
>     	ResultSetMetaData md = rs.getMetaData();
>     	int count = md.getColumnCount();
>     	Map columnNameMap = new HashMap(count);
>     	for(int i=0; i<count; i++){
>     		String columnName = md.getColumnName(i+1);
>     		columnNameMap.put(columnName, (i+1));
>     	}
>     	rsmd.set(columnNameMap);
>     }
>     // CUSTOMIZE END
> 3) to get the result's column , if the result map(class)'s columns does not exists, skip the getting the result colum
> in  getNestedSelectMappingValue method
> 	// CUSTOMIZE if not exist the column(s) of query, skip the column of the result map(class)
> 	Map columnNameMap = (Map)rsmd.get();
> 	if( columnNameMap == null || columnNameMap.containsKey(mapping.getColumnName())){
> 		result = ResultLoader.loadResult(client, statementName, parameterObject, targetType);
> 	}
> 	// CUSTOMIZE END
> and in getPrimitiveResultMappingValue method
>  protected Object getPrimitiveResultMappingValue(ResultSet rs, BasicResultMapping mapping) throws SQLException {
> 	Object value = null;
> 	// CUSTOMIZE if not exist the column(s) of query, skip the column of the result map(class)
> 	Map columnNameMap = (Map)rsmd.get();
> 	if( columnNameMap != null && !columnNameMap.containsKey(mapping.getColumnName())){
> 		return value;
> 	}
> 	...
> What do you think about this idea?

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.