diff --git a/src/main/java/org/mybatis/scripting/freemarker/FreeMarkerSqlSource.java b/src/main/java/org/mybatis/scripting/freemarker/FreeMarkerSqlSource.java index a546673..a179bce 100644 --- a/src/main/java/org/mybatis/scripting/freemarker/FreeMarkerSqlSource.java +++ b/src/main/java/org/mybatis/scripting/freemarker/FreeMarkerSqlSource.java @@ -21,6 +21,7 @@ import java.util.HashMap; import java.util.Map; +import freemarker.template.SimpleScalar; import org.apache.ibatis.builder.SqlSourceBuilder; import org.apache.ibatis.mapping.BoundSql; import org.apache.ibatis.mapping.SqlSource; @@ -40,6 +41,7 @@ public class FreeMarkerSqlSource implements SqlSource { private final Template template; private final Configuration configuration; private final Version incompatibleImprovementsVersion; + private final String databaseId; public static final String GENERATED_PARAMS_KEY = "__GENERATED__"; @@ -47,6 +49,7 @@ public FreeMarkerSqlSource(Template template, Configuration configuration, Versi this.template = template; this.configuration = configuration; this.incompatibleImprovementsVersion = incompatibleImprovementsVersion; + this.databaseId = configuration.getDatabaseId(); } /** @@ -56,9 +59,12 @@ public FreeMarkerSqlSource(Template template, Configuration configuration, Versi protected Object preProcessDataContext(Object dataContext, boolean isMap) { if (isMap) { ((Map) dataContext).put(MyBatisParamDirective.DEFAULT_KEY, new MyBatisParamDirective()); + ((Map) dataContext).put(MyBatisParamDirective.DATABASE_ID_KEY,new SimpleScalar(this.databaseId)); } else { ((ParamObjectAdapter) dataContext).putAdditionalParam(MyBatisParamDirective.DEFAULT_KEY, new MyBatisParamDirective()); + ((ParamObjectAdapter) dataContext).putAdditionalParam(MyBatisParamDirective.DATABASE_ID_KEY, + new SimpleScalar(this.databaseId)); } return dataContext; } diff --git a/src/main/java/org/mybatis/scripting/freemarker/MyBatisParamDirective.java b/src/main/java/org/mybatis/scripting/freemarker/MyBatisParamDirective.java index 12de994..76637c4 100644 --- a/src/main/java/org/mybatis/scripting/freemarker/MyBatisParamDirective.java +++ b/src/main/java/org/mybatis/scripting/freemarker/MyBatisParamDirective.java @@ -76,6 +76,7 @@ */ public class MyBatisParamDirective implements TemplateDirectiveModel { public static String DEFAULT_KEY = "p"; + public static String DATABASE_ID_KEY = "_databaseId"; @Override public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body) diff --git a/src/test/java/org/mybatis/scripting/freemarker/PreparedDatabaseIdParamsMapper.java b/src/test/java/org/mybatis/scripting/freemarker/PreparedDatabaseIdParamsMapper.java new file mode 100644 index 0000000..3d77981 --- /dev/null +++ b/src/test/java/org/mybatis/scripting/freemarker/PreparedDatabaseIdParamsMapper.java @@ -0,0 +1,29 @@ +/* + * Copyright 2015-2023 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 + * + * https://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.mybatis.scripting.freemarker; + +import org.apache.ibatis.annotations.Lang; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.util.List; +import java.util.Optional; + +public interface PreparedDatabaseIdParamsMapper { + @Lang(FreeMarkerLanguageDriver.class) + @Select("preparedDatabaseIdTest.ftl") + Optional getDatabaseIdTest(); +} diff --git a/src/test/java/org/mybatis/scripting/freemarker/PreparedDatabaseIdParamsTest.java b/src/test/java/org/mybatis/scripting/freemarker/PreparedDatabaseIdParamsTest.java new file mode 100644 index 0000000..5e79bfb --- /dev/null +++ b/src/test/java/org/mybatis/scripting/freemarker/PreparedDatabaseIdParamsTest.java @@ -0,0 +1,93 @@ +/* + * Copyright 2015-2023 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 + * + * https://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.mybatis.scripting.freemarker; + +import java.io.Reader; +import java.sql.Connection; +import java.util.ArrayList; +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.mapping.Environment; +import org.apache.ibatis.session.Configuration; +import org.apache.ibatis.session.SqlSession; +import org.apache.ibatis.session.SqlSessionFactory; +import org.apache.ibatis.session.SqlSessionFactoryBuilder; +import org.apache.ibatis.transaction.TransactionFactory; +import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory; +import org.hsqldb.jdbc.JDBCDataSource; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.util.Optional; + +/** + * Test of using FreeMarker to generate prepared statements parameters. + * + * @author s-nakao + */ +class PreparedDatabaseIdParamsTest { + private static SqlSessionFactory sqlSessionFactory; + + @BeforeAll + static void setUp() throws Exception { + Class.forName("org.hsqldb.jdbcDriver"); + + JDBCDataSource dataSource = new JDBCDataSource(); + dataSource.setUrl("jdbc:hsqldb:mem:db5"); + dataSource.setUser("sa"); + dataSource.setPassword(""); + + try (Connection conn = dataSource.getConnection()) { + try (Reader reader = Resources.getResourceAsReader("org/mybatis/scripting/freemarker/create-db.sql")) { + ScriptRunner runner = new ScriptRunner(conn); + runner.setLogWriter(null); + runner.setErrorLogWriter(null); + runner.runScript(reader); + conn.commit(); + } + } + + TransactionFactory transactionFactory = new JdbcTransactionFactory(); + Environment environment = new Environment("development", transactionFactory, dataSource); + + // You can call configuration.setDefaultScriptingLanguage(FreeMarkerLanguageDriver.class) + // after this to use FreeMarker driver by default. + Configuration configuration = new Configuration(environment); + + // set databaseId. default null + // If it is a property, please refer to the following + // https://mybatis.org/mybatis-3/ja/configuration.html#databaseIdProvider. + configuration.setDatabaseId("hsqldb"); + + configuration.addMapper(PreparedDatabaseIdParamsMapper.class); + sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration); + } + + @Test + void testInCall() { + try (SqlSession sqlSession = sqlSessionFactory.openSession()) { + PreparedDatabaseIdParamsMapper mapper = sqlSession.getMapper(PreparedDatabaseIdParamsMapper.class); + Optional nameList = mapper.getDatabaseIdTest(); + Assertions.assertEquals(true, nameList.isPresent()); + Assertions.assertEquals("Fred", nameList.get().getFirstName()); + Assertions.assertEquals("Flintstone", nameList.get().getLastName()); + } + } +} diff --git a/src/test/resources/sql/preparedDatabaseIdTest.ftl b/src/test/resources/sql/preparedDatabaseIdTest.ftl new file mode 100644 index 0000000..704918c --- /dev/null +++ b/src/test/resources/sql/preparedDatabaseIdTest.ftl @@ -0,0 +1,23 @@ +<#-- + + Copyright 2015-2023 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 + + https://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. + +--> +select + * +from + names +where + <#if '${_databaseId}' == 'hsqldb'>firstName = 'Fred' and lastName = 'Flintstone'