Skip to content

Support cache feature on TemplateFilePathProvider #21

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

Merged
merged 1 commit into from
Apr 15, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion src/main/asciidoc/user-guide.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -1124,7 +1124,7 @@ The mybatis-thymeleaf provides following properties for customizing configuratio
|`String[]`
|`"*.sql"`

4+|*Template file path provider configuration(TemplateFilePathProvider)*
4+|*Template file path provider configuration(for TemplateFilePathProvider)*

|`template-file.path-provider.prefix`
|The prefix for adding to template file path
Expand All @@ -1146,6 +1146,11 @@ The mybatis-thymeleaf provides following properties for customizing configuratio
|`Boolean`
|`true` (includes mapper name)

|`template-file.path-provider.cache-enabled`
|Whether cache a resolved template file path
|`Boolean`
|`true` (cache a resolved template file path)

4+|*Dialect configuration*

|`dialect.prefix`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,11 @@ public static class PathProviderConfig {
*/
private boolean includesMapperNameWhenSeparateDirectory = true;

/**
* Whether cache a resolved template file path.
*/
private boolean cacheEnabled = true;

/**
* Get a prefix for adding to template file path.
* <p>
Expand Down Expand Up @@ -403,7 +408,7 @@ public void setSeparateDirectoryPerMapper(boolean separateDirectoryPerMapper) {
* Default is {@code true}.
* </p>
*
* @return If includes mapper name, set {@code true}
* @return If includes mapper name, return {@code true}
*/
public boolean isIncludesMapperNameWhenSeparateDirectory() {
return includesMapperNameWhenSeparateDirectory;
Expand All @@ -422,6 +427,28 @@ public void setIncludesMapperNameWhenSeparateDirectory(boolean includesMapperNam
this.includesMapperNameWhenSeparateDirectory = includesMapperNameWhenSeparateDirectory;
}

/**
* Get whether cache a resolved template file path.
* <p>
* Default is {@code true}.
* </p>
*
* @return If cache a resolved template file path, return {@code true}
*/
public boolean isCacheEnabled() {
return cacheEnabled;
}

/**
* Set whether cache a resolved template file path.
*
* @param cacheEnabled
* If want to cache, set {@code true}
*/
public void setCacheEnabled(boolean cacheEnabled) {
this.cacheEnabled = cacheEnabled;
}

}

}
Expand Down Expand Up @@ -600,7 +627,6 @@ public void setLikeAdditionalEscapeTargetChars(Character... likeAdditionalEscape
* <td>{@code "*.sql"}</td>
* </tr>
* <tr>
* <tr>
* <th colspan="3">Template file path provider configuration(TemplateFilePathProvider)</th>
* </tr>
* <tr>
Expand All @@ -609,24 +635,26 @@ public void setLikeAdditionalEscapeTargetChars(Character... likeAdditionalEscape
* <td>{@code ""}</td>
* </tr>
* <tr>
* <tr>
* <td>template-file.path-provider.includes-package-path</td>
* <td>Whether includes package path part</td>
* <td>{@code true}</td>
* </tr>
* <tr>
* <tr>
* <td>template-file.patterns</td>
* <td>template-file.path-provider.separate-directory-per-mapper</td>
* <td>Whether separate directory per mapper</td>
* <td>{@code true}</td>
* </tr>
* <tr>
* <tr>
* <td>template-file.patterns</td>
* <td>template-file.path-provider.includes-mapper-name-when-separate-directory</td>
* <td>Whether includes mapper name into file name when separate directory per mapper</td>
* <td>{@code true}</td>
* </tr>
* <tr>
* <td>template-file.path-provider.cache-enabled</td>
* <td>Whether cache a resolved template file path</td>
* <td>{@code true}</td>
* </tr>
* <tr>
* <th colspan="3">Dialect configuration</th>
* </tr>
* <tr>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import org.apache.ibatis.builder.annotation.ProviderContext;
import org.apache.ibatis.io.Resources;
Expand Down Expand Up @@ -75,6 +77,8 @@ public class TemplateFilePathProvider {
private static PathGenerator pathGenerator = DEFAULT_PATH_GENERATOR;
private static ThymeleafLanguageDriverConfig languageDriverConfig = DEFAULT_LANGUAGE_DRIVER_CONFIG;

private static ConcurrentMap<ProviderContext, String> cache = new ConcurrentHashMap<>();

/**
* Set custom implementation for {@link PathGenerator}.
*
Expand Down Expand Up @@ -124,7 +128,16 @@ public static void setLanguageDriverConfig(ThymeleafLanguageDriverConfig languag
* @return an SQL scripting string(template file path)
*/
public static String provideSql(ProviderContext context) {
return providePath(context.getMapperType(), context.getMapperMethod(), context.getDatabaseId());
return languageDriverConfig.getTemplateFile().getPathProvider().isCacheEnabled()
? cache.computeIfAbsent(context, c -> providePath(c.getMapperType(), c.getMapperMethod(), c.getDatabaseId()))
: providePath(context.getMapperType(), context.getMapperMethod(), context.getDatabaseId());
}

/**
* Clear cache.
*/
public static void clearCache() {
cache.clear();
}

static String providePath(Class<?> mapperType, Method mapperMethod, String databaseId) {
Expand Down Expand Up @@ -183,7 +196,6 @@ private static String generateTemplatePath(Class<?> type, Method method, String
path.append('-').append(databaseId);
}
path.append(".sql");
System.out.println(path);
return path.toString();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@ void testCustomWithCustomConfigFileUsingMethodArgument() {
.assertFalse(thymeleafLanguageDriverConfig.getTemplateFile().getPathProvider().isSeparateDirectoryPerMapper());
Assertions.assertFalse(
thymeleafLanguageDriverConfig.getTemplateFile().getPathProvider().isIncludesMapperNameWhenSeparateDirectory());
Assertions.assertFalse(thymeleafLanguageDriverConfig.getTemplateFile().getPathProvider().isCacheEnabled());

}

Expand All @@ -245,6 +246,7 @@ void testCustomWithCustomizerFunction() {
c.getTemplateFile().getPathProvider().setIncludesPackagePath(false);
c.getTemplateFile().getPathProvider().setSeparateDirectoryPerMapper(false);
c.getTemplateFile().getPathProvider().setIncludesMapperNameWhenSeparateDirectory(false);
c.getTemplateFile().getPathProvider().setCacheEnabled(false);
c.getDialect().setPrefix("mbs");
c.getDialect().setLikeEscapeChar('~');
c.getDialect().setLikeEscapeClauseFormat("escape '%s'");
Expand Down Expand Up @@ -289,6 +291,7 @@ void testCustomWithCustomizerFunction() {
.assertFalse(thymeleafLanguageDriverConfig.getTemplateFile().getPathProvider().isSeparateDirectoryPerMapper());
Assertions.assertFalse(
thymeleafLanguageDriverConfig.getTemplateFile().getPathProvider().isIncludesMapperNameWhenSeparateDirectory());
Assertions.assertFalse(thymeleafLanguageDriverConfig.getTemplateFile().getPathProvider().isCacheEnabled());
}

@Test
Expand All @@ -307,6 +310,7 @@ void testCustomWithBuilderUsingCustomProperties() {
customProperties.setProperty("template-file.path-provider.includes-package-path", "false");
customProperties.setProperty("template-file.path-provider.separate-directory-per-mapper", "false");
customProperties.setProperty("template-file.path-provider.includes-mapper-name-when-separate-directory", "false");
customProperties.setProperty("template-file.path-provider.cache-enabled", "false");
customProperties.setProperty("dialect.prefix", "mbs");
customProperties.setProperty("dialect.like-escape-char", "~");
customProperties.setProperty("dialect.like-escape-clause-format", "escape '%s'");
Expand Down Expand Up @@ -353,6 +357,7 @@ void testCustomWithBuilderUsingCustomProperties() {
.assertFalse(thymeleafLanguageDriverConfig.getTemplateFile().getPathProvider().isSeparateDirectoryPerMapper());
Assertions.assertFalse(
thymeleafLanguageDriverConfig.getTemplateFile().getPathProvider().isIncludesMapperNameWhenSeparateDirectory());
Assertions.assertFalse(thymeleafLanguageDriverConfig.getTemplateFile().getPathProvider().isCacheEnabled());
}

@Test
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
/**
* Copyright 2018-2019 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.mybatis.scripting.thymeleaf.integrationtest;

import java.io.Reader;
import java.sql.Connection;

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 org.junit.jupiter.api.condition.DisabledIfSystemProperty;
import org.mybatis.scripting.thymeleaf.ThymeleafLanguageDriver;
import org.mybatis.scripting.thymeleaf.ThymeleafLanguageDriverConfig;
import org.mybatis.scripting.thymeleaf.integrationtest.domain.Name;
import org.mybatis.scripting.thymeleaf.integrationtest.mapper.TemplateFilePathProviderMapper;

@DisabledIfSystemProperty(named = "mybatis.version", matches = "3\\.4\\..*|3\\.5\\.0")
class TemplateFilePathProviderMapperNoCacheTest {
private static SqlSessionFactory sqlSessionFactory;

@BeforeAll
static void setUp() throws Exception {
Class.forName("org.hsqldb.jdbcDriver");
JDBCDataSource dataSource = new JDBCDataSource();
dataSource.setUrl("jdbc:hsqldb:mem:db1");
dataSource.setUser("sa");
dataSource.setPassword("");

try (Connection conn = dataSource.getConnection()) {
try (Reader reader = Resources.getResourceAsReader("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);

Configuration configuration = new Configuration(environment);
configuration.setMapUnderscoreToCamelCase(true);
configuration.getLanguageRegistry()
.register(new ThymeleafLanguageDriver(ThymeleafLanguageDriverConfig.newInstance(c -> {
c.getTemplateFile().getPathProvider().setPrefix("sql/");
c.getTemplateFile().getPathProvider().setIncludesPackagePath(false);
c.getTemplateFile().getPathProvider().setCacheEnabled(false);
})));
configuration.setDefaultScriptingLanguage(ThymeleafLanguageDriver.class);

configuration.addMapper(TemplateFilePathProviderMapper.class);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);
}

@Test
void testInsert() {
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
TemplateFilePathProviderMapper mapper = sqlSession.getMapper(TemplateFilePathProviderMapper.class);
Name name = new Name();
name.setFirstName("Thymeleaf");
name.setLastName("MyBatis");
mapper.insert(name);

Name loadedName = mapper.findById(name.getId());
Assertions.assertEquals(name.getFirstName(), loadedName.getFirstName());
Assertions.assertEquals(name.getLastName(), loadedName.getLastName());
}
}

@Test
void testUpdate() {
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
TemplateFilePathProviderMapper mapper = sqlSession.getMapper(TemplateFilePathProviderMapper.class);
Name name = new Name();
name.setFirstName("Thymeleaf");
name.setLastName("MyBatis");
mapper.insert(name);

Name updatingName = new Name();
updatingName.setId(name.getId());
updatingName.setFirstName("Thymeleaf3");
mapper.update(updatingName);

Name loadedName = mapper.findById(name.getId());
Assertions.assertEquals(updatingName.getFirstName(), loadedName.getFirstName());
Assertions.assertEquals(name.getLastName(), loadedName.getLastName());
}
}

@Test
void testDelete() {
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
TemplateFilePathProviderMapper mapper = sqlSession.getMapper(TemplateFilePathProviderMapper.class);
Name name = new Name();
name.setFirstName("Thymeleaf");
name.setLastName("MyBatis");
mapper.insert(name);

mapper.delete(name);

Name loadedName = mapper.findById(name.getId());
Assertions.assertNull(loadedName);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.apache.ibatis.transaction.TransactionFactory;
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
import org.hsqldb.jdbc.JDBCDataSource;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
Expand All @@ -36,11 +37,18 @@
import org.mybatis.scripting.thymeleaf.ThymeleafLanguageDriverConfig;
import org.mybatis.scripting.thymeleaf.integrationtest.domain.Name;
import org.mybatis.scripting.thymeleaf.integrationtest.mapper.TemplateFilePathProviderMapper;
import org.mybatis.scripting.thymeleaf.support.TemplateFilePathProvider;

@DisabledIfSystemProperty(named = "mybatis.version", matches = "3\\.4\\..*|3\\.5\\.0")
class TemplateFilePathProviderMapperTest {
private static SqlSessionFactory sqlSessionFactory;

@BeforeAll
@AfterAll
static void cleanup() {
TemplateFilePathProvider.clearCache();
}

@BeforeAll
static void setUp() throws Exception {
Class.forName("org.hsqldb.jdbcDriver");
Expand Down
1 change: 1 addition & 0 deletions src/test/resources/mybatis-thymeleaf-custom.properties
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ template-file.path-provider.prefix=sqls/
template-file.path-provider.includes-package-path=false
template-file.path-provider.separate-directory-per-mapper=false
template-file.path-provider.includes-mapper-name-when-separate-directory=false
template-file.path-provider.cache-enabled=false
dialect.prefix=mybatis
dialect.like-escape-char=~
dialect.like-escape-clause-format=escape '%s'
Expand Down