You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user-java@ibatis.apache.org by Michael He <hy...@yahoo.com.cn> on 2008/12/11 13:14:51 UTC

Is this a bug ?

Hi all
       
      I currently use ibatis-2.3.4 and find that the <settings> element in
SqlMapConfig.xml shouldn't missed if you want the default  settings in this
tag to take effect even if you don't put any attributes in it.In other
words,if you don't leave the <settings> element in SqlMapConfig.xml,all the
boolean attributes(like cacheModelsEnabled,lazyLoadingEnabled) will be false
instead of the default value as said by the
docs(cacheModelsEnabled,lazyLoadingEnabled are both setted as true defaultly
according to the docs) .

      I digged into the source code,trying to find the reason and may be i
have located the problem :)

 ibatis uses the SqlMapConfigParser class to load the SqlMapConfig file ,for
example ,the code below parse the SqlMapConfig file as a reader:

    public static SqlMapClient buildSqlMapClient(Reader reader) {
//    return new XmlSqlMapClientBuilder().buildSqlMap(reader);
    return new SqlMapConfigParser().parse(reader);
  }
  
   ibatis actually uses a customed parser called the NodeletParser to parse
xml nodes,i paste the comments of this parser below:
/**
 * The NodeletParser is a callback based parser similar to SAX.  The big
 * difference is that rather than having a single callback for all nodes,
 * the NodeletParser has a number of callbacks mapped to
 * various nodes.   The callback is called a Nodelet and it is registered
 * with the NodeletParser against a specific XPath.
 */

 when SqlMapConfigParser is first initialized,it will store all the
Xpath(predifined xpathes for all the elements in the SqlMapConfig file) and
Nodelet as the key-value pair in a hashmap in NodeletParser class for
possible processes in the future.
  The SqlMapConfig will be parsed by calling the parse(reader) method,the
NodeletParser will use a recursive method that walkes the DOM tree,
registers XPaths and calls Nodelets registered under those XPaths.
The process method in the codes below  nodelet.process(node) actually
processes all the elments and their children.

  private void processNodelet(Node node, String pathString) {
    Nodelet nodelet = (Nodelet) letMap.get(pathString);
    if (nodelet != null) {
      try {
        nodelet.process(node);
      } catch (Exception e) {
        throw new RuntimeException("Error parsing XPath '" + pathString +
"'.  Cause: " + e, e);
      }
    }
  }

the process method for setting element is below,as you can see ,the
attribute like setLazyLoadingEnabled is setted as true if you don't specify
the value

public void process(Node node) throws Exception {
				Properties attributes = NodeletUtils.parseAttributes(node,
						state.getGlobalProps());
				SqlMapConfiguration config = state.getConfig();

				String classInfoCacheEnabledAttr = attributes
						.getProperty("classInfoCacheEnabled");
				boolean classInfoCacheEnabled = (classInfoCacheEnabledAttr == null ||
"true"
						.equals(classInfoCacheEnabledAttr));
				config.setClassInfoCacheEnabled(classInfoCacheEnabled);

				String lazyLoadingEnabledAttr = attributes
						.getProperty("lazyLoadingEnabled");
				boolean lazyLoadingEnabled = (lazyLoadingEnabledAttr == null || "true"
						.equals(lazyLoadingEnabledAttr));
				config.setLazyLoadingEnabled(lazyLoadingEnabled);

				String statementCachingEnabledAttr = attributes
						.getProperty("statementCachingEnabled");
				boolean statementCachingEnabled = (statementCachingEnabledAttr == null
|| "true"
						.equals(statementCachingEnabledAttr));
				config.setStatementCachingEnabled(statementCachingEnabled);

				String cacheModelsEnabledAttr = attributes
						.getProperty("cacheModelsEnabled");
				boolean cacheModelsEnabled = (cacheModelsEnabledAttr == null || "true"
						.equals(cacheModelsEnabledAttr));
				config.setCacheModelsEnabled(cacheModelsEnabled);

				String enhancementEnabledAttr = attributes
						.getProperty("enhancementEnabled");
				boolean enhancementEnabled = (enhancementEnabledAttr == null || "true"
						.equals(enhancementEnabledAttr));
				config.setEnhancementEnabled(enhancementEnabled);

				String useColumnLabelAttr = attributes
						.getProperty("useColumnLabel");
				boolean useColumnLabel = (useColumnLabelAttr == null || "true"
						.equals(useColumnLabelAttr));
				config.setUseColumnLabel(useColumnLabel);

				String forceMultipleResultSetSupportAttr = attributes
						.getProperty("forceMultipleResultSetSupport");
				boolean forceMultipleResultSetSupport = "true"
						.equals(forceMultipleResultSetSupportAttr);
				config
						.setForceMultipleResultSetSupport(forceMultipleResultSetSupport);

				String defaultTimeoutAttr = attributes
						.getProperty("defaultStatementTimeout");
				Integer defaultTimeout = defaultTimeoutAttr == null ? null
						: Integer.valueOf(defaultTimeoutAttr);
				config.setDefaultStatementTimeout(defaultTimeout);

				String useStatementNamespacesAttr = attributes
						.getProperty("useStatementNamespaces");
				boolean useStatementNamespaces = "true"
						.equals(useStatementNamespacesAttr);
				state.setUseStatementNamespaces(useStatementNamespaces);
			}     
