Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#set inside #repeat does not work correctly #14

Open
tivv opened this issue Jan 29, 2014 · 3 comments
Open

#set inside #repeat does not work correctly #14

tivv opened this issue Jan 29, 2014 · 3 comments

Comments

@tivv
Copy link

tivv commented Jan 29, 2014

Mapper:

<update id="velocity-nested-set" lang="velocity">
    #repeat( $_parameter.list $level1)
        #set( $foo = $level1)
        @{foo}
    #end
</update>

Test:

@Test
public void velocityTestNestedSet() throws SQLException, IOException {
    expect(connection.getAutoCommit()).andStubReturn(false);
    expect(connection.prepareStatement("\n" +
            "                    ?\n" +
            "                    ?\n" +
            "            ")).andReturn(statement);
    statement.setInt(1, 1);
    statement.addBatch();
    statement.setInt(2, 2);
    statement.addBatch();
    expect(statement.executeBatch()).andStubReturn(new int[]{2});
    statement.close();
    connection.setAutoCommit(true);
    connection.rollback();
    connection.close();

    replay();

    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(
            Resources.getResourceAsStream("configuration.xml"));
    SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH, connection);
    List<Integer> param = Arrays.asList(1,2);
    sqlSession.insert("velocity-nested-set", param);
    sqlSession.flushStatements();
    sqlSession.close();

}

Exception:

java.lang.AssertionError: 
  Unexpected method call setInt(1, 2):
    setInt(1, 1): expected: 1, actual: 0
    addBatch(): expected: 2, actual: 0
    setInt(2, 2): expected: 1, actual: 0
    close(): expected: 1, actual: 0
    at org.easymock.internal.MockInvocationHandler.invoke(MockInvocationHandler.java:29)
    at org.easymock.internal.ObjectMethodsFilter.invoke(ObjectMethodsFilter.java:56)
    at com.sun.proxy.$Proxy7.setInt(Unknown Source)
    at org.apache.ibatis.type.IntegerTypeHandler.setNonNullParameter(IntegerTypeHandler.java:28)
    at org.apache.ibatis.type.IntegerTypeHandler.setNonNullParameter(IntegerTypeHandler.java:23)
    at org.apache.ibatis.type.BaseTypeHandler.setParameter(BaseTypeHandler.java:46)
    at org.apache.ibatis.type.UnknownTypeHandler.setNonNullParameter(UnknownTypeHandler.java:42)
    at org.apache.ibatis.type.BaseTypeHandler.setParameter(BaseTypeHandler.java:46)
    at org.apache.ibatis.scripting.defaults.DefaultParameterHandler.setParameters(DefaultParameterHandler.java:77)
    at org.apache.ibatis.executor.statement.PreparedStatementHandler.parameterize(PreparedStatementHandler.java:77)
    at org.apache.ibatis.executor.statement.RoutingStatementHandler.parameterize(RoutingStatementHandler.java:58)
    at org.apache.ibatis.executor.BatchExecutor.doUpdate(BatchExecutor.java:68)
    at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:100)
    at org.apache.ibatis.executor.CachingExecutor.update(CachingExecutor.java:75)
    at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:148)
    at org.apache.ibatis.session.defaults.DefaultSqlSession.insert(DefaultSqlSession.java:137)
@mnesarco
Copy link
Member

mnesarco commented May 1, 2014

Velocity vars like $foo and mybatis binding parameters like @{foo} has different scopes, so in this case @{foo} are always pointing to the last assigned value of $foo. @{foo} knows nothing about the iteration state.

In the current implementation, velocity runs before binding, in different phases, so it is not possible or at least not easy nor efficient way to support this requirement without a major refactoring.

@tivv
Copy link
Author

tivv commented May 2, 2014

Well, I understand this. But this limits usages a lot. I've got a question: why do you use this approach? As for me, using #p($foo) instead of @{foo) is a little more verbose, but much more flexible.

@mnesarco
Copy link
Member

mnesarco commented Jul 2, 2017

@emacarron This is a very old issue. Its root are in mybatis core because scripting evaluation and jdbc parameter binding are handled in different phases. I remember we have discussed this some years ago... Do you think it is time to address this or we will keep current mybatis way forever?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants