From 30ef590be1d6c5b9b670f99106ee4d072a05bfa6 Mon Sep 17 00:00:00 2001 From: Kazuki Shimizu Date: Sun, 12 Jul 2015 01:45:06 +0900 Subject: [PATCH 01/30] Add explanations for SqlSession#flushStatements and @Flush in documentation (cherry picked from commit e556d1c32a3bbd19e0e9e38a51e041a61ca1c5b9) --- src/site/es/xdoc/java-api.xml | 14 ++++++++++++++ src/site/ja/xdoc/java-api.xml | 14 ++++++++++++++ src/site/ko/xdoc/java-api.xml | 16 +++++++++++++++- src/site/xdoc/java-api.xml | 14 ++++++++++++++ src/site/zh/xdoc/java-api.xml | 15 +++++++++++++++ 5 files changed, 72 insertions(+), 1 deletion(-) diff --git a/src/site/es/xdoc/java-api.xml b/src/site/es/xdoc/java-api.xml index b4a916709..aaf8f4319 100644 --- a/src/site/es/xdoc/java-api.xml +++ b/src/site/es/xdoc/java-api.xml @@ -224,6 +224,10 @@ public interface ResultHandler {

El parámetro ResultContext te da acceso al objeto resultado en sí mismo, un contador del número de objetos creados y un método booleano stop() que te permite indicar a MyBatis que pare la carga de datos.

+
Batch update statement Flush Method
+

There is method for flushing(executing) batch update statements that stored in a JDBC driver class at any timing. This method can be used when you use the ExecutorType.BATCH as ExecutorType.

+ flushStatements()]]> +
Métodos de control de transacción

El parámetro ResultContext te da acceso al objeto resultado en sí mismo, un contador del número de objetos creados y un método booleano stop() que te permite indicar a MyBatis que pare la carga de datos.