so if there's no setting element in the config file,it will not be found in
the hashMap,so the nodelet will be null and the process(node) method will
not be called,thus all the setting attributes will be the default boolean
value false.That's where the problem is.

I'm a newbie so may be i have missed something or have made something
wrong,if I have, please let me know ,any help and comment will be
appreciated.

-- 
View this message in context: http://www.nabble.com/Is-this-a-bug---tp20954288p20954288.html
Sent from the iBATIS - User - Java mailing list archive at Nabble.com.


Re: Is this a bug ?

Posted by Jeff Butler <je...@gmail.com>.
I think this is a bug - there have been several posts related to this
issue.  If you could open a JIRA issue and attach a patch it would be
great.

Jeff


On Thu, Dec 11, 2008 at 6:14 AM, Michael He <hy...@yahoo.com.cn> wrote:
>
> Hi all
>
>      I currently use ibatis-2.3.4 and find that the <settings> element in
> SqlMapConfig.xml shouldn't missed if you want the default  settings in this
> tag to take effect even if you don't put any attributes in it.In other
> words,if you don't leave the <settings> element in SqlMapConfig.xml,all the
> boolean attributes(like cacheModelsEnabled,lazyLoadingEnabled) will be false
> instead of the default value as said by the
> docs(cacheModelsEnabled,lazyLoadingEnabled are both setted as true defaultly
> according to the docs) .
>
>      I digged into the source code,trying to find the reason and may be i
> have located the problem :)
>
>  ibatis uses the SqlMapConfigParser class to load the SqlMapConfig file ,for
> example ,the code below parse the SqlMapConfig file as a reader:
>
>    public static SqlMapClient buildSqlMapClient(Reader reader) {
> //    return new XmlSqlMapClientBuilder().buildSqlMap(reader);
>    return new SqlMapConfigParser().parse(reader);
>  }
>
>   ibatis actually uses a customed parser called the NodeletParser to parse
> xml nodes,i paste the comments of this parser below:
> /**
>  * The NodeletParser is a callback based parser similar to SAX.  The big
>  * difference is that rather than having a single callback for all nodes,
>  * the NodeletParser has a number of callbacks mapped to
>  * various nodes.   The callback is called a Nodelet and it is registered
>  * with the NodeletParser against a specific XPath.
>  */
>
>  when SqlMapConfigParser is first initialized,it will store all the
> Xpath(predifined xpathes for all the elements in the SqlMapConfig file) and
> Nodelet as the key-value pair in a hashmap in NodeletParser class for
> possible processes in the future.
>  The SqlMapConfig will be parsed by calling the parse(reader) method,the
> NodeletParser will use a recursive method that walkes the DOM tree,
> registers XPaths and calls Nodelets registered under those XPaths.
> The process method in the codes below  nodelet.process(node) actually
> processes all the elments and their children.
>
>  private void processNodelet(Node node, String pathString) {
>    Nodelet nodelet = (Nodelet) letMap.get(pathString);
>    if (nodelet != null) {
>      try {
>        nodelet.process(node);
>      } catch (Exception e) {
>        throw new RuntimeException("Error parsing XPath '" + pathString +
> "'.  Cause: " + e, e);
>      }
>    }
>  }
>
> the process method for setting element is below,as you can see ,the
> attribute like setLazyLoadingEnabled is setted as true if you don't specify
> the value
>
> public void process(Node node) throws Exception {
>                                Properties attributes = NodeletUtils.parseAttributes(node,
>                                                state.getGlobalProps());
>                                SqlMapConfiguration config = state.getConfig();
>
>                                String classInfoCacheEnabledAttr = attributes
>                                                .getProperty("classInfoCacheEnabled");
>                                boolean classInfoCacheEnabled = (classInfoCacheEnabledAttr == null ||
> "true"
>                                                .equals(classInfoCacheEnabledAttr));
>                                config.setClassInfoCacheEnabled(classInfoCacheEnabled);
>
>                                String lazyLoadingEnabledAttr = attributes
>                                                .getProperty("lazyLoadingEnabled");
>                                boolean lazyLoadingEnabled = (lazyLoadingEnabledAttr == null || "true"
>                                                .equals(lazyLoadingEnabledAttr));
>                                config.setLazyLoadingEnabled(lazyLoadingEnabled);
>
>                                String statementCachingEnabledAttr = attributes
>                                                .getProperty("statementCachingEnabled");
>                                boolean statementCachingEnabled = (statementCachingEnabledAttr == null
> || "true"
>                                                .equals(statementCachingEnabledAttr));
>                                config.setStatementCachingEnabled(statementCachingEnabled);
>
>                                String cacheModelsEnabledAttr = attributes
>                                                .getProperty("cacheModelsEnabled");
>                                boolean cacheModelsEnabled = (cacheModelsEnabledAttr == null || "true"
>                                                .equals(cacheModelsEnabledAttr));
>                                config.setCacheModelsEnabled(cacheModelsEnabled);
>
>                                String enhancementEnabledAttr = attributes
>                                                .getProperty("enhancementEnabled");
>                                boolean enhancementEnabled = (enhancementEnabledAttr == null || "true"
>                                                .equals(enhancementEnabledAttr));
>                                config.setEnhancementEnabled(enhancementEnabled);
>
>                                String useColumnLabelAttr = attributes
>                                                .getProperty("useColumnLabel");
>                                boolean useColumnLabel = (useColumnLabelAttr == null || "true"
>                                                .equals(useColumnLabelAttr));
>                                config.setUseColumnLabel(useColumnLabel);
>
>                                String forceMultipleResultSetSupportAttr = attributes
>                                                .getProperty("forceMultipleResultSetSupport");
>                                boolean forceMultipleResultSetSupport = "true"
>                                                .equals(forceMultipleResultSetSupportAttr);
>                                config
>                                                .setForceMultipleResultSetSupport(forceMultipleResultSetSupport);
>
>                                String defaultTimeoutAttr = attributes
>                                                .getProperty("defaultStatementTimeout");
>                                Integer defaultTimeout = defaultTimeoutAttr == null ? null
>                                                : Integer.valueOf(defaultTimeoutAttr);
>                                config.setDefaultStatementTimeout(defaultTimeout);
>
>                                String useStatementNamespacesAttr = attributes
>                                                .getProperty("useStatementNamespaces");
>                                boolean useStatementNamespaces = "true"
>                                                .equals(useStatementNamespacesAttr);
>                                state.setUseStatementNamespaces(useStatementNamespaces);
>                        }
> so if there's no setting element in the config file,it will not be found in
> the hashMap,so the nodelet will be null and the process(node) method will
> not be called,thus all the setting attributes will be the default boolean
> value false.That's where the problem is.
>
> I'm a newbie so may be i have missed something or have made something
> wrong,if I have, please let me know ,any help and comment will be
> appreciated.
>
> --
> View this message in context: http://www.nabble.com/Is-this-a-bug---tp20954288p20954288.html
> Sent from the iBATIS - User - Java mailing list archive at Nabble.com.
>
>