I have a mapper which passes prepared parameters into velocity macro. And this fails for at least two cases:
- When parameters in macro are used in different order than they are defined in the macro;
- When parameters are used more than one time in macro.
Most probably is is due to the changes in velocity from version 2.0 where they changed when arguments are evaluated (https://velocity.apache.org/engine/2.4.1/upgrading.html#vtl-changes_3):
Velocimacro arguments are now evaluated only once (instead of each time they were referenced inside the macro body as was the case for v1.7) and passed by value (or more precisely as reference after evaluation).
Using parameters in other order than they are defined
Mapper:
<select id="selectFromMacroParamsOrder" resultType="org.mybatis.scripting.velocity.use.Name">
#macro(select_values $firstName, $lastName)
SELECT firstName, lastName FROM (VALUES ($lastName, $firstName)) as tmp (lastName, firstName)
#end
#select_values(@{firstName}, @{lastName})
</select>
Test:
@Test
public void testSelectFromMacroWithParametersOrdering() {
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
Name fred = new Name();
fred.setFirstName("Fred");
fred.setLastName("Flinstone");
List<Name> answers = sqlSession.selectList("org.mybatis.scripting.velocity.use.selectFromMacroParamsOrder", fred);
assertEquals(1, answers.size());
assertEquals(answers.get(0).getFirstName(), fred.getFirstName());
assertEquals(answers.get(0).getLastName(), fred.getLastName());
}
}
MyBatis mapper logs:
[main] DEBUG org.mybatis.scripting.velocity.use.selectFromMacroParamsOrder - ==> Preparing: SELECT firstName, lastName FROM (VALUES (?, ?)) as tmp (lastName, firstName)
[main] DEBUG org.mybatis.scripting.velocity.use.selectFromMacroParamsOrder - ==> Parameters: Fred(String), Flinstone(String)
[main] DEBUG org.mybatis.scripting.velocity.use.selectFromMacroParamsOrder - <== Total: 1
Using parameters more than once in macro
Mapper:
<select id="selectFromMacroMultipleTimes" resultType="java.lang.String">
#macro(select_multiple $value)
SELECT * FROM (VALUES ($value), ($value)) as tmp (v)
#end
#select_multiple(@{value})
</select>
Test:
@Test
public void testSelectFromMacroMultipleTimes() {
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
List<String> answers = sqlSession.selectList("org.mybatis.scripting.velocity.use.selectFromMacroMultipleTimes", "A");
assertEquals(2, answers.size());
assertEquals(answers.get(0), "A");
assertEquals(answers.get(1), "A");
}
}
MyBatis mapper logs:
[main] DEBUG org.mybatis.scripting.velocity.use.selectFromMacroMultipleTimes - ==> Preparing: SELECT * FROM (VALUES (?), (?)) as tmp (v)
[main] DEBUG org.mybatis.scripting.velocity.use.selectFromMacroMultipleTimes - ==> Parameters: A(String)
Probably the ParameterMappingCollector should return some 'proxy' from org.mybatis.scripting.velocity.ParameterMappingCollector.g(int) method, which would add parameter mapping on toString call.
I have a mapper which passes prepared parameters into velocity macro. And this fails for at least two cases:
Most probably is is due to the changes in velocity from version 2.0 where they changed when arguments are evaluated (https://velocity.apache.org/engine/2.4.1/upgrading.html#vtl-changes_3):
Using parameters in other order than they are defined
Mapper:
Test:
MyBatis mapper logs:
Using parameters more than once in macro
Mapper:
Test:
MyBatis mapper logs:
Probably the
ParameterMappingCollectorshould return some 'proxy' fromorg.mybatis.scripting.velocity.ParameterMappingCollector.g(int)method, which would add parameter mapping ontoStringcall.