void commit() @@ -463,6 +467,12 @@ try (SqlSession session = sqlSessionFactory.openSession()) { el valor de retorno será void y por tanto se requiere incluir esta anotación (o @ResultMap). La anotación se ignora si el tipo devuelto por el méotdo no es void. + + @Flush + Method + N/A + If this annotation is used, it can be called the SqlSession#flushStatements() via method defined at a Mapper interface.(MyBatis 3.3 or above) + @@ -476,6 +486,10 @@ try (SqlSession session = sqlSessionFactory.openSession()) { @Insert("insert into table2 (name) values(#{name})") @SelectKey(statement="call identity()", keyProperty="nameId", before=false, resultType=int.class) int insertTable2(Name name); + +

This example shows using the @Flush annotation to call the SqlSession#flushStatements():

+ flush();]]> diff --git a/src/site/ja/xdoc/java-api.xml b/src/site/ja/xdoc/java-api.xml index d7cf28033..34577a413 100644 --- a/src/site/ja/xdoc/java-api.xml +++ b/src/site/ja/xdoc/java-api.xml @@ -232,6 +232,10 @@ public interface ResultHandler {
  • 複雑な ResultMap では複数行のデータがひとつのオブジェクトにマッピングされることもあります。こうした ResultMap を ResultHandler と併用する際、association や collection のデータがマッピングされる前の状態のオブジェクトが渡される場合があります。
  • +
    バッチ更新ステートメントをフラッシュするメソッド
    +

    バッチ更新用に JDBC ドライバ内に蓄積されたステートメントを任意のタイミングでデータベースへフラッシュ(実行)するメソッドがあります。このメソッドは、 ExecutorType として ExecutorType.BATCH を使用している場合に使用することができます。

    + flushStatements()]]> +
    トランザクションを制御するメソッド

    トランザクションのスコープを制御するメソッドは4つあります。当然ですが、auto-commit を使用する場合や、外部のトランザクションマネージャーを使っている場合、これらのメソッドは効果がありません。しかし、Connection のインスタンスによって管理されている JDBC トランザクションマネージャーを利用している場合は便利なメソッドです。

    void commit() @@ -481,6 +485,12 @@ try (SqlSession session = sqlSessionFactory.openSession()) { N/A ResultHandler を使うメソッドでは戻り値の型が void となるので、このアノテーションを使って各行のデータをどのクラスにマップするかを指定します。XMLの ResultMap が存在する場合は @ResultMap アノテーションで指定することができます。XML の <select> 要素で resultType が指定されている場合はアノテーションによる指定は不要です。それ以外の場合、例えば @Select アノテーションが付加された引数に ResultHandler を含むメソッドの場合は戻り値の型は void である必要があるので、このアノテーション(あるいは @ResultMap)を使って型を指定する必要があります。メソッドの戻り値の型が void 以外の場合、このアノテーションは無視されます。 + + @Flush + Method + N/A + このアノテーションを使用すると、SqlSession#flushStatements()メソッドを Mapper インタフェースに定義したメソッド経由で呼び出すことができます。(MyBatis 3.3以上) + @@ -494,6 +504,10 @@ try (SqlSession session = sqlSessionFactory.openSession()) { @Insert("insert into table2 (name) values(#{name})") @SelectKey(statement="call identity()", keyProperty="nameId", before=false, resultType=int.class) int insertTable2(Name name); + +

    次のコードは @Flush アノテーションを使って SqlSession#flushStatements()メソッドを呼び出す例です。

    + flush();]]> diff --git a/src/site/ko/xdoc/java-api.xml b/src/site/ko/xdoc/java-api.xml index c1515cbf3..64e671326 100644 --- a/src/site/ko/xdoc/java-api.xml +++ b/src/site/ko/xdoc/java-api.xml @@ -271,6 +271,10 @@ public interface ResultHandler {

    ResultContext 파라미터는 결과 객체에 접근할 수 있도록 해준다.

    +
    Batch update statement Flush Method
    +

    There is method for flushing(executing) batch update statements that stored in a JDBC driver class at any timing. This method can be used when you use the ExecutorType.BATCH as ExecutorType.

    + flushStatements()]]> +
    트랙잭션 제어 메서드

    트랜잭션을 제어하기 위해 4 개의 메서드가 있다. 물론 자동커밋을 선택하였거나 외부 트랜잭션 관리자를 사용하면 영향이 없다. 어쨌든, Connection 인스턴스에 의해 관리되고 JDBC 트랜잭션 관리자를 사용하면, 이 4 개의 메서드를 사용할 수 @@ -622,7 +626,13 @@ id 를 제공하기 위해 사용된다. XML 에 정의된 결과 예를들어, @Select 애노테이션이 선언되어 있다면 메소드는 결과 핸들러를 사용할 것이다. 결과 타입은 void여야만 하고 이 애노테이션(이나 @ResultMap)을 반드시 사용해야 한다. 이 애노테이션은 메소드 리턴타입이 void가 아니라면 무시한다. - + + + @Flush + Method + N/A + If this annotation is used, it can be called the SqlSession#flushStatements() via method defined at a Mapper interface.(MyBatis 3.3 or above) + @@ -636,6 +646,10 @@ id 를 제공하기 위해 사용된다. XML 에 정의된 결과 @Insert("insert into table2 (name) values(#{name})") @SelectKey(statement="call identity()", keyProperty="nameId", before=false, resultType=int.class) int insertTable2(Name name); + +

    This example shows using the @Flush annotation to call the SqlSession#flushStatements():

    + flush();]]> diff --git a/src/site/xdoc/java-api.xml b/src/site/xdoc/java-api.xml index 0a1d62c18..26e190ac0 100644 --- a/src/site/xdoc/java-api.xml +++ b/src/site/xdoc/java-api.xml @@ -237,6 +237,10 @@ public interface ResultHandler {
  • When using advanced resultmaps MyBatis will probably require several rows to build an object. If a ResultHandler is used you may be given an object whose associations or collections are not yet filled.
  • +
    Batch update statement Flush Method
    +

    There is method for flushing(executing) batch update statements that stored in a JDBC driver class at any timing. This method can be used when you use the ExecutorType.BATCH as ExecutorType.

    + flushStatements()]]> +
    Transaction Control Methods

    There are four methods for controlling the scope of a transaction. Of course, these have no effect if you've chosen to use auto-commit or if you're using an external transaction manager. However, if you're using the JDBC transaction manager, managed by the Connection instance, then the four methods that will come in handy are:

    void commit() @@ -530,6 +534,12 @@ try (SqlSession session = sqlSessionFactory.openSession()) { will use a result handler, the return type must be void and this annotation (or @ResultMap) is required. This annotation is ignored unless the method return type is void. + + @Flush + Method + N/A + If this annotation is used, it can be called the SqlSession#flushStatements() via method defined at a Mapper interface.(MyBatis 3.3 or above) + @@ -543,6 +553,10 @@ try (SqlSession session = sqlSessionFactory.openSession()) { @Insert("insert into table2 (name) values(#{name})") @SelectKey(statement="call identity()", keyProperty="nameId", before=false, resultType=int.class) int insertTable2(Name name); + +

    This example shows using the @Flush annotation to call the SqlSession#flushStatements():

    + flush();]]> diff --git a/src/site/zh/xdoc/java-api.xml b/src/site/zh/xdoc/java-api.xml index d206db072..633c63204 100644 --- a/src/site/zh/xdoc/java-api.xml +++ b/src/site/zh/xdoc/java-api.xml @@ -364,6 +364,11 @@ public interface ResultHandler { 尔返回值的 stop()方法来停止 MyBatis 加载更多的结果。

    +
    Batch update statement Flush Method
    +

    There is method for flushing(executing) batch update statements that stored in a JDBC driver class at any timing. This method can be used when you use the ExecutorType.BATCH as ExecutorType.

    + flushStatements()]]> + +
    事务控制方法

    控制事务范围有四个方法。 @@ -800,6 +805,12 @@ type,method。type 属性是类的完全限 will use a result handler, the return type must be void and this annotation (or @ResultMap) is required. This annotation is ignored unless the method return type is void. + + @Flush + Method + N/A + If this annotation is used, it can be called the SqlSession#flushStatements() via method defined at a Mapper interface.(MyBatis 3.3 or above) + @@ -813,6 +824,10 @@ type,method。type 属性是类的完全限 @Insert("insert into table2 (name) values(#{name})") @SelectKey(statement="call identity()", keyProperty="nameId", before=false, resultType=int.class) int insertTable2(Name name); + +

    This example shows using the @Flush annotation to call the SqlSession#flushStatements():

    + flush();]]> From 7923be4b7ef462ae66dd00bc79252b5b822a2136 Mon Sep 17 00:00:00 2001 From: Kazuki Shimizu Date: Sun, 12 Jul 2015 03:14:01 +0900 Subject: [PATCH 02/30] Add explanations for defaultFetchSize in documentation (cherry picked from commit f1419125348aabb499602558de20742990285000) --- src/site/es/xdoc/configuration.xml | 16 ++++++++++++++++ src/site/ja/xdoc/configuration.xml | 16 ++++++++++++++++ src/site/ko/xdoc/configuration.xml | 16 ++++++++++++++++ src/site/xdoc/configuration.xml | 16 ++++++++++++++++ src/site/zh/xdoc/configuration.xml | 16 ++++++++++++++++ 5 files changed, 80 insertions(+) diff --git a/src/site/es/xdoc/configuration.xml b/src/site/es/xdoc/configuration.xml index acb713ff5..ed2307f52 100644 --- a/src/site/es/xdoc/configuration.xml +++ b/src/site/es/xdoc/configuration.xml @@ -226,6 +226,21 @@ SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader, environment, Sin valor (null) + + + defaultFetchSize + + + Sets the driver a hint as to control fetching size for return results. + This parameter value can be override by a query setting. + + + Cualquier entero positivo + + + Sin valor (null) + + safeRowBoundsEnabled @@ -384,6 +399,7 @@ A continuación se muestra un ejemplo del elemento settings al completo: + diff --git a/src/site/ja/xdoc/configuration.xml b/src/site/ja/xdoc/configuration.xml index 1d467ec45..eb3fe1927 100644 --- a/src/site/ja/xdoc/configuration.xml +++ b/src/site/ja/xdoc/configuration.xml @@ -257,6 +257,21 @@ SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader, environment, なし (null) + + + defaultFetchSize + + + 検索結果のフェッチサイズを制御するためのドライバヒントを設定します。 + このパラメータ値はクエリ毎の設定で上書きできます。 + + + 正の整数 + + + なし (null) + + safeRowBoundsEnabled @@ -414,6 +429,7 @@ SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader, environment, + diff --git a/src/site/ko/xdoc/configuration.xml b/src/site/ko/xdoc/configuration.xml index a722d2d0d..4929ed938 100644 --- a/src/site/ko/xdoc/configuration.xml +++ b/src/site/ko/xdoc/configuration.xml @@ -209,6 +209,21 @@ SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader, environment, 셋팅되지 않음(null) + + + defaultFetchSize + + + Sets the driver a hint as to control fetching size for return results. + This parameter value can be override by a query setting. + + + 양수 + + + 셋팅되지 않음(null) + + safeRowBoundsEnabled @@ -367,6 +382,7 @@ SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader, environment, + diff --git a/src/site/xdoc/configuration.xml b/src/site/xdoc/configuration.xml index 416b19767..139a8e6cd 100644 --- a/src/site/xdoc/configuration.xml +++ b/src/site/xdoc/configuration.xml @@ -315,6 +315,21 @@ SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader, environment, Not Set (null) + + + defaultFetchSize + + + Sets the driver a hint as to control fetching size for return results. + This parameter value can be override by a query setting. + + + Any positive integer + + + Not Set (null) + + safeRowBoundsEnabled @@ -476,6 +491,7 @@ SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader, environment, + diff --git a/src/site/zh/xdoc/configuration.xml b/src/site/zh/xdoc/configuration.xml index 048ee55d8..283e75a7f 100644 --- a/src/site/zh/xdoc/configuration.xml +++ b/src/site/zh/xdoc/configuration.xml @@ -238,6 +238,21 @@ SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader, environment, Not Set (null) + + + defaultFetchSize + + + Sets the driver a hint as to control fetching size for return results. + This parameter value can be override by a query setting. + + + Any positive integer + + + Not Set (null) + + safeRowBoundsEnabled @@ -395,6 +410,7 @@ SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader, environment, + From 87d3f56a09132f8afc371f3b9e9b4344ff3830fe Mon Sep 17 00:00:00 2001 From: Kazuki Shimizu Date: Sun, 12 Jul 2015 03:26:26 +0900 Subject: [PATCH 03/30] Change explanation of default proxyFactory in documentation (CGLIB -> JAVASSIST) (cherry picked from commit 53f459444b411a3b69d6c8a8d46332667b5a1379) --- src/site/es/xdoc/configuration.xml | 2 +- src/site/ja/xdoc/configuration.xml | 2 +- src/site/ko/xdoc/configuration.xml | 2 +- src/site/xdoc/configuration.xml | 2 +- src/site/zh/xdoc/configuration.xml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/site/es/xdoc/configuration.xml b/src/site/es/xdoc/configuration.xml index acb713ff5..d9332abe7 100644 --- a/src/site/es/xdoc/configuration.xml +++ b/src/site/es/xdoc/configuration.xml @@ -367,7 +367,7 @@ SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader, environment, CGLIB | JAVASSIST - CGLIB + JAVASSIST (MyBatis 3.3 or above) diff --git a/src/site/ja/xdoc/configuration.xml b/src/site/ja/xdoc/configuration.xml index 1d467ec45..fc169b791 100644 --- a/src/site/ja/xdoc/configuration.xml +++ b/src/site/ja/xdoc/configuration.xml @@ -397,7 +397,7 @@ SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader, environment, CGLIB | JAVASSIST - CGLIB + JAVASSIST (MyBatis 3.3 以上) diff --git a/src/site/ko/xdoc/configuration.xml b/src/site/ko/xdoc/configuration.xml index a722d2d0d..080b29224 100644 --- a/src/site/ko/xdoc/configuration.xml +++ b/src/site/ko/xdoc/configuration.xml @@ -352,7 +352,7 @@ SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader, environment, CGLIB | JAVASSIST - CGLIB + JAVASSIST (MyBatis 3.3 or above) diff --git a/src/site/xdoc/configuration.xml b/src/site/xdoc/configuration.xml index 416b19767..124b1aaa5 100644 --- a/src/site/xdoc/configuration.xml +++ b/src/site/xdoc/configuration.xml @@ -459,7 +459,7 @@ SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader, environment, CGLIB | JAVASSIST - CGLIB + JAVASSIST (MyBatis 3.3 or above) diff --git a/src/site/zh/xdoc/configuration.xml b/src/site/zh/xdoc/configuration.xml index 048ee55d8..c6e16576b 100644 --- a/src/site/zh/xdoc/configuration.xml +++ b/src/site/zh/xdoc/configuration.xml @@ -378,7 +378,7 @@ SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader, environment, CGLIB | JAVASSIST - CGLIB + JAVASSIST (MyBatis 3.3 or above) From 46086be16e32f4534c8f1ddbe3dc2af91cae01ee Mon Sep 17 00:00:00 2001 From: Iwao AVE! Date: Wed, 19 Aug 2015 03:58:57 +0900 Subject: [PATCH 04/30] #325 Added vfsImpl setting to make VFS implementation configurable. --- .../ibatis/builder/xml/XMLConfigBuilder.java | 88 ++++++++++++------- .../apache/ibatis/session/Configuration.java | 14 +++ .../CustomizedSettingsMapperConfig.xml | 1 + .../ibatis/builder/XmlConfigBuilderTest.java | 2 + 4 files changed, 71 insertions(+), 34 deletions(-) diff --git a/src/main/java/org/apache/ibatis/builder/xml/XMLConfigBuilder.java b/src/main/java/org/apache/ibatis/builder/xml/XMLConfigBuilder.java index 6c503ec82..52724c8e6 100644 --- a/src/main/java/org/apache/ibatis/builder/xml/XMLConfigBuilder.java +++ b/src/main/java/org/apache/ibatis/builder/xml/XMLConfigBuilder.java @@ -18,6 +18,7 @@ import java.io.InputStream; import java.io.Reader; import java.util.Properties; +import java.util.Set; import javax.sql.DataSource; @@ -98,14 +99,16 @@ public Configuration parse() { private void parseConfiguration(XNode root) { try { + Properties settings = settingsAsPropertiess(root.evalNode("settings")); //issue #117 read properties first propertiesElement(root.evalNode("properties")); + loadCustomVfs(settings); typeAliasesElement(root.evalNode("typeAliases")); pluginElement(root.evalNode("plugins")); objectFactoryElement(root.evalNode("objectFactory")); objectWrapperFactoryElement(root.evalNode("objectWrapperFactory")); reflectionFactoryElement(root.evalNode("reflectionFactory")); - settingsElement(root.evalNode("settings")); + settingsElement(settings); // read it after objectFactory and objectWrapperFactory issue #631 environmentsElement(root.evalNode("environments")); databaseIdProviderElement(root.evalNode("databaseIdProvider")); @@ -116,6 +119,33 @@ private void parseConfiguration(XNode root) { } } + private Properties settingsAsPropertiess(XNode context) { + if (context == null) { + return new Properties(); + } + Properties props = context.getChildrenAsProperties(); + // Check that all settings are known to the configuration class + MetaClass metaConfig = MetaClass.forClass(Configuration.class, localReflectorFactory); + for (Object key : props.keySet()) { + if (!metaConfig.hasSetter(String.valueOf(key))) { + throw new BuilderException("The setting " + key + " is not known. Make sure you spelled it correctly (case sensitive)."); + } + } + return props; + } + + private void loadCustomVfs(Properties props) throws ClassNotFoundException { + String value = props.getProperty("vfsImpl"); + if (value != null) { + String[] clazzes = value.split(","); + for (String clazz : clazzes) { + if (!clazz.isEmpty()) { + configuration.setVfsImpl(Resources.classForName(clazz)); + } + } + } + } + private void typeAliasesElement(XNode parent) { if (parent != null) { for (XNode child : parent.getChildren()) { @@ -200,39 +230,29 @@ private void propertiesElement(XNode context) throws Exception { } } - private void settingsElement(XNode context) throws Exception { - if (context != null) { - Properties props = context.getChildrenAsProperties(); - // Check that all settings are known to the configuration class - MetaClass metaConfig = MetaClass.forClass(Configuration.class, localReflectorFactory); - for (Object key : props.keySet()) { - if (!metaConfig.hasSetter(String.valueOf(key))) { - throw new BuilderException("The setting " + key + " is not known. Make sure you spelled it correctly (case sensitive)."); - } - } - configuration.setAutoMappingBehavior(AutoMappingBehavior.valueOf(props.getProperty("autoMappingBehavior", "PARTIAL"))); - configuration.setCacheEnabled(booleanValueOf(props.getProperty("cacheEnabled"), true)); - configuration.setProxyFactory((ProxyFactory) createInstance(props.getProperty("proxyFactory"))); - configuration.setLazyLoadingEnabled(booleanValueOf(props.getProperty("lazyLoadingEnabled"), false)); - configuration.setAggressiveLazyLoading(booleanValueOf(props.getProperty("aggressiveLazyLoading"), true)); - configuration.setMultipleResultSetsEnabled(booleanValueOf(props.getProperty("multipleResultSetsEnabled"), true)); - configuration.setUseColumnLabel(booleanValueOf(props.getProperty("useColumnLabel"), true)); - configuration.setUseGeneratedKeys(booleanValueOf(props.getProperty("useGeneratedKeys"), false)); - configuration.setDefaultExecutorType(ExecutorType.valueOf(props.getProperty("defaultExecutorType", "SIMPLE"))); - configuration.setDefaultStatementTimeout(integerValueOf(props.getProperty("defaultStatementTimeout"), null)); - configuration.setDefaultFetchSize(integerValueOf(props.getProperty("defaultFetchSize"), null)); - configuration.setMapUnderscoreToCamelCase(booleanValueOf(props.getProperty("mapUnderscoreToCamelCase"), false)); - configuration.setSafeRowBoundsEnabled(booleanValueOf(props.getProperty("safeRowBoundsEnabled"), false)); - configuration.setLocalCacheScope(LocalCacheScope.valueOf(props.getProperty("localCacheScope", "SESSION"))); - configuration.setJdbcTypeForNull(JdbcType.valueOf(props.getProperty("jdbcTypeForNull", "OTHER"))); - configuration.setLazyLoadTriggerMethods(stringSetValueOf(props.getProperty("lazyLoadTriggerMethods"), "equals,clone,hashCode,toString")); - configuration.setSafeResultHandlerEnabled(booleanValueOf(props.getProperty("safeResultHandlerEnabled"), true)); - configuration.setDefaultScriptingLanguage(resolveClass(props.getProperty("defaultScriptingLanguage"))); - configuration.setCallSettersOnNulls(booleanValueOf(props.getProperty("callSettersOnNulls"), false)); - configuration.setLogPrefix(props.getProperty("logPrefix")); - configuration.setLogImpl(resolveClass(props.getProperty("logImpl"))); - configuration.setConfigurationFactory(resolveClass(props.getProperty("configurationFactory"))); - } + private void settingsElement(Properties props) throws Exception { + configuration.setAutoMappingBehavior(AutoMappingBehavior.valueOf(props.getProperty("autoMappingBehavior", "PARTIAL"))); + configuration.setCacheEnabled(booleanValueOf(props.getProperty("cacheEnabled"), true)); + configuration.setProxyFactory((ProxyFactory) createInstance(props.getProperty("proxyFactory"))); + configuration.setLazyLoadingEnabled(booleanValueOf(props.getProperty("lazyLoadingEnabled"), false)); + configuration.setAggressiveLazyLoading(booleanValueOf(props.getProperty("aggressiveLazyLoading"), true)); + configuration.setMultipleResultSetsEnabled(booleanValueOf(props.getProperty("multipleResultSetsEnabled"), true)); + configuration.setUseColumnLabel(booleanValueOf(props.getProperty("useColumnLabel"), true)); + configuration.setUseGeneratedKeys(booleanValueOf(props.getProperty("useGeneratedKeys"), false)); + configuration.setDefaultExecutorType(ExecutorType.valueOf(props.getProperty("defaultExecutorType", "SIMPLE"))); + configuration.setDefaultStatementTimeout(integerValueOf(props.getProperty("defaultStatementTimeout"), null)); + configuration.setDefaultFetchSize(integerValueOf(props.getProperty("defaultFetchSize"), null)); + configuration.setMapUnderscoreToCamelCase(booleanValueOf(props.getProperty("mapUnderscoreToCamelCase"), false)); + configuration.setSafeRowBoundsEnabled(booleanValueOf(props.getProperty("safeRowBoundsEnabled"), false)); + configuration.setLocalCacheScope(LocalCacheScope.valueOf(props.getProperty("localCacheScope", "SESSION"))); + configuration.setJdbcTypeForNull(JdbcType.valueOf(props.getProperty("jdbcTypeForNull", "OTHER"))); + configuration.setLazyLoadTriggerMethods(stringSetValueOf(props.getProperty("lazyLoadTriggerMethods"), "equals,clone,hashCode,toString")); + configuration.setSafeResultHandlerEnabled(booleanValueOf(props.getProperty("safeResultHandlerEnabled"), true)); + configuration.setDefaultScriptingLanguage(resolveClass(props.getProperty("defaultScriptingLanguage"))); + configuration.setCallSettersOnNulls(booleanValueOf(props.getProperty("callSettersOnNulls"), false)); + configuration.setLogPrefix(props.getProperty("logPrefix")); + configuration.setLogImpl(resolveClass(props.getProperty("logImpl"))); + configuration.setConfigurationFactory(resolveClass(props.getProperty("configurationFactory"))); } private void environmentsElement(XNode context) throws Exception { diff --git a/src/main/java/org/apache/ibatis/session/Configuration.java b/src/main/java/org/apache/ibatis/session/Configuration.java index 57201d084..e6c63f356 100644 --- a/src/main/java/org/apache/ibatis/session/Configuration.java +++ b/src/main/java/org/apache/ibatis/session/Configuration.java @@ -53,6 +53,7 @@ import org.apache.ibatis.executor.resultset.ResultSetHandler; import org.apache.ibatis.executor.statement.RoutingStatementHandler; import org.apache.ibatis.executor.statement.StatementHandler; +import org.apache.ibatis.io.VFS; import org.apache.ibatis.logging.Log; import org.apache.ibatis.logging.LogFactory; import org.apache.ibatis.logging.commons.JakartaCommonsLoggingImpl; @@ -108,6 +109,7 @@ public class Configuration { protected String logPrefix; protected Class logImpl; + protected Class vfsImpl; protected LocalCacheScope localCacheScope = LocalCacheScope.SESSION; protected JdbcType jdbcTypeForNull = JdbcType.OTHER; protected Set lazyLoadTriggerMethods = new HashSet(Arrays.asList(new String[] { "equals", "clone", "hashCode", "toString" })); @@ -219,6 +221,18 @@ public void setLogImpl(Class logImpl) { } } + public Class getVfsImpl() { + return this.vfsImpl; + } + + @SuppressWarnings("unchecked") + public void setVfsImpl(Class vfsImpl) { + if (vfsImpl != null) { + this.vfsImpl = (Class) vfsImpl; + VFS.addImplClass(this.vfsImpl); + } + } + public boolean isCallSettersOnNulls() { return callSettersOnNulls; } diff --git a/src/test/java/org/apache/ibatis/builder/CustomizedSettingsMapperConfig.xml b/src/test/java/org/apache/ibatis/builder/CustomizedSettingsMapperConfig.xml index 539471226..394d88cdc 100644 --- a/src/test/java/org/apache/ibatis/builder/CustomizedSettingsMapperConfig.xml +++ b/src/test/java/org/apache/ibatis/builder/CustomizedSettingsMapperConfig.xml @@ -45,6 +45,7 @@ + diff --git a/src/test/java/org/apache/ibatis/builder/XmlConfigBuilderTest.java b/src/test/java/org/apache/ibatis/builder/XmlConfigBuilderTest.java index d6aefdf52..18c7d3eaa 100644 --- a/src/test/java/org/apache/ibatis/builder/XmlConfigBuilderTest.java +++ b/src/test/java/org/apache/ibatis/builder/XmlConfigBuilderTest.java @@ -28,6 +28,7 @@ import org.apache.ibatis.builder.xml.XMLConfigBuilder; import org.apache.ibatis.executor.loader.cglib.CglibProxyFactory; import org.apache.ibatis.executor.loader.javassist.JavassistProxyFactory; +import org.apache.ibatis.io.JBoss6VFS; import org.apache.ibatis.io.Resources; import org.apache.ibatis.logging.slf4j.Slf4jImpl; import org.apache.ibatis.scripting.defaults.RawLanguageDriver; @@ -164,6 +165,7 @@ public void shouldSuccessfullyLoadXMLConfigFile() throws Exception { assertThat(config.isCallSettersOnNulls(), is(true)); assertThat(config.getLogPrefix(), is("mybatis_")); assertThat(config.getLogImpl().getName(), is(Slf4jImpl.class.getName())); + assertThat(config.getVfsImpl().getName(), is(JBoss6VFS.class.getName())); assertThat(config.getConfigurationFactory().getName(), is(String.class.getName())); } From f9ce9b6835cfa036ebb402c48393b6a42191c370 Mon Sep 17 00:00:00 2001 From: Iwao AVE! Date: Wed, 3 Feb 2016 04:55:40 +0900 Subject: [PATCH 05/30] Increased heap size for maven-surefire-plugin. --- pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/pom.xml b/pom.xml index 0bb52ab26..c9e74e35e 100644 --- a/pom.xml +++ b/pom.xml @@ -249,6 +249,7 @@ org.apache.maven.plugins maven-surefire-plugin + -Xmx1024m derby.stream.error.file From 42209f2347f9ab441122dfb5a0084b1ff9835b35 Mon Sep 17 00:00:00 2001 From: Iwao AVE! Date: Wed, 3 Feb 2016 15:49:22 +0900 Subject: [PATCH 06/30] Trying container based build on Travis-CI. --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 593876855..880602d32 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,6 @@ language: java +sudo: false + jdk: - oraclejdk8 - oraclejdk7 From 610e55290768d80ee6cb5401db2fe7ae81987709 Mon Sep 17 00:00:00 2001 From: Iwao AVE! Date: Fri, 13 Nov 2015 03:49:19 +0900 Subject: [PATCH 07/30] fixes #492 Avoid NPE when CallableStatement#getObject(int parameterIndex) returned null. --- .../ibatis/executor/resultset/DefaultResultSetHandler.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/org/apache/ibatis/executor/resultset/DefaultResultSetHandler.java b/src/main/java/org/apache/ibatis/executor/resultset/DefaultResultSetHandler.java index a025097cf..6c08f9b84 100644 --- a/src/main/java/org/apache/ibatis/executor/resultset/DefaultResultSetHandler.java +++ b/src/main/java/org/apache/ibatis/executor/resultset/DefaultResultSetHandler.java @@ -127,6 +127,9 @@ public void handleOutputParameters(CallableStatement cs) throws SQLException { } private void handleRefCursorOutputParameter(ResultSet rs, ParameterMapping parameterMapping, MetaObject metaParam) throws SQLException { + if (rs == null) { + return; + } try { final String resultMapId = parameterMapping.getResultMapId(); final ResultMap resultMap = configuration.getResultMap(resultMapId); From 9b50bfef72901c17005c523dde30621e86d24313 Mon Sep 17 00:00:00 2001 From: Iwao AVE! Date: Wed, 9 Dec 2015 14:28:39 +0900 Subject: [PATCH 08/30] fixes #482 As MyBatis requires Java 6 since version 3.2.0, we can use the setNString/getNString methods. --- .../org/apache/ibatis/type/NStringTypeHandler.java | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/apache/ibatis/type/NStringTypeHandler.java b/src/main/java/org/apache/ibatis/type/NStringTypeHandler.java index 52d59b40d..91c5b632d 100644 --- a/src/main/java/org/apache/ibatis/type/NStringTypeHandler.java +++ b/src/main/java/org/apache/ibatis/type/NStringTypeHandler.java @@ -28,28 +28,25 @@ public class NStringTypeHandler extends BaseTypeHandler { @Override public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException { -// ps.setNString(i, ((String) parameter)); - ps.setString(i, parameter); + ps.setNString(i, parameter); } @Override public String getNullableResult(ResultSet rs, String columnName) throws SQLException { -// return rs.getNString(columnName); - return rs.getString(columnName); + return rs.getNString(columnName); } @Override public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException { - return rs.getString(columnIndex); + return rs.getNString(columnIndex); } @Override public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { -// return cs.getNString(columnIndex); - return cs.getString(columnIndex); + return cs.getNString(columnIndex); } -} \ No newline at end of file +} From 1ccb98866286767f0beddccda0b801cced0913ae Mon Sep 17 00:00:00 2001 From: Eduardo Macarron Date: Wed, 13 Jan 2016 16:44:41 +0100 Subject: [PATCH 09/30] Merge pull request #550 from djgraff209/master Correct logging of 'N' parameters --- .../java/org/apache/ibatis/logging/jdbc/BaseJdbcLogger.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/org/apache/ibatis/logging/jdbc/BaseJdbcLogger.java b/src/main/java/org/apache/ibatis/logging/jdbc/BaseJdbcLogger.java index 4f2b47d1b..dae045dc2 100644 --- a/src/main/java/org/apache/ibatis/logging/jdbc/BaseJdbcLogger.java +++ b/src/main/java/org/apache/ibatis/logging/jdbc/BaseJdbcLogger.java @@ -59,6 +59,7 @@ public BaseJdbcLogger(Log log, int queryStack) { static { SET_METHODS.add("setString"); + SET_METHODS.add("setNString"); SET_METHODS.add("setInt"); SET_METHODS.add("setByte"); SET_METHODS.add("setShort"); @@ -76,7 +77,9 @@ public BaseJdbcLogger(Log log, int queryStack) { SET_METHODS.add("setBoolean"); SET_METHODS.add("setBytes"); SET_METHODS.add("setCharacterStream"); + SET_METHODS.add("setNCharacterStream"); SET_METHODS.add("setClob"); + SET_METHODS.add("setNClob"); SET_METHODS.add("setObject"); SET_METHODS.add("setNull"); From 87b2c88760ed1d5867476fe721000af53a7513a8 Mon Sep 17 00:00:00 2001 From: Iwao AVE! Date: Wed, 9 Sep 2015 03:35:15 +0900 Subject: [PATCH 10/30] fixes #155 Allow naming a result map in java mapper interface. --- .../apache/ibatis/annotations/Results.java | 4 + .../annotation/MapperAnnotationBuilder.java | 4 + .../submitted/results_id/AnotherMapper.java | 32 ++++++ .../submitted/results_id/AnotherMapper.xml | 25 ++++ .../ibatis/submitted/results_id/CreateDB.sql | 25 ++++ .../results_id/IdConflictMapper.java | 27 +++++ .../submitted/results_id/IdConflictMapper.xml | 26 +++++ .../submitted/results_id/IdConflictTest.java | 38 ++++++ .../ibatis/submitted/results_id/Mapper.java | 49 ++++++++ .../submitted/results_id/ResultsIdTest.java | 108 ++++++++++++++++++ .../ibatis/submitted/results_id/User.java | 48 ++++++++ .../submitted/results_id/mybatis-config.xml | 41 +++++++ 12 files changed, 427 insertions(+) create mode 100644 src/test/java/org/apache/ibatis/submitted/results_id/AnotherMapper.java create mode 100644 src/test/java/org/apache/ibatis/submitted/results_id/AnotherMapper.xml create mode 100644 src/test/java/org/apache/ibatis/submitted/results_id/CreateDB.sql create mode 100644 src/test/java/org/apache/ibatis/submitted/results_id/IdConflictMapper.java create mode 100644 src/test/java/org/apache/ibatis/submitted/results_id/IdConflictMapper.xml create mode 100644 src/test/java/org/apache/ibatis/submitted/results_id/IdConflictTest.java create mode 100644 src/test/java/org/apache/ibatis/submitted/results_id/Mapper.java create mode 100644 src/test/java/org/apache/ibatis/submitted/results_id/ResultsIdTest.java create mode 100644 src/test/java/org/apache/ibatis/submitted/results_id/User.java create mode 100644 src/test/java/org/apache/ibatis/submitted/results_id/mybatis-config.xml diff --git a/src/main/java/org/apache/ibatis/annotations/Results.java b/src/main/java/org/apache/ibatis/annotations/Results.java index 00ad42106..45c36453c 100644 --- a/src/main/java/org/apache/ibatis/annotations/Results.java +++ b/src/main/java/org/apache/ibatis/annotations/Results.java @@ -26,5 +26,9 @@ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface Results { + /** + * The name of the result map. + */ + String id() default ""; Result[] value() default {}; } diff --git a/src/main/java/org/apache/ibatis/builder/annotation/MapperAnnotationBuilder.java b/src/main/java/org/apache/ibatis/builder/annotation/MapperAnnotationBuilder.java index 749174357..3a4455d6f 100644 --- a/src/main/java/org/apache/ibatis/builder/annotation/MapperAnnotationBuilder.java +++ b/src/main/java/org/apache/ibatis/builder/annotation/MapperAnnotationBuilder.java @@ -196,6 +196,10 @@ private String parseResultMap(Method method) { } private String generateResultMapName(Method method) { + Results results = method.getAnnotation(Results.class); + if (results != null && !results.id().isEmpty()) { + return type.getName() + "." + results.id(); + } StringBuilder suffix = new StringBuilder(); for (Class c : method.getParameterTypes()) { suffix.append("-"); diff --git a/src/test/java/org/apache/ibatis/submitted/results_id/AnotherMapper.java b/src/test/java/org/apache/ibatis/submitted/results_id/AnotherMapper.java new file mode 100644 index 000000000..bde4b6223 --- /dev/null +++ b/src/test/java/org/apache/ibatis/submitted/results_id/AnotherMapper.java @@ -0,0 +1,32 @@ +/** + * Copyright 2009-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ibatis.submitted.results_id; + +import java.util.List; + +import org.apache.ibatis.annotations.ResultMap; +import org.apache.ibatis.annotations.Select; + +public interface AnotherMapper { + + @ResultMap("org.apache.ibatis.submitted.results_id.Mapper.userResult") + @Select("select * from users order by uid") + List getUsers(); + + User getUser(Integer id); + +} diff --git a/src/test/java/org/apache/ibatis/submitted/results_id/AnotherMapper.xml b/src/test/java/org/apache/ibatis/submitted/results_id/AnotherMapper.xml new file mode 100644 index 000000000..84e23a364 --- /dev/null +++ b/src/test/java/org/apache/ibatis/submitted/results_id/AnotherMapper.xml @@ -0,0 +1,25 @@ + + + + + + + diff --git a/src/test/java/org/apache/ibatis/submitted/results_id/CreateDB.sql b/src/test/java/org/apache/ibatis/submitted/results_id/CreateDB.sql new file mode 100644 index 000000000..468b8a759 --- /dev/null +++ b/src/test/java/org/apache/ibatis/submitted/results_id/CreateDB.sql @@ -0,0 +1,25 @@ +-- +-- Copyright 2009-2015 the original author or authors. +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- + +drop table users if exists; + +create table users ( + uid int, + name varchar(20) +); + +insert into users (uid, name) values(1, 'User1'); +insert into users (uid, name) values(2, 'User2'); diff --git a/src/test/java/org/apache/ibatis/submitted/results_id/IdConflictMapper.java b/src/test/java/org/apache/ibatis/submitted/results_id/IdConflictMapper.java new file mode 100644 index 000000000..3ebb57965 --- /dev/null +++ b/src/test/java/org/apache/ibatis/submitted/results_id/IdConflictMapper.java @@ -0,0 +1,27 @@ +/** + * Copyright 2009-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ibatis.submitted.results_id; + +import org.apache.ibatis.annotations.Result; +import org.apache.ibatis.annotations.Results; +import org.apache.ibatis.annotations.Select; + +public interface IdConflictMapper { + + @Results(id = "userResult", value = { @Result(id = true, column = "uid", property = "id") }) + @Select("select * from users where uid = #{id}") + User getUserById(Integer id); +} diff --git a/src/test/java/org/apache/ibatis/submitted/results_id/IdConflictMapper.xml b/src/test/java/org/apache/ibatis/submitted/results_id/IdConflictMapper.xml new file mode 100644 index 000000000..8d312121b --- /dev/null +++ b/src/test/java/org/apache/ibatis/submitted/results_id/IdConflictMapper.xml @@ -0,0 +1,26 @@ + + + + + + + + + diff --git a/src/test/java/org/apache/ibatis/submitted/results_id/IdConflictTest.java b/src/test/java/org/apache/ibatis/submitted/results_id/IdConflictTest.java new file mode 100644 index 000000000..a1a7f03fd --- /dev/null +++ b/src/test/java/org/apache/ibatis/submitted/results_id/IdConflictTest.java @@ -0,0 +1,38 @@ +/** + * Copyright 2009-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ibatis.submitted.results_id; + +import org.apache.ibatis.session.Configuration; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +public class IdConflictTest { + + @Rule + public ExpectedException ex = ExpectedException.none(); + + @Test + public void shouldFailOnDuplicatedId() throws Exception { + ex.expect(RuntimeException.class); + ex.expectMessage("Result Maps collection already contains value for org.apache.ibatis.submitted.results_id.IdConflictMapper.userResult"); + + Configuration configuration = new Configuration(); + configuration.addMapper(IdConflictMapper.class); + configuration.getMappedStatements(); + } + +} diff --git a/src/test/java/org/apache/ibatis/submitted/results_id/Mapper.java b/src/test/java/org/apache/ibatis/submitted/results_id/Mapper.java new file mode 100644 index 000000000..1c593344e --- /dev/null +++ b/src/test/java/org/apache/ibatis/submitted/results_id/Mapper.java @@ -0,0 +1,49 @@ +/** + * Copyright 2009-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ibatis.submitted.results_id; + +import org.apache.ibatis.annotations.Arg; +import org.apache.ibatis.annotations.ConstructorArgs; +import org.apache.ibatis.annotations.Result; +import org.apache.ibatis.annotations.ResultMap; +import org.apache.ibatis.annotations.Results; +import org.apache.ibatis.annotations.Select; + +public interface Mapper { + + @Results(id = "userResult", value = { + @Result(id = true, column = "uid", property = "id"), + @Result(column = "name", property = "name") + }) + @Select("select * from users where uid = #{id}") + User getUserById(Integer id); + + @ResultMap("userResult") + @Select("select * from users where name = #{name}") + User getUserByName(String name); + + @Results(id = "userResultConstructor") + @ConstructorArgs({ + @Arg(id = true, column = "uid", javaType = Integer.class), + @Arg(column = "name", javaType = String.class) + }) + @Select("select * from users where uid = #{id}") + User getUserByIdConstructor(Integer id); + + @ResultMap("userResultConstructor") + @Select("select * from users where name = #{name}") + User getUserByNameConstructor(String name); +} diff --git a/src/test/java/org/apache/ibatis/submitted/results_id/ResultsIdTest.java b/src/test/java/org/apache/ibatis/submitted/results_id/ResultsIdTest.java new file mode 100644 index 000000000..99621ea1f --- /dev/null +++ b/src/test/java/org/apache/ibatis/submitted/results_id/ResultsIdTest.java @@ -0,0 +1,108 @@ +/** + * Copyright 2009-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ibatis.submitted.results_id; + +import static org.junit.Assert.*; + +import java.io.Reader; +import java.sql.Connection; +import java.util.List; + +import org.apache.ibatis.io.Resources; +import org.apache.ibatis.jdbc.ScriptRunner; +import org.apache.ibatis.session.SqlSession; +import org.apache.ibatis.session.SqlSessionFactory; +import org.apache.ibatis.session.SqlSessionFactoryBuilder; +import org.junit.BeforeClass; +import org.junit.Test; + +public class ResultsIdTest { + + private static SqlSessionFactory sqlSessionFactory; + + @BeforeClass + public static void setUp() throws Exception { + // create an SqlSessionFactory + Reader reader = Resources.getResourceAsReader("org/apache/ibatis/submitted/results_id/mybatis-config.xml"); + sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader); + reader.close(); + + // populate in-memory database + SqlSession session = sqlSessionFactory.openSession(); + Connection conn = session.getConnection(); + reader = Resources.getResourceAsReader("org/apache/ibatis/submitted/results_id/CreateDB.sql"); + ScriptRunner runner = new ScriptRunner(conn); + runner.setLogWriter(null); + runner.runScript(reader); + reader.close(); + session.close(); + } + + @Test + public void testNamingResults() { + SqlSession sqlSession = sqlSessionFactory.openSession(); + try { + Mapper mapper = sqlSession.getMapper(Mapper.class); + User user = mapper.getUserByName("User2"); + assertEquals(Integer.valueOf(2), user.getId()); + assertEquals("User2", user.getName()); + } finally { + sqlSession.close(); + } + } + + @Test + public void testResultsOnlyForNaming() { + SqlSession sqlSession = sqlSessionFactory.openSession(); + try { + Mapper mapper = sqlSession.getMapper(Mapper.class); + User user = mapper.getUserByNameConstructor("User2"); + assertEquals(Integer.valueOf(2), user.getId()); + assertEquals("User2", user.getName()); + } finally { + sqlSession.close(); + } + } + + @Test + public void testReuseNamedResultsFromAnotherMapper() { + SqlSession sqlSession = sqlSessionFactory.openSession(); + try { + AnotherMapper mapper = sqlSession.getMapper(AnotherMapper.class); + List users = mapper.getUsers(); + assertEquals(2, users.size()); + assertEquals(Integer.valueOf(1), users.get(0).getId()); + assertEquals("User1", users.get(0).getName()); + assertEquals(Integer.valueOf(2), users.get(1).getId()); + assertEquals("User2", users.get(1).getName()); + } finally { + sqlSession.close(); + } + } + + @Test + public void testReuseNamedResultsFromXmlMapper() { + SqlSession sqlSession = sqlSessionFactory.openSession(); + try { + AnotherMapper mapper = sqlSession.getMapper(AnotherMapper.class); + User user = mapper.getUser(1); + assertEquals(Integer.valueOf(1), user.getId()); + assertEquals("User1", user.getName()); + } finally { + sqlSession.close(); + } + } +} diff --git a/src/test/java/org/apache/ibatis/submitted/results_id/User.java b/src/test/java/org/apache/ibatis/submitted/results_id/User.java new file mode 100644 index 000000000..0fbbaa3e8 --- /dev/null +++ b/src/test/java/org/apache/ibatis/submitted/results_id/User.java @@ -0,0 +1,48 @@ +/** + * Copyright 2009-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ibatis.submitted.results_id; + +public class User { + + private Integer id; + private String name; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public User() { + super(); + } + + public User(Integer id, String name) { + super(); + this.id = id; + this.name = name; + } +} diff --git a/src/test/java/org/apache/ibatis/submitted/results_id/mybatis-config.xml b/src/test/java/org/apache/ibatis/submitted/results_id/mybatis-config.xml new file mode 100644 index 000000000..db4946de3 --- /dev/null +++ b/src/test/java/org/apache/ibatis/submitted/results_id/mybatis-config.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + From 01e1453089d36c43c6d72fcf1365a854b11c6924 Mon Sep 17 00:00:00 2001 From: Iwao AVE! Date: Wed, 21 Oct 2015 10:05:09 +0900 Subject: [PATCH 11/30] fixes #494 Allow escaping '}' character in ${} expression. e.g. ${num in {1, 2, 3\}} --- .../ibatis/parsing/GenericTokenParser.java | 33 ++++++++++++++----- .../xml/dynamic/DynamicSqlSourceTest.java | 11 +++++++ .../parsing/GenericTokenParserTest.java | 4 +++ 3 files changed, 39 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/apache/ibatis/parsing/GenericTokenParser.java b/src/main/java/org/apache/ibatis/parsing/GenericTokenParser.java index 09a948e7f..45103195d 100644 --- a/src/main/java/org/apache/ibatis/parsing/GenericTokenParser.java +++ b/src/main/java/org/apache/ibatis/parsing/GenericTokenParser.java @@ -31,26 +31,42 @@ public GenericTokenParser(String openToken, String closeToken, TokenHandler hand } public String parse(String text) { - StringBuilder builder = new StringBuilder(); + final StringBuilder builder = new StringBuilder(); + final StringBuilder expression = new StringBuilder(); if (text != null && text.length() > 0) { char[] src = text.toCharArray(); int offset = 0; + // search open token int start = text.indexOf(openToken, offset); while (start > -1) { if (start > 0 && src[start - 1] == '\\') { - // the variable is escaped. remove the backslash. + // this open token is escaped. remove the backslash and continue. builder.append(src, offset, start - offset - 1).append(openToken); offset = start + openToken.length(); } else { - int end = text.indexOf(closeToken, start); + // found open token. let's search close token. + expression.setLength(0); + builder.append(src, offset, start - offset); + offset = start + openToken.length(); + int end = text.indexOf(closeToken, offset); + while (end > -1) { + if (end > offset && src[end - 1] == '\\') { + // this close token is escaped. remove the backslash and continue. + expression.append(src, offset, end - offset - 1).append(closeToken); + offset = end + closeToken.length(); + end = text.indexOf(closeToken, offset); + } else { + expression.append(src, offset, end - offset); + offset = end + closeToken.length(); + break; + } + } if (end == -1) { - builder.append(src, offset, src.length - offset); + // close token was not found. + builder.append(src, start, src.length - start); offset = src.length; } else { - builder.append(src, offset, start - offset); - offset = start + openToken.length(); - String content = new String(src, offset, end - offset); - builder.append(handler.handleToken(content)); + builder.append(handler.handleToken(expression.toString())); offset = end + closeToken.length(); } } @@ -62,5 +78,4 @@ public String parse(String text) { } return builder.toString(); } - } diff --git a/src/test/java/org/apache/ibatis/builder/xml/dynamic/DynamicSqlSourceTest.java b/src/test/java/org/apache/ibatis/builder/xml/dynamic/DynamicSqlSourceTest.java index bdba78579..07b9bad68 100644 --- a/src/test/java/org/apache/ibatis/builder/xml/dynamic/DynamicSqlSourceTest.java +++ b/src/test/java/org/apache/ibatis/builder/xml/dynamic/DynamicSqlSourceTest.java @@ -317,6 +317,17 @@ public void shouldIterateOnceForEachItemInCollection() throws Exception { assertEquals("__frch_item_2", boundSql.getParameterMappings().get(2).getProperty()); } + @Test + public void shouldHandleOgnlExpression() throws Exception { + final HashMap parameterObject = new HashMap() {{ + put("name", "Steve"); + }}; + final String expected = "Expression test: 3 / yes."; + DynamicSqlSource source = createDynamicSqlSource(new TextSqlNode("Expression test: ${name.indexOf('v')} / ${name in {'Bob', 'Steve'\\} ? 'yes' : 'no'}.")); + BoundSql boundSql = source.getBoundSql(parameterObject); + assertEquals(expected, boundSql.getSql()); + } + @Test public void shouldSkipForEachWhenCollectionIsEmpty() throws Exception { final HashMap parameterObject = new HashMap() {{ diff --git a/src/test/java/org/apache/ibatis/parsing/GenericTokenParserTest.java b/src/test/java/org/apache/ibatis/parsing/GenericTokenParserTest.java index a81f510ea..404062bd9 100644 --- a/src/test/java/org/apache/ibatis/parsing/GenericTokenParserTest.java +++ b/src/test/java/org/apache/ibatis/parsing/GenericTokenParserTest.java @@ -42,6 +42,7 @@ public void shouldDemonstrateGenericTokenReplacement() { put("first_name", "James"); put("initial", "T"); put("last_name", "Kirk"); + put("var{with}brace", "Hiya"); put("", ""); } })); @@ -61,6 +62,9 @@ public void shouldDemonstrateGenericTokenReplacement() { assertEquals("{$$something}JamesTKirk", parser.parse("{$$something}${first_name}${initial}${last_name}")); assertEquals("${", parser.parse("${")); + assertEquals("${\\}", parser.parse("${\\}")); + assertEquals("Hiya", parser.parse("${var{with\\}brace}")); + assertEquals("", parser.parse("${}")); assertEquals("}", parser.parse("}")); assertEquals("Hello ${ this is a test.", parser.parse("Hello ${ this is a test.")); assertEquals("Hello } this is a test.", parser.parse("Hello } this is a test.")); From 656cb5840be9ea1d3292c8b242e3655d1d699641 Mon Sep 17 00:00:00 2001 From: Iwao AVE! Date: Tue, 25 Aug 2015 15:28:42 +0900 Subject: [PATCH 12/30] BoundSql#hasAdditionalParameter should check only the existence of the parent parameter. This should yield more accurate error message in cases like #411 --- .../org/apache/ibatis/mapping/BoundSql.java | 5 +- .../apache/ibatis/mapping/BoundSqlTest.java | 59 +++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 src/test/java/org/apache/ibatis/mapping/BoundSqlTest.java diff --git a/src/main/java/org/apache/ibatis/mapping/BoundSql.java b/src/main/java/org/apache/ibatis/mapping/BoundSql.java index c0bd094a3..aa45f6ac4 100644 --- a/src/main/java/org/apache/ibatis/mapping/BoundSql.java +++ b/src/main/java/org/apache/ibatis/mapping/BoundSql.java @@ -20,6 +20,7 @@ import java.util.Map; import org.apache.ibatis.reflection.MetaObject; +import org.apache.ibatis.reflection.property.PropertyTokenizer; import org.apache.ibatis.session.Configuration; /** @@ -62,7 +63,9 @@ public Object getParameterObject() { } public boolean hasAdditionalParameter(String name) { - return metaParameters.hasGetter(name); + PropertyTokenizer prop = new PropertyTokenizer(name); + String indexedName = prop.getIndexedName(); + return additionalParameters.containsKey(indexedName); } public void setAdditionalParameter(String name, Object value) { diff --git a/src/test/java/org/apache/ibatis/mapping/BoundSqlTest.java b/src/test/java/org/apache/ibatis/mapping/BoundSqlTest.java new file mode 100644 index 000000000..439fbbf94 --- /dev/null +++ b/src/test/java/org/apache/ibatis/mapping/BoundSqlTest.java @@ -0,0 +1,59 @@ +/** + * Copyright 2009-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ibatis.mapping; + +import static org.junit.Assert.*; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.ibatis.session.Configuration; +import org.junit.Test; + +public class BoundSqlTest { + + @Test + public void testHasAdditionalParameter() throws Exception { + List params = Collections.emptyList(); + BoundSql boundSql = new BoundSql(new Configuration(), "some sql", params, new Object()); + + Map map = new HashMap(); + map.put("key1", "value1"); + boundSql.setAdditionalParameter("map", map); + + Person bean = new Person(); + bean.id = 1; + boundSql.setAdditionalParameter("person", bean); + + assertFalse(boundSql.hasAdditionalParameter("pet")); + assertFalse(boundSql.hasAdditionalParameter("pet.name")); + + assertTrue(boundSql.hasAdditionalParameter("map")); + assertTrue(boundSql.hasAdditionalParameter("map.key1")); + assertTrue("should return true even if the child property does not exists.", boundSql.hasAdditionalParameter("map.key2")); + + assertTrue(boundSql.hasAdditionalParameter("person")); + assertTrue(boundSql.hasAdditionalParameter("person.id")); + assertTrue("should return true even if the child property does not exists.", boundSql.hasAdditionalParameter("person.name")); + } + + public static class Person { + public Integer id; + } + +} From 232ae0a39ea4c338a4905d987603a185a4aaa434 Mon Sep 17 00:00:00 2001 From: Iwao AVE! Date: Tue, 25 Aug 2015 15:37:20 +0900 Subject: [PATCH 13/30] Close #411 with a test case. See the previous commit [263b47e] . --- .../ibatis/submitted/foreach/ForEachTest.java | 21 +++++++++++++++++++ .../ibatis/submitted/foreach/Mapper.java | 1 + .../ibatis/submitted/foreach/Mapper.xml | 7 +++++++ 3 files changed, 29 insertions(+) diff --git a/src/test/java/org/apache/ibatis/submitted/foreach/ForEachTest.java b/src/test/java/org/apache/ibatis/submitted/foreach/ForEachTest.java index 2ed0bf31e..1a8548335 100644 --- a/src/test/java/org/apache/ibatis/submitted/foreach/ForEachTest.java +++ b/src/test/java/org/apache/ibatis/submitted/foreach/ForEachTest.java @@ -18,8 +18,10 @@ import java.io.Reader; import java.sql.Connection; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import org.apache.ibatis.exceptions.PersistenceException; import org.apache.ibatis.io.Resources; import org.apache.ibatis.jdbc.ScriptRunner; import org.apache.ibatis.session.SqlSession; @@ -27,12 +29,17 @@ import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.Assert; import org.junit.BeforeClass; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; public class ForEachTest { private static SqlSessionFactory sqlSessionFactory; + @Rule + public ExpectedException ex = ExpectedException.none(); + @BeforeClass public static void setUp() throws Exception { // create a SqlSessionFactory @@ -124,4 +131,18 @@ public void nullItemInContext() { } } + @Test + public void shouldReportMissingPropertyName() { + ex.expect(PersistenceException.class); + ex.expectMessage("There is no getter for property named 'idd' in 'class org.apache.ibatis.submitted.foreach.User'"); + + SqlSession sqlSession = sqlSessionFactory.openSession(); + try { + Mapper mapper = sqlSession.getMapper(Mapper.class); + mapper.typoInItemProperty(Arrays.asList(new User())); + } finally { + sqlSession.close(); + } + } + } diff --git a/src/test/java/org/apache/ibatis/submitted/foreach/Mapper.java b/src/test/java/org/apache/ibatis/submitted/foreach/Mapper.java index d8a1037a4..cca0bdf30 100644 --- a/src/test/java/org/apache/ibatis/submitted/foreach/Mapper.java +++ b/src/test/java/org/apache/ibatis/submitted/foreach/Mapper.java @@ -27,4 +27,5 @@ public interface Mapper { String selectWithNullItemCheck(List users); + int typoInItemProperty(List users); } diff --git a/src/test/java/org/apache/ibatis/submitted/foreach/Mapper.xml b/src/test/java/org/apache/ibatis/submitted/foreach/Mapper.xml index 0404b85ff..63d133833 100644 --- a/src/test/java/org/apache/ibatis/submitted/foreach/Mapper.xml +++ b/src/test/java/org/apache/ibatis/submitted/foreach/Mapper.xml @@ -62,4 +62,11 @@ + + insert into users (id, name) values + + (#{item.idd}, #{item.name}) + + + From a9d7ed0cf426b48fbbeca62e8717050ed69ca3b7 Mon Sep 17 00:00:00 2001 From: Eduardo Macarron Date: Wed, 10 Feb 2016 21:41:08 +0100 Subject: [PATCH 14/30] #547 Merged into 3.3.x branch --- .../executor/keygen/Jdbc3KeyGenerator.java | 37 ++++++--- .../ibatis/submitted/keygen/Country.java | 63 +++++++++++++++ .../submitted/keygen/CountryMapper.java | 24 ++++++ .../ibatis/submitted/keygen/CountryMapper.xml | 28 +++++++ .../ibatis/submitted/keygen/CreateDB.sql | 23 ++++++ .../keygen/Jdbc3KeyGeneratorTest.java | 76 +++++++++++++++++++ .../ibatis/submitted/keygen/MapperConfig.xml | 38 ++++++++++ 7 files changed, 280 insertions(+), 9 deletions(-) create mode 100644 src/test/java/org/apache/ibatis/submitted/keygen/Country.java create mode 100644 src/test/java/org/apache/ibatis/submitted/keygen/CountryMapper.java create mode 100644 src/test/java/org/apache/ibatis/submitted/keygen/CountryMapper.xml create mode 100644 src/test/java/org/apache/ibatis/submitted/keygen/CreateDB.sql create mode 100644 src/test/java/org/apache/ibatis/submitted/keygen/Jdbc3KeyGeneratorTest.java create mode 100644 src/test/java/org/apache/ibatis/submitted/keygen/MapperConfig.xml diff --git a/src/main/java/org/apache/ibatis/executor/keygen/Jdbc3KeyGenerator.java b/src/main/java/org/apache/ibatis/executor/keygen/Jdbc3KeyGenerator.java index eb28acc90..5b17bcdd7 100644 --- a/src/main/java/org/apache/ibatis/executor/keygen/Jdbc3KeyGenerator.java +++ b/src/main/java/org/apache/ibatis/executor/keygen/Jdbc3KeyGenerator.java @@ -19,14 +19,14 @@ import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Statement; -import java.util.ArrayList; -import java.util.List; +import java.util.*; import org.apache.ibatis.executor.Executor; import org.apache.ibatis.executor.ExecutorException; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.reflection.MetaObject; import org.apache.ibatis.session.Configuration; +import org.apache.ibatis.type.JdbcType; import org.apache.ibatis.type.TypeHandler; import org.apache.ibatis.type.TypeHandlerRegistry; @@ -42,12 +42,10 @@ public void processBefore(Executor executor, MappedStatement ms, Statement stmt, @Override public void processAfter(Executor executor, MappedStatement ms, Statement stmt, Object parameter) { - List parameters = new ArrayList(); - parameters.add(parameter); - processBatch(ms, stmt, parameters); + processBatch(ms, stmt, getParameters(parameter)); } - public void processBatch(MappedStatement ms, Statement stmt, List parameters) { + public void processBatch(MappedStatement ms, Statement stmt, Collection parameters) { ResultSet rs = null; try { rs = stmt.getGeneratedKeys(); @@ -64,7 +62,7 @@ public void processBatch(MappedStatement ms, Statement stmt, List parame } final MetaObject metaParam = configuration.newMetaObject(parameter); if (typeHandlers == null) { - typeHandlers = getTypeHandlers(typeHandlerRegistry, metaParam, keyProperties); + typeHandlers = getTypeHandlers(typeHandlerRegistry, metaParam, keyProperties, rsmd); } populateKeys(rs, metaParam, keyProperties, typeHandlers); } @@ -82,12 +80,33 @@ public void processBatch(MappedStatement ms, Statement stmt, List parame } } - private TypeHandler[] getTypeHandlers(TypeHandlerRegistry typeHandlerRegistry, MetaObject metaParam, String[] keyProperties) { + private Collection getParameters(Object parameter) { + Collection parameters = null; + if (parameter instanceof Collection) { + parameters = (Collection) parameter; + } else if (parameter instanceof Map) { + Map parameterMap = (Map) parameter; + if (parameterMap.containsKey("collection")) { + parameters = (Collection) parameterMap.get("collection"); + } else if (parameterMap.containsKey("list")) { + parameters = (List) parameterMap.get("list"); + } else if (parameterMap.containsKey("array")) { + parameters = Arrays.asList((Object[]) parameterMap.get("array")); + } + } + if (parameters == null) { + parameters = new ArrayList(); + parameters.add(parameter); + } + return parameters; + } + + private TypeHandler[] getTypeHandlers(TypeHandlerRegistry typeHandlerRegistry, MetaObject metaParam, String[] keyProperties, ResultSetMetaData rsmd) throws SQLException { TypeHandler[] typeHandlers = new TypeHandler[keyProperties.length]; for (int i = 0; i < keyProperties.length; i++) { if (metaParam.hasSetter(keyProperties[i])) { Class keyPropertyType = metaParam.getSetterType(keyProperties[i]); - TypeHandler th = typeHandlerRegistry.getTypeHandler(keyPropertyType); + TypeHandler th = typeHandlerRegistry.getTypeHandler(keyPropertyType, JdbcType.forCode(rsmd.getColumnType(i + 1))); typeHandlers[i] = th; } } diff --git a/src/test/java/org/apache/ibatis/submitted/keygen/Country.java b/src/test/java/org/apache/ibatis/submitted/keygen/Country.java new file mode 100644 index 000000000..dbcc73cdc --- /dev/null +++ b/src/test/java/org/apache/ibatis/submitted/keygen/Country.java @@ -0,0 +1,63 @@ +/** + * Copyright 2009-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ibatis.submitted.keygen; + +/** + * @author liuzh + */ +public class Country { + private Integer id; + private String countryname; + private String countrycode; + + public Country() { + } + + public Country(String countryname, String countrycode) { + this.countryname = countryname; + this.countrycode = countrycode; + } + + public Country(Integer id, String countryname, String countrycode) { + this.id = id; + this.countryname = countryname; + this.countrycode = countrycode; + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getCountryname() { + return countryname; + } + + public void setCountryname(String countryname) { + this.countryname = countryname; + } + + public String getCountrycode() { + return countrycode; + } + + public void setCountrycode(String countrycode) { + this.countrycode = countrycode; + } +} diff --git a/src/test/java/org/apache/ibatis/submitted/keygen/CountryMapper.java b/src/test/java/org/apache/ibatis/submitted/keygen/CountryMapper.java new file mode 100644 index 000000000..325ffd6d8 --- /dev/null +++ b/src/test/java/org/apache/ibatis/submitted/keygen/CountryMapper.java @@ -0,0 +1,24 @@ +/** + * Copyright 2009-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ibatis.submitted.keygen; + +import java.util.List; + +public interface CountryMapper { + + int insertList(List countries); + +} diff --git a/src/test/java/org/apache/ibatis/submitted/keygen/CountryMapper.xml b/src/test/java/org/apache/ibatis/submitted/keygen/CountryMapper.xml new file mode 100644 index 000000000..e201dce49 --- /dev/null +++ b/src/test/java/org/apache/ibatis/submitted/keygen/CountryMapper.xml @@ -0,0 +1,28 @@ + + + + + + insert into country (countryname,countrycode) + values + + (#{country.countryname},#{country.countrycode}) + + + diff --git a/src/test/java/org/apache/ibatis/submitted/keygen/CreateDB.sql b/src/test/java/org/apache/ibatis/submitted/keygen/CreateDB.sql new file mode 100644 index 000000000..55a4dd6b4 --- /dev/null +++ b/src/test/java/org/apache/ibatis/submitted/keygen/CreateDB.sql @@ -0,0 +1,23 @@ +-- +-- Copyright 2009-2016 the original author or authors. +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- + +DROP TABLE country IF EXISTS; + +CREATE TABLE country ( + Id int IDENTITY, + countryname varchar(255) DEFAULT NULL, + countrycode varchar(255) DEFAULT NULL, +); diff --git a/src/test/java/org/apache/ibatis/submitted/keygen/Jdbc3KeyGeneratorTest.java b/src/test/java/org/apache/ibatis/submitted/keygen/Jdbc3KeyGeneratorTest.java new file mode 100644 index 000000000..2f3fbd326 --- /dev/null +++ b/src/test/java/org/apache/ibatis/submitted/keygen/Jdbc3KeyGeneratorTest.java @@ -0,0 +1,76 @@ +/** + * Copyright 2009-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ibatis.submitted.keygen; + +import static org.junit.Assert.*; + +import java.io.Reader; +import java.sql.Connection; +import java.util.ArrayList; +import java.util.List; + +import org.apache.ibatis.io.Resources; +import org.apache.ibatis.jdbc.ScriptRunner; +import org.apache.ibatis.session.SqlSession; +import org.apache.ibatis.session.SqlSessionFactory; +import org.apache.ibatis.session.SqlSessionFactoryBuilder; +import org.junit.BeforeClass; +import org.junit.Test; + +/** + * @author liuzh + */ +public class Jdbc3KeyGeneratorTest { + + private static SqlSessionFactory sqlSessionFactory; + + @BeforeClass + public static void setUp() throws Exception { + // create an SqlSessionFactory + Reader reader = Resources.getResourceAsReader("org/apache/ibatis/submitted/keygen/MapperConfig.xml"); + sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader); + reader.close(); + + // populate in-memory database + SqlSession session = sqlSessionFactory.openSession(); + Connection conn = session.getConnection(); + reader = Resources.getResourceAsReader("org/apache/ibatis/submitted/keygen/CreateDB.sql"); + ScriptRunner runner = new ScriptRunner(conn); + runner.setLogWriter(null); + runner.runScript(reader); + reader.close(); + session.close(); + } + + @Test + public void shouldInsertListAndRetrieveId() throws Exception { + SqlSession sqlSession = sqlSessionFactory.openSession(); + try { + CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); + List countries = new ArrayList(); + countries.add(new Country("China", "CN")); + countries.add(new Country("United Kiongdom", "GB")); + countries.add(new Country("United States of America", "US")); + mapper.insertList(countries); + for (Country country : countries) { + assertNotNull(country.getId()); + } + } finally { + sqlSession.rollback(); + sqlSession.close(); + } + } +} diff --git a/src/test/java/org/apache/ibatis/submitted/keygen/MapperConfig.xml b/src/test/java/org/apache/ibatis/submitted/keygen/MapperConfig.xml new file mode 100644 index 000000000..2425f5801 --- /dev/null +++ b/src/test/java/org/apache/ibatis/submitted/keygen/MapperConfig.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + From 95895546e6ac57d466c4915c233f36c980075f35 Mon Sep 17 00:00:00 2001 From: Eduardo Macarron Date: Wed, 10 Feb 2016 22:03:33 +0100 Subject: [PATCH 15/30] #39 Merged into 3.3.x branch --- .../resultset/DefaultResultSetHandler.java | 35 +++++++------ .../submitted/nestedresulthandler/Item.java | 10 ++++ .../submitted/nestedresulthandler/Mapper.java | 1 + .../submitted/nestedresulthandler/Mapper.xml | 19 +++++++ .../NestedResultHandlerTest.java | 20 ++++++++ .../submitted/nestedresulthandler/Person.java | 14 +++++- .../nestedresulthandler/PersonItemPair.java | 50 +++++++++++++++++++ 7 files changed, 130 insertions(+), 19 deletions(-) create mode 100644 src/test/java/org/apache/ibatis/submitted/nestedresulthandler/PersonItemPair.java diff --git a/src/main/java/org/apache/ibatis/executor/resultset/DefaultResultSetHandler.java b/src/main/java/org/apache/ibatis/executor/resultset/DefaultResultSetHandler.java index 6c08f9b84..bc6e83d85 100644 --- a/src/main/java/org/apache/ibatis/executor/resultset/DefaultResultSetHandler.java +++ b/src/main/java/org/apache/ibatis/executor/resultset/DefaultResultSetHandler.java @@ -60,6 +60,7 @@ /** * @author Clinton Begin * @author Eduardo Macarron + * @author Iwao AVE! */ public class DefaultResultSetHandler implements ResultSetHandler { @@ -78,7 +79,7 @@ public class DefaultResultSetHandler implements ResultSetHandler { // nested resultmaps private final Map nestedResultObjects = new HashMap(); - private final Map ancestorObjects = new HashMap(); + private final Map ancestorObjects = new HashMap(); private final Map ancestorColumnPrefix = new HashMap(); // multiple resultsets @@ -755,9 +756,9 @@ private void handleRowValuesForNestedResultMap(ResultSetWrapper rsw, ResultMap r nestedResultObjects.clear(); storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet()); } - rowValue = getRowValue(rsw, discriminatedResultMap, rowKey, rowKey, null, partialObject); + rowValue = getRowValue(rsw, discriminatedResultMap, rowKey, null, partialObject); } else { - rowValue = getRowValue(rsw, discriminatedResultMap, rowKey, rowKey, null, partialObject); + rowValue = getRowValue(rsw, discriminatedResultMap, rowKey, null, partialObject); if (partialObject == null) { storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet()); } @@ -772,14 +773,14 @@ private void handleRowValuesForNestedResultMap(ResultSetWrapper rsw, ResultMap r // GET VALUE FROM ROW FOR NESTED RESULT MAP // - private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap, CacheKey combinedKey, CacheKey absoluteKey, String columnPrefix, Object partialObject) throws SQLException { + private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap, CacheKey combinedKey, String columnPrefix, Object partialObject) throws SQLException { final String resultMapId = resultMap.getId(); Object resultObject = partialObject; if (resultObject != null) { final MetaObject metaObject = configuration.newMetaObject(resultObject); - putAncestor(absoluteKey, resultObject, resultMapId, columnPrefix); + putAncestor(resultObject, resultMapId, columnPrefix); applyNestedResultMappings(rsw, resultMap, metaObject, columnPrefix, combinedKey, false); - ancestorObjects.remove(absoluteKey); + ancestorObjects.remove(resultMapId); } else { final ResultLoaderMap lazyLoader = new ResultLoaderMap(); resultObject = createResultObject(rsw, resultMap, lazyLoader, columnPrefix); @@ -790,9 +791,9 @@ private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap, CacheKey c foundValues = applyAutomaticMappings(rsw, resultMap, metaObject, columnPrefix) || foundValues; } foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, columnPrefix) || foundValues; - putAncestor(absoluteKey, resultObject, resultMapId, columnPrefix); + putAncestor(resultObject, resultMapId, columnPrefix); foundValues = applyNestedResultMappings(rsw, resultMap, metaObject, columnPrefix, combinedKey, true) || foundValues; - ancestorObjects.remove(absoluteKey); + ancestorObjects.remove(resultMapId); foundValues = lazyLoader.size() > 0 || foundValues; resultObject = foundValues ? resultObject : null; } @@ -803,11 +804,11 @@ private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap, CacheKey c return resultObject; } - private void putAncestor(CacheKey rowKey, Object resultObject, String resultMapId, String columnPrefix) { + private void putAncestor(Object resultObject, String resultMapId, String columnPrefix) { if (!ancestorColumnPrefix.containsKey(resultMapId)) { ancestorColumnPrefix.put(resultMapId, columnPrefix); } - ancestorObjects.put(rowKey, resultObject); + ancestorObjects.put(resultMapId, resultObject); } // @@ -822,24 +823,19 @@ private boolean applyNestedResultMappings(ResultSetWrapper rsw, ResultMap result try { final String columnPrefix = getColumnPrefix(parentPrefix, resultMapping); final ResultMap nestedResultMap = getNestedResultMap(rsw.getResultSet(), nestedResultMapId, columnPrefix); - CacheKey rowKey = null; - Object ancestorObject = null; - if (ancestorColumnPrefix.containsKey(nestedResultMapId)) { - rowKey = createRowKey(nestedResultMap, rsw, ancestorColumnPrefix.get(nestedResultMapId)); - ancestorObject = ancestorObjects.get(rowKey); - } + Object ancestorObject = ancestorObjects.get(nestedResultMapId); if (ancestorObject != null) { if (newObject) { linkObjects(metaObject, resultMapping, ancestorObject); // issue #385 } } else { - rowKey = createRowKey(nestedResultMap, rsw, columnPrefix); + final CacheKey rowKey = createRowKey(nestedResultMap, rsw, columnPrefix); final CacheKey combinedKey = combineKeys(rowKey, parentRowKey); Object rowValue = nestedResultObjects.get(combinedKey); boolean knownValue = (rowValue != null); instantiateCollectionPropertyIfAppropriate(resultMapping, metaObject); // mandatory if (anyNotNullColumnHasValue(resultMapping, columnPrefix, rsw.getResultSet())) { - rowValue = getRowValue(rsw, nestedResultMap, combinedKey, rowKey, columnPrefix, rowValue); + rowValue = getRowValue(rsw, nestedResultMap, combinedKey, columnPrefix, rowValue); if (rowValue != null && !knownValue) { linkObjects(metaObject, resultMapping, rowValue); foundValues = true; @@ -903,6 +899,9 @@ private CacheKey createRowKey(ResultMap resultMap, ResultSetWrapper rsw, String } else { createRowKeyForMappedProperties(resultMap, rsw, cacheKey, resultMappings, columnPrefix); } + if (cacheKey.getUpdateCount() < 2) { + return CacheKey.NULL_CACHE_KEY; + } return cacheKey; } diff --git a/src/test/java/org/apache/ibatis/submitted/nestedresulthandler/Item.java b/src/test/java/org/apache/ibatis/submitted/nestedresulthandler/Item.java index 70ca2e558..6a3b1d11e 100644 --- a/src/test/java/org/apache/ibatis/submitted/nestedresulthandler/Item.java +++ b/src/test/java/org/apache/ibatis/submitted/nestedresulthandler/Item.java @@ -19,6 +19,16 @@ public class Item { private Integer id; private String name; + public String toString(){ + return new StringBuilder() + .append("Item(") + .append(id) + .append(", ") + .append(name) + .append(" )") + .toString(); + } + public Integer getId() { return id; } diff --git a/src/test/java/org/apache/ibatis/submitted/nestedresulthandler/Mapper.java b/src/test/java/org/apache/ibatis/submitted/nestedresulthandler/Mapper.java index b786e03ff..fab97238f 100644 --- a/src/test/java/org/apache/ibatis/submitted/nestedresulthandler/Mapper.java +++ b/src/test/java/org/apache/ibatis/submitted/nestedresulthandler/Mapper.java @@ -20,4 +20,5 @@ public interface Mapper { List getPersons(); List getPersonsWithItemsOrdered(); + List getPersonItemPairs(); } diff --git a/src/test/java/org/apache/ibatis/submitted/nestedresulthandler/Mapper.xml b/src/test/java/org/apache/ibatis/submitted/nestedresulthandler/Mapper.xml index 380179c44..b5eb012ee 100644 --- a/src/test/java/org/apache/ibatis/submitted/nestedresulthandler/Mapper.xml +++ b/src/test/java/org/apache/ibatis/submitted/nestedresulthandler/Mapper.xml @@ -40,4 +40,23 @@ where p.id = i.owner order by i.name + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/java/org/apache/ibatis/submitted/nestedresulthandler/NestedResultHandlerTest.java b/src/test/java/org/apache/ibatis/submitted/nestedresulthandler/NestedResultHandlerTest.java index c93e9eca0..0dbef4780 100644 --- a/src/test/java/org/apache/ibatis/submitted/nestedresulthandler/NestedResultHandlerTest.java +++ b/src/test/java/org/apache/ibatis/submitted/nestedresulthandler/NestedResultHandlerTest.java @@ -150,4 +150,24 @@ public void testGetPersonOrderedByItem() { } } + @Test //reopen issue 39? (not a bug?) + public void testGetPersonItemPairs(){ + SqlSession sqlSession = sqlSessionFactory.openSession(); + try{ + Mapper mapper = sqlSession.getMapper(Mapper.class); + List pairs = mapper.getPersonItemPairs(); + + Assert.assertNotNull( pairs ); +// System.out.println( new StringBuilder().append("selected pairs: ").append(pairs) ); + + Assert.assertEquals(5, pairs.size() ); + Assert.assertNotNull(pairs.get(0).getPerson()); + Assert.assertEquals(pairs.get(0).getPerson().getId(), Integer.valueOf(1)); + Assert.assertNotNull(pairs.get(0).getItem()); + Assert.assertEquals( pairs.get(0).getItem().getId(), Integer.valueOf(1)); + } finally{ + sqlSession.close(); + } + } + } diff --git a/src/test/java/org/apache/ibatis/submitted/nestedresulthandler/Person.java b/src/test/java/org/apache/ibatis/submitted/nestedresulthandler/Person.java index d76b66cf3..8e5ad3f61 100644 --- a/src/test/java/org/apache/ibatis/submitted/nestedresulthandler/Person.java +++ b/src/test/java/org/apache/ibatis/submitted/nestedresulthandler/Person.java @@ -22,7 +22,19 @@ public class Person { private Integer id; private String name; - private List items=new ArrayList(); + private List items=new ArrayList(); + + public String toString(){ + return new StringBuilder() + .append("Person(") + .append(id) + .append(", ") + .append(name) + .append(", ") + .append(items) + .append(" )") + .toString(); + } public Integer getId() { return id; diff --git a/src/test/java/org/apache/ibatis/submitted/nestedresulthandler/PersonItemPair.java b/src/test/java/org/apache/ibatis/submitted/nestedresulthandler/PersonItemPair.java new file mode 100644 index 000000000..60f53a195 --- /dev/null +++ b/src/test/java/org/apache/ibatis/submitted/nestedresulthandler/PersonItemPair.java @@ -0,0 +1,50 @@ +/** + * Copyright 2009-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ibatis.submitted.nestedresulthandler; + +/** + * Created by eyal on 12/9/2015. + */ +public class PersonItemPair { + private Person person; + private Item item; + + public String toString(){ + return new StringBuilder() + .append("PersonItemPair(") + .append(person) + .append(", ") + .append(item) + .append(" )") + .toString(); + } + + public Person getPerson() { + return person; + } + + public void setPerson(Person person) { + this.person = person; + } + + public Item getItem() { + return item; + } + + public void setItem(Item item) { + this.item = item; + } +} From ff8db5c314a598564cb5bafb62db6dbbcd5699bb Mon Sep 17 00:00:00 2001 From: Eduardo Macarron Date: Wed, 10 Feb 2016 22:05:30 +0100 Subject: [PATCH 16/30] #421 Merged into 3.3.x branch --- .../resultset/DefaultResultSetHandler.java | 2 +- .../ibatis/submitted/emptycollection/Dao.java | 24 +++++ .../ibatis/submitted/emptycollection/Dao.xml | 39 ++++++++ .../submitted/emptycollection/DaoTest.java | 93 +++++++++++++++++++ .../submitted/emptycollection/TodoItem.java | 44 +++++++++ .../submitted/emptycollection/TodoLists.java | 47 ++++++++++ .../emptycollection/mybatis-config.xml | 21 +++++ 7 files changed, 269 insertions(+), 1 deletion(-) create mode 100644 src/test/java/org/apache/ibatis/submitted/emptycollection/Dao.java create mode 100644 src/test/java/org/apache/ibatis/submitted/emptycollection/Dao.xml create mode 100644 src/test/java/org/apache/ibatis/submitted/emptycollection/DaoTest.java create mode 100644 src/test/java/org/apache/ibatis/submitted/emptycollection/TodoItem.java create mode 100644 src/test/java/org/apache/ibatis/submitted/emptycollection/TodoLists.java create mode 100644 src/test/java/org/apache/ibatis/submitted/emptycollection/mybatis-config.xml diff --git a/src/main/java/org/apache/ibatis/executor/resultset/DefaultResultSetHandler.java b/src/main/java/org/apache/ibatis/executor/resultset/DefaultResultSetHandler.java index bc6e83d85..4cc7721b5 100644 --- a/src/main/java/org/apache/ibatis/executor/resultset/DefaultResultSetHandler.java +++ b/src/main/java/org/apache/ibatis/executor/resultset/DefaultResultSetHandler.java @@ -394,7 +394,7 @@ private boolean applyPropertyMappings(ResultSetWrapper rsw, ResultMap resultMap, && (value != null || (configuration.isCallSettersOnNulls() && !metaObject.getSetterType(property).isPrimitive()))) { metaObject.setValue(property, value); } - if (value != null || value == DEFERED) { + if (property != null && (value != null || value == DEFERED)) { foundValues = true; } } diff --git a/src/test/java/org/apache/ibatis/submitted/emptycollection/Dao.java b/src/test/java/org/apache/ibatis/submitted/emptycollection/Dao.java new file mode 100644 index 000000000..f7aa7fd83 --- /dev/null +++ b/src/test/java/org/apache/ibatis/submitted/emptycollection/Dao.java @@ -0,0 +1,24 @@ +/** + * Copyright 2009-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ibatis.submitted.emptycollection; + +import java.util.List; + +interface Dao { + List selectWithEmptyList(); + List selectWithNonEmptyList(); + List selectWithNonEmptyList_noCollectionId(); +} diff --git a/src/test/java/org/apache/ibatis/submitted/emptycollection/Dao.xml b/src/test/java/org/apache/ibatis/submitted/emptycollection/Dao.xml new file mode 100644 index 000000000..d3c8766d6 --- /dev/null +++ b/src/test/java/org/apache/ibatis/submitted/emptycollection/Dao.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/java/org/apache/ibatis/submitted/emptycollection/DaoTest.java b/src/test/java/org/apache/ibatis/submitted/emptycollection/DaoTest.java new file mode 100644 index 000000000..e42c823f6 --- /dev/null +++ b/src/test/java/org/apache/ibatis/submitted/emptycollection/DaoTest.java @@ -0,0 +1,93 @@ +/** + * Copyright 2009-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ibatis.submitted.emptycollection; + +import java.io.Reader; +import java.sql.Connection; +import java.util.List; + +import org.apache.ibatis.io.Resources; +import org.apache.ibatis.jdbc.ScriptRunner; +import org.apache.ibatis.session.SqlSession; +import org.apache.ibatis.session.SqlSessionFactory; +import org.apache.ibatis.session.SqlSessionFactoryBuilder; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class DaoTest { + private Dao dao; + private SqlSession sqlSession; + + @Before + public void setUp() throws Exception { + Reader reader = Resources.getResourceAsReader("org/apache/ibatis/submitted/emptycollection/mybatis-config.xml"); + SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader); + reader.close(); + + sqlSession = sqlSessionFactory.openSession(); + Connection conn = sqlSession.getConnection(); + ScriptRunner runner = new ScriptRunner(conn); + runner.setLogWriter(null); + dao = sqlSession.getMapper(Dao.class); + } + + @After + public void tearDown() throws Exception { + sqlSession.close(); + } + + @Test + public void testWithEmptyList() throws Exception { + final List actual = dao.selectWithEmptyList(); + Assert.assertEquals(1, actual.size()); + final List todoItems = actual.get(0).getTodoItems(); + Assert.assertEquals("expect " + todoItems + " to be empty", 0, todoItems.size()); + } + + @Test + public void testWithNonEmptyList() throws Exception { + final List actual = dao.selectWithNonEmptyList(); + checkNonEmptyList(actual); + } + + @Test + public void testWithNonEmptyList_noCollectionId() throws Exception { + final List actual = dao.selectWithNonEmptyList_noCollectionId(); + + checkNonEmptyList(actual); + } + + private void checkNonEmptyList(final List actual) { +// Assert.assertEquals("[List(1)=[a description(1), a 2nd description(2)], List(2)=[a description(1)]]", actual.toString()); + Assert.assertEquals(2, actual.size()); + + Assert.assertEquals(2, actual.get(0).getTodoItems().size()); + Assert.assertEquals(1, actual.get(0).getTodoItems().get(0).getOrder()); + Assert.assertEquals("a description", actual.get(0).getTodoItems().get(0).getDescription().trim()); + Assert.assertEquals(2, actual.get(0).getTodoItems().get(1).getOrder()); + Assert.assertEquals("a 2nd description", actual.get(0).getTodoItems().get(1).getDescription().trim()); + + Assert.assertEquals(1, actual.get(1).getTodoItems().size()); + Assert.assertEquals(1, actual.get(1).getTodoItems().get(0).getOrder()); + Assert.assertEquals("a description", actual.get(0).getTodoItems().get(0).getDescription().trim()); + + // We should have gotten three item objects. The first item from the first list and the first item from + // the second list have identical properties, but they should be distinct objects + Assert.assertNotSame(actual.get(0).getTodoItems().get(0), actual.get(1).getTodoItems().get(0)); + } +} \ No newline at end of file diff --git a/src/test/java/org/apache/ibatis/submitted/emptycollection/TodoItem.java b/src/test/java/org/apache/ibatis/submitted/emptycollection/TodoItem.java new file mode 100644 index 000000000..71a30351a --- /dev/null +++ b/src/test/java/org/apache/ibatis/submitted/emptycollection/TodoItem.java @@ -0,0 +1,44 @@ +/** + * Copyright 2009-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ibatis.submitted.emptycollection; + +public class TodoItem { + + @Override + public String toString() { + return "TodoItem [order=" + order + ", description=" + description + "]"; + } + + private int order; + private String description; + + public int getOrder() { + return order; + } + + public void setOrder(int order) { + this.order = order; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + +} diff --git a/src/test/java/org/apache/ibatis/submitted/emptycollection/TodoLists.java b/src/test/java/org/apache/ibatis/submitted/emptycollection/TodoLists.java new file mode 100644 index 000000000..b2e0b1b4c --- /dev/null +++ b/src/test/java/org/apache/ibatis/submitted/emptycollection/TodoLists.java @@ -0,0 +1,47 @@ +/** + * Copyright 2009-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ibatis.submitted.emptycollection; + +import java.util.List; + +public class TodoLists { + + @Override + public String toString() { + return "TodoLists [id=" + id + ", todoItems=" + todoItems + "]"; + } + + private int id; + + private List todoItems; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public List getTodoItems() { + return todoItems; + } + + public void setTodoItems(List todoItems) { + this.todoItems = todoItems; + } + +} diff --git a/src/test/java/org/apache/ibatis/submitted/emptycollection/mybatis-config.xml b/src/test/java/org/apache/ibatis/submitted/emptycollection/mybatis-config.xml new file mode 100644 index 000000000..871a4454e --- /dev/null +++ b/src/test/java/org/apache/ibatis/submitted/emptycollection/mybatis-config.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 599dcf9b94d2d5e69d87a568f19c89ac8805a96d Mon Sep 17 00:00:00 2001 From: Eduardo Macarron Date: Wed, 10 Feb 2016 22:16:03 +0100 Subject: [PATCH 17/30] #574 Merged into 3.3.x branch --- .../resultset/DefaultResultSetHandler.java | 86 +++++++++++++------ 1 file changed, 61 insertions(+), 25 deletions(-) diff --git a/src/main/java/org/apache/ibatis/executor/resultset/DefaultResultSetHandler.java b/src/main/java/org/apache/ibatis/executor/resultset/DefaultResultSetHandler.java index 4cc7721b5..d1b4bad17 100644 --- a/src/main/java/org/apache/ibatis/executor/resultset/DefaultResultSetHandler.java +++ b/src/main/java/org/apache/ibatis/executor/resultset/DefaultResultSetHandler.java @@ -86,11 +86,27 @@ public class DefaultResultSetHandler implements ResultSetHandler { private final Map nextResultMaps = new HashMap(); private final Map> pendingRelations = new HashMap>(); + // Cached Automappings + private final Map> autoMappingsCache = new HashMap>(); + private static class PendingRelation { public MetaObject metaObject; public ResultMapping propertyMapping; } + private static class UnMappedColumAutoMapping { + private final String column; + private final String property; + private final TypeHandler typeHandler; + private final boolean primitive; + public UnMappedColumAutoMapping(String column, String property, TypeHandler typeHandler, boolean primitive) { + this.column = column; + this.property = property; + this.typeHandler = typeHandler; + this.primitive = primitive; + } + } + public DefaultResultSetHandler(Executor executor, MappedStatement mappedStatement, ParameterHandler parameterHandler, ResultHandler resultHandler, BoundSql boundSql, RowBounds rowBounds) { this.executor = executor; @@ -416,33 +432,49 @@ private Object getPropertyMappingValue(ResultSet rs, MetaObject metaResultObject } } - private boolean applyAutomaticMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, String columnPrefix) throws SQLException { - final List unmappedColumnNames = rsw.getUnmappedColumnNames(resultMap, columnPrefix); - boolean foundValues = false; - for (String columnName : unmappedColumnNames) { - String propertyName = columnName; - if (columnPrefix != null && !columnPrefix.isEmpty()) { - // When columnPrefix is specified, - // ignore columns without the prefix. - if (columnName.toUpperCase(Locale.ENGLISH).startsWith(columnPrefix)) { - propertyName = columnName.substring(columnPrefix.length()); - } else { - continue; + private List createAutomaticMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, String columnPrefix) throws SQLException { + final String mapKey = getMapKey(resultMap, columnPrefix); + List autoMapping = autoMappingsCache.get(mapKey); + if (autoMapping == null) { + autoMapping = new ArrayList(); + final List unmappedColumnNames = rsw.getUnmappedColumnNames(resultMap, columnPrefix); + for (String columnName : unmappedColumnNames) { + String propertyName = columnName; + if (columnPrefix != null && !columnPrefix.isEmpty()) { + // When columnPrefix is specified, + // ignore columns without the prefix. + if (columnName.toUpperCase(Locale.ENGLISH).startsWith(columnPrefix)) { + propertyName = columnName.substring(columnPrefix.length()); + } else { + continue; + } + } + final String property = metaObject.findProperty(propertyName, configuration.isMapUnderscoreToCamelCase()); + if (property != null && metaObject.hasSetter(property)) { + final Class propertyType = metaObject.getSetterType(property); + if (typeHandlerRegistry.hasTypeHandler(propertyType)) { + final TypeHandler typeHandler = rsw.getTypeHandler(propertyType, columnName); + autoMapping.add(new UnMappedColumAutoMapping(columnName, property, typeHandler, propertyType.isPrimitive())); + } } } - final String property = metaObject.findProperty(propertyName, configuration.isMapUnderscoreToCamelCase()); - if (property != null && metaObject.hasSetter(property)) { - final Class propertyType = metaObject.getSetterType(property); - if (typeHandlerRegistry.hasTypeHandler(propertyType)) { - final TypeHandler typeHandler = rsw.getTypeHandler(propertyType, columnName); - final Object value = typeHandler.getResult(rsw.getResultSet(), columnName); - // issue #377, call setter on nulls - if (value != null || configuration.isCallSettersOnNulls()) { - if (value != null || !propertyType.isPrimitive()) { - metaObject.setValue(property, value); - } - foundValues = true; + autoMappingsCache.put(mapKey, autoMapping); + } + return autoMapping; + } + + private boolean applyAutomaticMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, String columnPrefix) throws SQLException { + List autoMapping = createAutomaticMappings(rsw, resultMap, metaObject, columnPrefix); + boolean foundValues = false; + if (autoMapping.size() > 0) { + for (UnMappedColumAutoMapping mapping : autoMapping) { + final Object value = mapping.typeHandler.getResult(rsw.getResultSet(), mapping.column); + // issue #377, call setter on nulls + if (value != null || configuration.isCallSettersOnNulls()) { + if (value != null || !mapping.primitive) { + metaObject.setValue(mapping.property, value); } + foundValues = true; } } } @@ -1015,6 +1047,10 @@ private Object instantiateCollectionPropertyIfAppropriate(ResultMapping resultMa return propertyValue; } return null; - } + } + private String getMapKey(ResultMap resultMap, String columnPrefix) { + return resultMap.getId() + ":" + columnPrefix; + } + } From b4527d13a5f705972968bf17ce60fe7cde5a56a9 Mon Sep 17 00:00:00 2001 From: Eduardo Macarron Date: Wed, 10 Feb 2016 22:44:33 +0100 Subject: [PATCH 18/30] #503 Merged into 3.3.x branch --- .../builder/MapperBuilderAssistant.java | 162 ++++++++---------- .../statement/BaseStatementHandler.java | 6 +- .../ibatis/mapping/MappedStatement.java | 1 - .../ibatis/executor/ExecutorTestHelper.java | 2 +- 4 files changed, 76 insertions(+), 95 deletions(-) diff --git a/src/main/java/org/apache/ibatis/builder/MapperBuilderAssistant.java b/src/main/java/org/apache/ibatis/builder/MapperBuilderAssistant.java index 676085fe1..d43c1787b 100644 --- a/src/main/java/org/apache/ibatis/builder/MapperBuilderAssistant.java +++ b/src/main/java/org/apache/ibatis/builder/MapperBuilderAssistant.java @@ -128,11 +128,9 @@ public Cache useNewCache(Class typeClass, boolean readWrite, boolean blocking, Properties props) { - typeClass = valueOrDefault(typeClass, PerpetualCache.class); - evictionClass = valueOrDefault(evictionClass, LruCache.class); Cache cache = new CacheBuilder(currentNamespace) - .implementation(typeClass) - .addDecorator(evictionClass) + .implementation(valueOrDefault(typeClass, PerpetualCache.class)) + .addDecorator(valueOrDefault(evictionClass, LruCache.class)) .clearInterval(flushInterval) .size(size) .readWrite(readWrite) @@ -146,8 +144,7 @@ public Cache useNewCache(Class typeClass, public ParameterMap addParameterMap(String id, Class parameterClass, List parameterMappings) { id = applyCurrentNamespace(id, false); - ParameterMap.Builder parameterMapBuilder = new ParameterMap.Builder(configuration, id, parameterClass, parameterMappings); - ParameterMap parameterMap = parameterMapBuilder.build(); + ParameterMap parameterMap = new ParameterMap.Builder(configuration, id, parameterClass, parameterMappings).build(); configuration.addParameterMap(parameterMap); return parameterMap; } @@ -167,13 +164,13 @@ public ParameterMapping buildParameterMapping( Class javaTypeClass = resolveParameterJavaType(parameterType, property, javaType, jdbcType); TypeHandler typeHandlerInstance = resolveTypeHandler(javaTypeClass, typeHandler); - ParameterMapping.Builder builder = new ParameterMapping.Builder(configuration, property, javaTypeClass); - builder.jdbcType(jdbcType); - builder.resultMapId(resultMap); - builder.mode(parameterMode); - builder.numericScale(numericScale); - builder.typeHandler(typeHandlerInstance); - return builder.build(); + return new ParameterMapping.Builder(configuration, property, javaTypeClass) + .jdbcType(jdbcType) + .resultMapId(resultMap) + .mode(parameterMode) + .numericScale(numericScale) + .typeHandler(typeHandlerInstance) + .build(); } public ResultMap addResultMap( @@ -186,7 +183,6 @@ public ResultMap addResultMap( id = applyCurrentNamespace(id, false); extend = applyCurrentNamespace(extend, true); - ResultMap.Builder resultMapBuilder = new ResultMap.Builder(configuration, id, type, resultMappings, autoMapping); if (extend != null) { if (!configuration.hasResultMap(extend)) { throw new IncompleteElementException("Could not find a parent resultmap with id '" + extend + "'"); @@ -212,8 +208,9 @@ public ResultMap addResultMap( } resultMappings.addAll(extendedResultMappings); } - resultMapBuilder.discriminator(discriminator); - ResultMap resultMap = resultMapBuilder.build(); + ResultMap resultMap = new ResultMap.Builder(configuration, id, type, resultMappings, autoMapping) + .discriminator(discriminator) + .build(); configuration.addResultMap(resultMap); return resultMap; } @@ -246,8 +243,7 @@ public Discriminator buildDiscriminator( resultMap = applyCurrentNamespace(resultMap, true); namespaceDiscriminatorMap.put(e.getKey(), resultMap); } - Discriminator.Builder discriminatorBuilder = new Discriminator.Builder(configuration, resultMapping, namespaceDiscriminatorMap); - return discriminatorBuilder.build(); + return new Discriminator.Builder(configuration, resultMapping, namespaceDiscriminatorMap).build(); } public MappedStatement addMappedStatement( @@ -279,22 +275,28 @@ public MappedStatement addMappedStatement( id = applyCurrentNamespace(id, false); boolean isSelect = sqlCommandType == SqlCommandType.SELECT; - MappedStatement.Builder statementBuilder = new MappedStatement.Builder(configuration, id, sqlSource, sqlCommandType); - statementBuilder.resource(resource); - statementBuilder.fetchSize(fetchSize); - statementBuilder.statementType(statementType); - statementBuilder.keyGenerator(keyGenerator); - statementBuilder.keyProperty(keyProperty); - statementBuilder.keyColumn(keyColumn); - statementBuilder.databaseId(databaseId); - statementBuilder.lang(lang); - statementBuilder.resultOrdered(resultOrdered); - statementBuilder.resulSets(resultSets); - setStatementTimeout(timeout, statementBuilder); - - setStatementParameterMap(parameterMap, parameterType, statementBuilder); - setStatementResultMap(resultMap, resultType, resultSetType, statementBuilder); - setStatementCache(isSelect, flushCache, useCache, currentCache, statementBuilder); + MappedStatement.Builder statementBuilder = new MappedStatement.Builder(configuration, id, sqlSource, sqlCommandType) + .resource(resource) + .fetchSize(fetchSize) + .timeout(timeout) + .statementType(statementType) + .keyGenerator(keyGenerator) + .keyProperty(keyProperty) + .keyColumn(keyColumn) + .databaseId(databaseId) + .lang(lang) + .resultOrdered(resultOrdered) + .resulSets(resultSets) + .resultMaps(getStatementResultMaps(resultMap, resultType, id)) + .resultSetType(resultSetType) + .flushCacheRequired(valueOrDefault(flushCache, !isSelect)) + .useCache(valueOrDefault(useCache, isSelect)) + .cache(currentCache); + + ParameterMap statementParameterMap = getStatementParameterMap(parameterMap, parameterType, id); + if (statementParameterMap != null) { + statementBuilder.parameterMap(statementParameterMap); + } MappedStatement statement = statementBuilder.build(); configuration.addMappedStatement(statement); @@ -305,47 +307,33 @@ private T valueOrDefault(T value, T defaultValue) { return value == null ? defaultValue : value; } - private void setStatementCache( - boolean isSelect, - boolean flushCache, - boolean useCache, - Cache cache, - MappedStatement.Builder statementBuilder) { - flushCache = valueOrDefault(flushCache, !isSelect); - useCache = valueOrDefault(useCache, isSelect); - statementBuilder.flushCacheRequired(flushCache); - statementBuilder.useCache(useCache); - statementBuilder.cache(cache); - } - - private void setStatementParameterMap( - String parameterMap, + private ParameterMap getStatementParameterMap( + String parameterMapName, Class parameterTypeClass, - MappedStatement.Builder statementBuilder) { - parameterMap = applyCurrentNamespace(parameterMap, true); - - if (parameterMap != null) { + String statementId) { + parameterMapName = applyCurrentNamespace(parameterMapName, true); + ParameterMap parameterMap = null; + if (parameterMapName != null) { try { - statementBuilder.parameterMap(configuration.getParameterMap(parameterMap)); + parameterMap = configuration.getParameterMap(parameterMapName); } catch (IllegalArgumentException e) { - throw new IncompleteElementException("Could not find parameter map " + parameterMap, e); + throw new IncompleteElementException("Could not find parameter map " + parameterMapName, e); } } else if (parameterTypeClass != null) { List parameterMappings = new ArrayList(); - ParameterMap.Builder inlineParameterMapBuilder = new ParameterMap.Builder( + parameterMap = new ParameterMap.Builder( configuration, - statementBuilder.id() + "-Inline", + statementId + "-Inline", parameterTypeClass, - parameterMappings); - statementBuilder.parameterMap(inlineParameterMapBuilder.build()); + parameterMappings).build(); } + return parameterMap; } - private void setStatementResultMap( + private List getStatementResultMaps( String resultMap, Class resultType, - ResultSetType resultSetType, - MappedStatement.Builder statementBuilder) { + String statementId) { resultMap = applyCurrentNamespace(resultMap, true); List resultMaps = new ArrayList(); @@ -359,24 +347,15 @@ private void setStatementResultMap( } } } else if (resultType != null) { - ResultMap.Builder inlineResultMapBuilder = new ResultMap.Builder( + ResultMap inlineResultMap = new ResultMap.Builder( configuration, - statementBuilder.id() + "-Inline", + statementId + "-Inline", resultType, new ArrayList(), - null); - resultMaps.add(inlineResultMapBuilder.build()); - } - statementBuilder.resultMaps(resultMaps); - - statementBuilder.resultSetType(resultSetType); - } - - private void setStatementTimeout(Integer timeout, MappedStatement.Builder statementBuilder) { - if (timeout == null) { - timeout = configuration.getDefaultStatementTimeout(); + null).build(); + resultMaps.add(inlineResultMap); } - statementBuilder.timeout(timeout); + return resultMaps; } public ResultMapping buildResultMapping( @@ -400,19 +379,19 @@ public ResultMapping buildResultMapping( if (composites.size() > 0) { column = null; } - ResultMapping.Builder builder = new ResultMapping.Builder(configuration, property, column, javaTypeClass); - builder.jdbcType(jdbcType); - builder.nestedQueryId(applyCurrentNamespace(nestedSelect, true)); - builder.nestedResultMapId(applyCurrentNamespace(nestedResultMap, true)); - builder.resultSet(resultSet); - builder.typeHandler(typeHandlerInstance); - builder.flags(flags == null ? new ArrayList() : flags); - builder.composites(composites); - builder.notNullColumns(parseMultipleColumnNames(notNullColumn)); - builder.columnPrefix(columnPrefix); - builder.foreignColumn(foreignColumn); - builder.lazy(lazy); - return builder.build(); + return new ResultMapping.Builder(configuration, property, column, javaTypeClass) + .jdbcType(jdbcType) + .nestedQueryId(applyCurrentNamespace(nestedSelect, true)) + .nestedResultMapId(applyCurrentNamespace(nestedResultMap, true)) + .resultSet(resultSet) + .typeHandler(typeHandlerInstance) + .flags(flags == null ? new ArrayList() : flags) + .composites(composites) + .notNullColumns(parseMultipleColumnNames(notNullColumn)) + .columnPrefix(columnPrefix) + .foreignColumn(foreignColumn) + .lazy(lazy) + .build(); } private Set parseMultipleColumnNames(String columnName) { @@ -438,8 +417,9 @@ private List parseCompositeColumnName(String columnName) { while (parser.hasMoreTokens()) { String property = parser.nextToken(); String column = parser.nextToken(); - ResultMapping.Builder complexBuilder = new ResultMapping.Builder(configuration, property, column, configuration.getTypeHandlerRegistry().getUnknownTypeHandler()); - composites.add(complexBuilder.build()); + ResultMapping complexResultMapping = new ResultMapping.Builder( + configuration, property, column, configuration.getTypeHandlerRegistry().getUnknownTypeHandler()).build(); + composites.add(complexResultMapping); } } return composites; diff --git a/src/main/java/org/apache/ibatis/executor/statement/BaseStatementHandler.java b/src/main/java/org/apache/ibatis/executor/statement/BaseStatementHandler.java index b81a2b2a0..2858566ee 100644 --- a/src/main/java/org/apache/ibatis/executor/statement/BaseStatementHandler.java +++ b/src/main/java/org/apache/ibatis/executor/statement/BaseStatementHandler.java @@ -102,10 +102,12 @@ public Statement prepare(Connection connection) throws SQLException { protected void setStatementTimeout(Statement stmt) throws SQLException { Integer timeout = mappedStatement.getTimeout(); - Integer defaultTimeout = configuration.getDefaultStatementTimeout(); if (timeout != null) { stmt.setQueryTimeout(timeout); - } else if (defaultTimeout != null) { + return; + } + Integer defaultTimeout = configuration.getDefaultStatementTimeout(); + if (defaultTimeout != null) { stmt.setQueryTimeout(defaultTimeout); } } diff --git a/src/main/java/org/apache/ibatis/mapping/MappedStatement.java b/src/main/java/org/apache/ibatis/mapping/MappedStatement.java index c343e4a93..2b19b7530 100644 --- a/src/main/java/org/apache/ibatis/mapping/MappedStatement.java +++ b/src/main/java/org/apache/ibatis/mapping/MappedStatement.java @@ -71,7 +71,6 @@ public Builder(Configuration configuration, String id, SqlSource sqlSource, SqlC mappedStatement.statementType = StatementType.PREPARED; mappedStatement.parameterMap = new ParameterMap.Builder(configuration, "defaultParameterMap", null, new ArrayList()).build(); mappedStatement.resultMaps = new ArrayList(); - mappedStatement.timeout = configuration.getDefaultStatementTimeout(); mappedStatement.sqlCommandType = sqlCommandType; mappedStatement.keyGenerator = configuration.isUseGeneratedKeys() && SqlCommandType.INSERT.equals(sqlCommandType) ? new Jdbc3KeyGenerator() : new NoKeyGenerator(); String logId = id; diff --git a/src/test/java/org/apache/ibatis/executor/ExecutorTestHelper.java b/src/test/java/org/apache/ibatis/executor/ExecutorTestHelper.java index b40a6609c..baadf3a22 100644 --- a/src/test/java/org/apache/ibatis/executor/ExecutorTestHelper.java +++ b/src/test/java/org/apache/ibatis/executor/ExecutorTestHelper.java @@ -197,7 +197,7 @@ public static MappedStatement prepareSelectAllAuthorsAutoMappedStatement(final C } }).build()); } - }).fetchSize(1000).build(); + }).fetchSize(1000).timeout(2000).build(); } public static MappedStatement prepareSelectOneAuthorMappedStatementWithConstructorResults(final Configuration config) { From 178cd64bb44698eaf7870c442ec95fb3d37a60c1 Mon Sep 17 00:00:00 2001 From: Eduardo Macarron Date: Wed, 10 Feb 2016 23:01:55 +0100 Subject: [PATCH 19/30] Version -> 3.3.1-SNAPSHOT and port pom.xml updates to 3.3.x branch --- pom.xml | 134 +++++++++++++++++++++++--------------------------------- 1 file changed, 54 insertions(+), 80 deletions(-) diff --git a/pom.xml b/pom.xml index c9e74e35e..0b80a75fa 100644 --- a/pom.xml +++ b/pom.xml @@ -1,4 +1,4 @@ - + org.javassist javassist - 3.18.2-GA - provided + 3.20.0-GA + compile true org.slf4j slf4j-api - 1.7.12 + 1.7.14 true org.slf4j slf4j-log4j12 - 1.7.12 + 1.7.14 true @@ -172,10 +173,11 @@ 1.2.17 true + org.apache.logging.log4j log4j-core - 2.2 + 2.3 true @@ -187,7 +189,7 @@ cglib cglib - 3.1 + 3.2.0 true @@ -201,13 +203,13 @@ org.hsqldb hsqldb - 2.3.2 + 2.3.3 test org.apache.derby derby - 10.11.1.1 + 10.12.1.1 test @@ -216,6 +218,7 @@ 1.10.19 test + commons-dbcp commons-dbcp @@ -255,7 +258,7 @@ derby.stream.error.file target/derby.log - + @@ -263,52 +266,36 @@ maven-pdf-plugin - org.sonatype.plugins - jarjar-maven-plugin - - {classes} - {test-classes} - - ognl:ognl - org.javassist:javassist - - - - ognl.** - org.apache.ibatis.ognl.@1 - - - javassist.** - org.apache.ibatis.javassist.@1 - - - org.apache.ibatis.** - - - true - + org.apache.maven.plugins + maven-shade-plugin - jarjar-classes - process-test-classes + package - jarjar + shade - {classes} - - - - jarjar-test-classes - process-test-classes - - jarjar - - - {test-classes} - - - + false + + + org.mybatis:mybatis + ognl:ognl + org.javassist:javassist + + + + + ognl + org.apache.ibatis.ognl + + + javassist + org.apache.ibatis.javassist + + + + + org.apache.maven.plugins @@ -318,27 +305,14 @@ - org.codehaus.mojo - cobertura-maven-plugin + org.jacoco + jacoco-maven-plugin - - - org.apache.ibatis.ognl.* - org.apache.ibatis.javassist.* - - - org/apache/ibatis/ognl/**/*.class - org/apache/ibatis/javassist/**/*.class - - + + org.apache.ibatis.ognl.* + org.apache.ibatis.javassist.* + - - - - clean - - - From d3573faa5d9fda0e85d2c4713b4dd538318fec58 Mon Sep 17 00:00:00 2001 From: Eduardo Macarron Date: Thu, 11 Feb 2016 20:26:07 +0100 Subject: [PATCH 20/30] Removed on-liner method used in only one place --- .../ibatis/executor/resultset/DefaultResultSetHandler.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/main/java/org/apache/ibatis/executor/resultset/DefaultResultSetHandler.java b/src/main/java/org/apache/ibatis/executor/resultset/DefaultResultSetHandler.java index d1b4bad17..9a4e5dcb9 100644 --- a/src/main/java/org/apache/ibatis/executor/resultset/DefaultResultSetHandler.java +++ b/src/main/java/org/apache/ibatis/executor/resultset/DefaultResultSetHandler.java @@ -433,7 +433,7 @@ private Object getPropertyMappingValue(ResultSet rs, MetaObject metaResultObject } private List createAutomaticMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, String columnPrefix) throws SQLException { - final String mapKey = getMapKey(resultMap, columnPrefix); + final String mapKey = resultMap.getId() + ":" + columnPrefix; List autoMapping = autoMappingsCache.get(mapKey); if (autoMapping == null) { autoMapping = new ArrayList(); @@ -1048,9 +1048,5 @@ private Object instantiateCollectionPropertyIfAppropriate(ResultMapping resultMa } return null; } - - private String getMapKey(ResultMap resultMap, String columnPrefix) { - return resultMap.getId() + ":" + columnPrefix; - } } From 4269dbb6061f0465905d70b8d3e023b5455da838 Mon Sep 17 00:00:00 2001 From: Eduardo Macarron Date: Sat, 13 Feb 2016 18:25:24 +0100 Subject: [PATCH 21/30] [maven-release-plugin] prepare release mybatis-3.3.1 --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 0b80a75fa..a5ba76e42 100644 --- a/pom.xml +++ b/pom.xml @@ -1,4 +1,4 @@ - +