From 2141411f47156f96b052c69e7a961bbacf9589f1 Mon Sep 17 00:00:00 2001 From: fanbeibei Date: Mon, 24 Apr 2023 18:37:04 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E5=BC=95=E5=85=A5=E7=A6=81=E7=94=A8?= =?UTF-8?q?=E6=B3=A8=E8=A7=A3=E7=9A=84=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 344 ++++++++++++++++-- .../core/ext/MapperLocationsBuilder.java | 2 + .../src/main/resources/application.properties | 2 + .../boot/autoconfigure/MybatisProperties.java | 17 + .../core/ext/SqlSessionFactoryBeanExt.java | 15 + 5 files changed, 358 insertions(+), 22 deletions(-) diff --git a/.gitignore b/.gitignore index fa13141..2d62230 100644 --- a/.gitignore +++ b/.gitignore @@ -1,31 +1,331 @@ -target/ -logs/ -!.mvn/wrapper/maven-wrapper.jar +#java忽略文件 + +*.class + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +#Eclipse忽略文件 +.metadata +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.settings/ +.loadpath +.recommenders + +.mvn/ + +# Eclipse Core +.project + +# External tool builders +.externalToolBuilders/ -### STS ### -.apt_generated +# Locally stored "Eclipse launch configurations" +*.launch + +# PyDev specific (Python IDE for Eclipse) +*.pydevproject + +# CDT-specific (C/C++ Development Tooling) +.cproject + +# JDT-specific (Eclipse Java Development Tools) .classpath + +# Java annotation processor (APT) .factorypath -.project -.settings + +# PDT-specific (PHP Development Tools) +.buildpath + +# sbteclipse plugin +.target + +# Tern plugin +.tern-project + +# TeXlipse plugin +.texlipse + +# STS (Spring Tool Suite) .springBeans -### IntelliJ IDEA ### -.idea +# Code Recommenders +.recommenders/ + +#windows忽略文件 +# Windows thumbnail cache files +Thumbs.db +ehthumbs.db +ehthumbs_vista.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msm +*.msp + +# Windows shortcuts +*.lnk + +#JetBrains 公司产品 如前端常用webstorm +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff: +.idea/workspace.xml +.idea/tasks.xml + +# Sensitive or high-churn files: +.idea/dataSources/ +.idea/dataSources.ids +.idea/dataSources.xml +.idea/dataSources.local.xml +.idea/sqlDataSources.xml +.idea/dynamic.xml +.idea/uiDesigner.xml + +# Gradle: +.idea/gradle.xml +.idea/libraries + +# Mongo Explorer plugin: +.idea/mongoSettings.xml + +## File-based project format: *.iws + +## Plugin-specific files: + +# IntelliJ +/out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + + +#前端常用sublime编辑器 +# cache files for sublime text +*.tmlanguage.cache +*.tmPreferences.cache +*.stTheme.cache + +# workspace files are user-specific +*.sublime-workspace + +# project files should be checked into the repository, unless a significant +# proportion of contributors will probably not be using SublimeText +# *.sublime-project + +# sftp configuration file +sftp-config.json + +# Package control specific files +Package Control.last-run +Package Control.ca-list +Package Control.ca-bundle +Package Control.system-ca-bundle +Package Control.cache/ +Package Control.ca-certs/ +Package Control.merged-ca-bundle +Package Control.user-ca-bundle +oscrypto-ca-bundle.crt +bh_unicode_properties.cache + +# Sublime-github package stores a github token in this file +# https://packagecontrol.io/packages/sublime-github +GitHub.sublime-settings + +#notepad +# Notepad++ backups # +*.bak + +#python忽略文件 +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg +.vscode/ +node_modules/ + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*,cover +.hypothesis/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ +webapp/ +/webapp/ + +# Jupyter Notebook +.ipynb_checkpoints + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# dotenv +.env + +# virtualenv +.venv/ +venv/ +ENV/ + +# Spyder project settings +.spyderproject + +# Rope project settings +.ropeproject + + +#maven忽略文件 +target/ +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +pom.xml.next +release.properties +dependency-reduced-pom.xml +buildNumber.properties +.mvn/timing.properties + +# Exclude maven wrapper +!/.mvn/wrapper/maven-wrapper.jar + + +#mircosoft office忽略 +*.tmp + +# Word temporary +~$*.doc* + +# Excel temporary +~$*.xls* + +# Excel Backup File +*.xlk + +# PowerPoint temporary +~$*.ppt* + +# Visio autosave temporary files +*.~vsdx + +#防止恶意插件病毒等 +*.exe + + +# 忽略各级目录的idea和eclipse文件 +target/ +.settings/ +*.classpath +*.project +/logs/ +*.yml *.iml +.idea/ *.ipr +*.iws -### NetBeans ### -nbproject/private/ -nbbuild/ -dist/ -nbdist/ -.nb-gradle/ -/.idea/ -/easyopen-parent.iml -/.settings/ -/.project -!/.idea/ -/.idea/libraries/ -/local-config/ + +# Ignore Gradle project-specific cache directory +.gradle + +# Ignore Gradle build output directory +build \ No newline at end of file diff --git a/fastmybatis-core/src/main/java/com/gitee/fastmybatis/core/ext/MapperLocationsBuilder.java b/fastmybatis-core/src/main/java/com/gitee/fastmybatis/core/ext/MapperLocationsBuilder.java index 2261f9e..f908ea1 100644 --- a/fastmybatis-core/src/main/java/com/gitee/fastmybatis/core/ext/MapperLocationsBuilder.java +++ b/fastmybatis-core/src/main/java/com/gitee/fastmybatis/core/ext/MapperLocationsBuilder.java @@ -75,6 +75,8 @@ public class MapperLocationsBuilder { StringUtil.CONFIG_LOCATION_DELIMITERS); ClassSearch classSearch = SpiContext.getClassSearch(); Set> clazzsSet = classSearch.search(Object.class, basePackages); + // TODO 插入检查注解的代码 + return this.buildMapperLocations(clazzsSet); } catch (Exception e) { LOG.error("构建mapper失败", e); diff --git a/fastmybatis-demo/fastmybatis-demo-springboot/src/main/resources/application.properties b/fastmybatis-demo/fastmybatis-demo-springboot/src/main/resources/application.properties index 8ec6da1..a05e27a 100644 --- a/fastmybatis-demo/fastmybatis-demo-springboot/src/main/resources/application.properties +++ b/fastmybatis-demo/fastmybatis-demo-springboot/src/main/resources/application.properties @@ -15,6 +15,8 @@ spring.datasource.password=${mysql.password} mybatis.mapper-locations=classpath*:mybatis/mapper/*.xml # mybatis config file mybatis.config-location=classpath:mybatis/mybatisConfig.xml +# ???sql????? +mybatis.disable-sql-annotation=true # \u81EA\u52A8\u586B\u5145\u65F6\u95F4 #mybatis.fill.com.gitee.fastmybatis.core.support.DateFillInsert=add_time diff --git a/fastmybatis-spring-boot-starter/src/main/java/com/gitee/fastmybatis/spring/boot/autoconfigure/MybatisProperties.java b/fastmybatis-spring-boot-starter/src/main/java/com/gitee/fastmybatis/spring/boot/autoconfigure/MybatisProperties.java index 061c4ec..7cc844f 100644 --- a/fastmybatis-spring-boot-starter/src/main/java/com/gitee/fastmybatis/spring/boot/autoconfigure/MybatisProperties.java +++ b/fastmybatis-spring-boot-starter/src/main/java/com/gitee/fastmybatis/spring/boot/autoconfigure/MybatisProperties.java @@ -41,6 +41,7 @@ import org.springframework.core.io.support.ResourcePatternResolver; public class MybatisProperties { private static final String COMMON_SQL_CLASSPATH = "fastmybatis/commonSql.xml"; + public static final String MYBATIS_PREFIX = "mybatis"; @@ -106,6 +107,13 @@ public class MybatisProperties { * mapper文件保存文件夹地址,如:C:/mapper */ private String mapperSaveDir; + + + /** + * 是否禁止将sql写到mybatis的原生注解中,如禁止启动报错 + * + */ + private boolean disableSqlAnnotation = false; /** * Dao路径 */ @@ -378,4 +386,13 @@ public class MybatisProperties { public void setEmptyStringWithTrim(boolean emptyStringWithTrim) { this.emptyStringWithTrim = emptyStringWithTrim; } + + + public boolean isDisableSqlAnnotation() { + return disableSqlAnnotation; + } + + public void setDisableSqlAnnotation(boolean disableSqlAnnotation) { + this.disableSqlAnnotation = disableSqlAnnotation; + } } diff --git a/fastmybatis-spring/src/main/java/com/gitee/fastmybatis/core/ext/SqlSessionFactoryBeanExt.java b/fastmybatis-spring/src/main/java/com/gitee/fastmybatis/core/ext/SqlSessionFactoryBeanExt.java index 493c483..3aa8010 100644 --- a/fastmybatis-spring/src/main/java/com/gitee/fastmybatis/core/ext/SqlSessionFactoryBeanExt.java +++ b/fastmybatis-spring/src/main/java/com/gitee/fastmybatis/core/ext/SqlSessionFactoryBeanExt.java @@ -38,6 +38,12 @@ public class SqlSessionFactoryBeanExt extends SqlSessionFactoryBean { private String basePackage; + /** + * 是否禁止将sql写到mybatis的原生注解中,如禁止启动报错 + * + */ + private boolean disableSqlAnnotation = false; + private String dialect; @@ -112,6 +118,15 @@ public class SqlSessionFactoryBeanExt extends SqlSessionFactoryBean { return mapperLocationsBuilder.getConfig(); } + + public boolean isDisableSqlAnnotation() { + return disableSqlAnnotation; + } + + public void setDisableSqlAnnotation(boolean disableSqlAnnotation) { + this.disableSqlAnnotation = disableSqlAnnotation; + } + public Resource[] getMapperLocations() { return mapperLocations; } -- Gitee From 1ce461a8ea647b5959f2a3af375a9e2faccde618 Mon Sep 17 00:00:00 2001 From: youbeiwuhuan Date: Mon, 24 Apr 2023 22:34:45 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E5=AE=8C=E6=88=90mybatis.disable-sql-annot?= =?UTF-8?q?ation=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fastmybatis/core/FastmybatisConfig.java | 18 + .../core/ext/MapperLocationsBuilder.java | 587 ++++++++++-------- .../src/main/resources/application.properties | 2 +- .../main/resources/spring/database-config.xml | 2 + .../core/ext/SqlSessionFactoryBeanExt.java | 14 - 5 files changed, 356 insertions(+), 267 deletions(-) diff --git a/fastmybatis-core/src/main/java/com/gitee/fastmybatis/core/FastmybatisConfig.java b/fastmybatis-core/src/main/java/com/gitee/fastmybatis/core/FastmybatisConfig.java index ee571ec..110f819 100644 --- a/fastmybatis-core/src/main/java/com/gitee/fastmybatis/core/FastmybatisConfig.java +++ b/fastmybatis-core/src/main/java/com/gitee/fastmybatis/core/FastmybatisConfig.java @@ -26,11 +26,21 @@ public class FastmybatisConfig { /** 查询字段去掉首尾空格 */ public static volatile boolean emptyStringWithTrim = true; + + + /** * 数据库忽略更新的字段,如gmt_create,gmt_modified */ public static volatile List defaultIgnoreUpdateColumns = Collections.emptyList(); + + /** + * 是否禁止将sql写到mybatis的原生注解中,如禁止启动报错 + * + */ + private boolean disableSqlAnnotation = false; + /** * Mybatis xml文件存放位置,如:mybatis/mapper */ @@ -258,4 +268,12 @@ public class FastmybatisConfig { public void setGlobalIdIncrement(boolean globalIdIncrement) { this.globalIdIncrement = globalIdIncrement; } + + public boolean isDisableSqlAnnotation() { + return disableSqlAnnotation; + } + + public void setDisableSqlAnnotation(boolean disableSqlAnnotation) { + this.disableSqlAnnotation = disableSqlAnnotation; + } } diff --git a/fastmybatis-core/src/main/java/com/gitee/fastmybatis/core/ext/MapperLocationsBuilder.java b/fastmybatis-core/src/main/java/com/gitee/fastmybatis/core/ext/MapperLocationsBuilder.java index f908ea1..38b331f 100644 --- a/fastmybatis-core/src/main/java/com/gitee/fastmybatis/core/ext/MapperLocationsBuilder.java +++ b/fastmybatis-core/src/main/java/com/gitee/fastmybatis/core/ext/MapperLocationsBuilder.java @@ -10,6 +10,7 @@ import com.gitee.fastmybatis.core.ext.spi.SpiContext; import com.gitee.fastmybatis.core.util.IOUtil; import com.gitee.fastmybatis.core.util.MybatisFileUtil; import com.gitee.fastmybatis.core.util.StringUtil; +import org.apache.ibatis.annotations.*; import org.apache.ibatis.logging.Log; import org.apache.ibatis.logging.LogFactory; import org.dom4j.Attribute; @@ -23,290 +24,372 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.lang.reflect.Method; import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; +import java.util.*; /** * mapper构建 - * - * @author tanghc * + * @author tanghc */ public class MapperLocationsBuilder { - private static final Log LOG = LogFactory.getLog(MapperLocationsBuilder.class); - - private final Map mybatisMapperStore = new HashMap<>(); - - private FastmybatisConfig config; - - private List mapperNames = Collections.emptyList(); - - private Set> mapperClasses = new HashSet<>(64); - - private String dialect; - - public MapperLocationsBuilder() { - this(new FastmybatisConfig()); - } - - public MapperLocationsBuilder(FastmybatisConfig config) { - Objects.requireNonNull(config, "config can not null"); - this.config = config; - } - - public MyBatisResource[] build(String basePackage, List myBatisResources, String dialect) { - for (MyBatisResource myBatisResource : myBatisResources) { - // XxDao.xml - String filename = myBatisResource.getFilename(); - mybatisMapperStore.put(filename, myBatisResource); - } - this.dialect = dialect; - try { - String[] basePackages = StringUtil.tokenizeToStringArray(basePackage, - StringUtil.CONFIG_LOCATION_DELIMITERS); - ClassSearch classSearch = SpiContext.getClassSearch(); - Set> clazzsSet = classSearch.search(Object.class, basePackages); - // TODO 插入检查注解的代码 - - return this.buildMapperLocations(clazzsSet); - } catch (Exception e) { - LOG.error("构建mapper失败", e); - throw new MapperFileException(e); - } finally { - distroy(); - } - } - - private void distroy() { - mybatisMapperStore.clear(); - } - - private MyBatisResource getMapperFile(String mapperFileName) { - return mybatisMapperStore.get(mapperFileName); - } - - private MyBatisResource[] buildMapperLocations(Set> clazzsSet) { - this.initContext(clazzsSet); - - List mapperLocations = this.buildMapperResource(clazzsSet); - - this.addUnmergedResource(mapperLocations); - - this.addCommonSqlClasspathMapper(mapperLocations); - - return mapperLocations.toArray(new MyBatisResource[mapperLocations.size()]); - } - - private List buildMapperResource(Set> clazzsSet) { - int classCount = clazzsSet.size(); - if(classCount == 0) { - return new ArrayList<>(); - } - final MyBatisResource templateResource = this.buildTemplateResource(this.getDbName()); - LOG.debug("使用模板:" + templateResource); - final String globalVmLocation = this.config.getGlobalVmLocation(); - final ClassClient codeClient = new ClassClient(config); - final List mapperLocations = new ArrayList<>(classCount); - - long startTime = System.currentTimeMillis(); - try { - String templateContent = templateResource.getContent(); - for (Class daoClass : clazzsSet) { - String xml = codeClient.genMybatisXml(daoClass, templateContent, globalVmLocation); - xml = mergeExtMapperFile(daoClass, xml); - saveMapper(daoClass.getSimpleName() + FastmybatisConstants.XML_SUFFIX, xml); - mapperLocations.add(MyBatisResource.build(xml, daoClass)); - } - - long endTime = System.currentTimeMillis(); - LOG.debug("生成Mapper内容总耗时:" + (endTime - startTime) / 1000.0 + "秒"); - return mapperLocations; - } catch (Exception e) { - LOG.error(e.getMessage(), e); - throw new GenCodeException(e); - } - - } - - private List buildMapperNames(Set> clazzsSet) { - List list = new ArrayList<>(clazzsSet.size()); - for (Class mapperClass : clazzsSet) { - list.add(mapperClass.getSimpleName()); - } - return list; - } - - private void initContext(Set> clazzsSet) { - mapperClasses.addAll(clazzsSet); - mapperNames = this.buildMapperNames(clazzsSet); - for (Class mapperClass : clazzsSet) { - ExtContext.addMapperClass(mapperClass); - } - } - - public Set> getMapperClasses() { - return mapperClasses; - } - - /** 保存mapper到本地文件夹 - * @throws IOException - */ - private void saveMapper(String filename, final String content) throws IOException { - String saveDir = config.getMapperSaveDir(); - if (StringUtil.hasText(saveDir)) { - String path = saveDir + "/" + filename; - LOG.debug("保存mapper文件到" + path); - try (OutputStream out = new FileOutputStream(path)) { - IOUtil.copy(IOUtil.toInputStream(content, StandardCharsets.UTF_8), out); - }catch (IOException e) { - throw e; - } - } - } - - private MyBatisResource buildTemplateResource(String dialect) { - // mysql.vm - String templateFileName = this.buildTemplateFileName(dialect); - // 优先使用classpath根目录下的vm模板 - MyBatisResource myBatisResource = MyBatisResource.buildFromClasspath(templateFileName); - if (myBatisResource.exists()) { - return myBatisResource; - } - String templateClasspath = config.getTemplateClasspath(); - if (StringUtil.isEmpty(templateClasspath)) { - templateClasspath = FastmybatisConstants.DEFAULT_CLASS_PATH; - } - // 返回格式:classpath路径 + 数据库名称 + 文件后缀 - // 如:/fastmybatis/tpl/mysql.vm - String location = templateClasspath + templateFileName; - return MyBatisResource.buildFromClasspath(location); - } - - /** 构建文件名 */ - private String buildTemplateFileName(String dialect) { - dialect = dialect.replaceAll("\\s", "").toLowerCase(); - return dialect + FastmybatisConstants.TEMPLATE_SUFFIX; - } - - private void addCommonSqlClasspathMapper(List mapperLocations) { - String commonSqlClasspath = config.getCommonSqlClasspath(); - MyBatisResource myBatisResource = MyBatisResource.buildFromClasspath(commonSqlClasspath); - mapperLocations.add(myBatisResource); - } - - /**合并其它mapper*/ - private void addUnmergedResource(List mapperLocations) { - Collection mapperResourceDefinitions = this.mybatisMapperStore.values(); - for (MyBatisResource mapperResourceDefinition : mapperResourceDefinitions) { - if (mapperResourceDefinition.isMerged()) { - continue; - } - LOG.debug("加载未合并Mapper:" + mapperResourceDefinition.getFilename()); - mapperLocations.add(mapperResourceDefinition); - } - } - - /** 合并扩展mapper文件内容 - * @throws DocumentException - * @throws IOException */ - private String mergeExtMapperFile(Class mapperClass, String xml) throws IOException, DocumentException { - // 自定义文件 - String mapperFileName = mapperClass.getSimpleName() + FastmybatisConstants.XML_SUFFIX; - // 先找跟自己同名的xml,如:UserMapper.java -> UserMapper.xml - MyBatisResource myBatisResource = this.getMapperFile(mapperFileName); - StringBuilder extXml = new StringBuilder(); - - if (myBatisResource != null) { - // 追加内容 - String extFileContent = MybatisFileUtil.getExtFileContent(myBatisResource.getInputStream()); - extXml.append(extFileContent); - - myBatisResource.setMerged(true); - } - // 再找namespace一样的xml + private static final Log LOG = LogFactory.getLog(MapperLocationsBuilder.class); + + private final Map mybatisMapperStore = new HashMap<>(); + + private FastmybatisConfig config; + + private List mapperNames = Collections.emptyList(); + + private Set> mapperClasses = new HashSet<>(64); + + private String dialect; + + public MapperLocationsBuilder() { + this(new FastmybatisConfig()); + } + + public MapperLocationsBuilder(FastmybatisConfig config) { + Objects.requireNonNull(config, "config can not null"); + this.config = config; + } + + public MyBatisResource[] build(String basePackage, List myBatisResources, String dialect) { + for (MyBatisResource myBatisResource : myBatisResources) { + // XxDao.xml + String filename = myBatisResource.getFilename(); + mybatisMapperStore.put(filename, myBatisResource); + } + this.dialect = dialect; + try { + String[] basePackages = StringUtil.tokenizeToStringArray(basePackage, + StringUtil.CONFIG_LOCATION_DELIMITERS); + ClassSearch classSearch = SpiContext.getClassSearch(); + Set> clazzsSet = classSearch.search(Object.class, basePackages); + + // 检查是否将sql写在了注解中 + if (config.isDisableSqlAnnotation()) { + checkSqlAnnotationOnMapper(clazzsSet); + } + + return this.buildMapperLocations(clazzsSet); + } catch (Exception e) { + LOG.error("构建mapper失败", e); + throw new MapperFileException(e); + } finally { + distroy(); + } + } + + + /** + * 禁止将sql写在注解中 + * + * @param clazzsSet + */ + private void checkSqlAnnotationOnMapper(Set> clazzsSet) { + + if (null == clazzsSet || 0 == clazzsSet.size()) { + return; + } + + for (Class mapperClass : clazzsSet) { + Method[] methods = mapperClass.getMethods(); + if (null == methods || methods.length == 0) { + continue; + } + + for (Method m : methods) { + checkInsert(mapperClass, m); + checkDelete(mapperClass, m); + checkSelect(mapperClass, m); + checkUpdate(mapperClass, m); + } + } + + } + + + private void checkInsert(Class mapperClass, Method m) { + Insert anno = m.getAnnotation(Insert.class); + if (null != anno) { + throw new IllegalStateException("本项目禁止将sql写在Mybatis注解中.问题Mapper:" + mapperClass.getName()+",问题方法:"+m.getName()); + } + InsertProvider annoSp = m.getAnnotation(InsertProvider.class); + if (null != annoSp) { + throw new IllegalStateException("本项目禁止使用InsertProvider注解.问题Mapper:" + mapperClass.getName()+",问题方法:"+m.getName()); + } + } + + private void checkSelect(Class mapperClass, Method m) { + Select anno = m.getAnnotation(Select.class); + if (null != anno) { + throw new IllegalStateException("本项目禁止将sql写在Mybatis注解中.问题Mapper:" + mapperClass.getName()+",问题方法:"+m.getName()); + } + SelectProvider annoSp = m.getAnnotation(SelectProvider.class); + if (null != annoSp) { + throw new IllegalStateException("本项目禁止使用SelectProvider注解.问题Mapper:" + mapperClass.getName()+",问题方法:"+m.getName()); + } + } + + private void checkUpdate(Class mapperClass, Method m) { + Update anno = m.getAnnotation(Update.class); + if (null != anno) { + throw new IllegalStateException("本项目禁止将sql写在Mybatis注解中.问题Mapper:" + mapperClass.getName()+",问题方法:"+m.getName()); + } + + UpdateProvider annoSp = m.getAnnotation(UpdateProvider.class); + if (null != annoSp) { + throw new IllegalStateException("本项目禁止使用UpdateProvider注解.问题Mapper:" + mapperClass.getName()+",问题方法:"+m.getName()); + } + } + + private void checkDelete(Class mapperClass, Method m) { + Delete anno = m.getAnnotation(Delete.class); + if (null != anno) { + throw new IllegalStateException("本项目禁止将sql写在Mybatis注解中.问题Mapper:" + mapperClass.getName()+",问题方法:"+m.getName()); + } + + DeleteProvider annoSp = m.getAnnotation(DeleteProvider.class); + if (null != annoSp) { + throw new IllegalStateException("本项目禁止使用DeleteProvider注解.问题Mapper:" + mapperClass.getName()+",问题方法:"+m.getName()); + } + } + + + private void distroy() { + mybatisMapperStore.clear(); + } + + private MyBatisResource getMapperFile(String mapperFileName) { + return mybatisMapperStore.get(mapperFileName); + } + + private MyBatisResource[] buildMapperLocations(Set> clazzsSet) { + this.initContext(clazzsSet); + + List mapperLocations = this.buildMapperResource(clazzsSet); + + this.addUnmergedResource(mapperLocations); + + this.addCommonSqlClasspathMapper(mapperLocations); + + return mapperLocations.toArray(new MyBatisResource[mapperLocations.size()]); + } + + private List buildMapperResource(Set> clazzsSet) { + int classCount = clazzsSet.size(); + if (classCount == 0) { + return new ArrayList<>(); + } + final MyBatisResource templateResource = this.buildTemplateResource(this.getDbName()); + LOG.debug("使用模板:" + templateResource); + final String globalVmLocation = this.config.getGlobalVmLocation(); + final ClassClient codeClient = new ClassClient(config); + final List mapperLocations = new ArrayList<>(classCount); + + long startTime = System.currentTimeMillis(); + try { + String templateContent = templateResource.getContent(); + for (Class daoClass : clazzsSet) { + String xml = codeClient.genMybatisXml(daoClass, templateContent, globalVmLocation); + xml = mergeExtMapperFile(daoClass, xml); + saveMapper(daoClass.getSimpleName() + FastmybatisConstants.XML_SUFFIX, xml); + mapperLocations.add(MyBatisResource.build(xml, daoClass)); + } + + long endTime = System.currentTimeMillis(); + LOG.debug("生成Mapper内容总耗时:" + (endTime - startTime) / 1000.0 + "秒"); + return mapperLocations; + } catch (Exception e) { + LOG.error(e.getMessage(), e); + throw new GenCodeException(e); + } + + } + + private List buildMapperNames(Set> clazzsSet) { + List list = new ArrayList<>(clazzsSet.size()); + for (Class mapperClass : clazzsSet) { + list.add(mapperClass.getSimpleName()); + } + return list; + } + + private void initContext(Set> clazzsSet) { + mapperClasses.addAll(clazzsSet); + mapperNames = this.buildMapperNames(clazzsSet); + for (Class mapperClass : clazzsSet) { + ExtContext.addMapperClass(mapperClass); + } + } + + public Set> getMapperClasses() { + return mapperClasses; + } + + /** + * 保存mapper到本地文件夹 + * + * @throws IOException + */ + private void saveMapper(String filename, final String content) throws IOException { + String saveDir = config.getMapperSaveDir(); + if (StringUtil.hasText(saveDir)) { + String path = saveDir + "/" + filename; + LOG.debug("保存mapper文件到" + path); + try (OutputStream out = new FileOutputStream(path)) { + IOUtil.copy(IOUtil.toInputStream(content, StandardCharsets.UTF_8), out); + } catch (IOException e) { + throw e; + } + } + } + + private MyBatisResource buildTemplateResource(String dialect) { + // mysql.vm + String templateFileName = this.buildTemplateFileName(dialect); + // 优先使用classpath根目录下的vm模板 + MyBatisResource myBatisResource = MyBatisResource.buildFromClasspath(templateFileName); + if (myBatisResource.exists()) { + return myBatisResource; + } + String templateClasspath = config.getTemplateClasspath(); + if (StringUtil.isEmpty(templateClasspath)) { + templateClasspath = FastmybatisConstants.DEFAULT_CLASS_PATH; + } + // 返回格式:classpath路径 + 数据库名称 + 文件后缀 + // 如:/fastmybatis/tpl/mysql.vm + String location = templateClasspath + templateFileName; + return MyBatisResource.buildFromClasspath(location); + } + + /** + * 构建文件名 + */ + private String buildTemplateFileName(String dialect) { + dialect = dialect.replaceAll("\\s", "").toLowerCase(); + return dialect + FastmybatisConstants.TEMPLATE_SUFFIX; + } + + private void addCommonSqlClasspathMapper(List mapperLocations) { + String commonSqlClasspath = config.getCommonSqlClasspath(); + MyBatisResource myBatisResource = MyBatisResource.buildFromClasspath(commonSqlClasspath); + mapperLocations.add(myBatisResource); + } + + /** + * 合并其它mapper + */ + private void addUnmergedResource(List mapperLocations) { + Collection mapperResourceDefinitions = this.mybatisMapperStore.values(); + for (MyBatisResource mapperResourceDefinition : mapperResourceDefinitions) { + if (mapperResourceDefinition.isMerged()) { + continue; + } + LOG.debug("加载未合并Mapper:" + mapperResourceDefinition.getFilename()); + mapperLocations.add(mapperResourceDefinition); + } + } + + /** + * 合并扩展mapper文件内容 + * + * @throws DocumentException + * @throws IOException + */ + private String mergeExtMapperFile(Class mapperClass, String xml) throws IOException, DocumentException { + // 自定义文件 + String mapperFileName = mapperClass.getSimpleName() + FastmybatisConstants.XML_SUFFIX; + // 先找跟自己同名的xml,如:UserMapper.java -> UserMapper.xml + MyBatisResource myBatisResource = this.getMapperFile(mapperFileName); + StringBuilder extXml = new StringBuilder(); + + if (myBatisResource != null) { + // 追加内容 + String extFileContent = MybatisFileUtil.getExtFileContent(myBatisResource.getInputStream()); + extXml.append(extFileContent); + + myBatisResource.setMerged(true); + } + // 再找namespace一样的xml String otherMapperXml = this.buildOtherMapperContent(mapperClass, this.mybatisMapperStore.values()); extXml.append(otherMapperXml); - - xml = xml.replace(FastmybatisConstants.EXT_MAPPER_PLACEHOLDER, extXml.toString()); - - return xml; - } - - /** - 一个Mapper.java可以对应多个Mapper.xml。只要namespace相同,就会把它们的内容合并,最终形成一个完整的MapperResource
- 这样做的好处是每人维护一个文件相互不干扰,至少在提交代码是不会冲突,同时也遵循了开闭原则。 - * @throws IOException - * @throws DocumentException - */ - private String buildOtherMapperContent(Class mapperClass, Collection mapperResourceDefinitions) throws IOException, DocumentException { - StringBuilder xml = new StringBuilder(); - String trueNamespace = mapperClass.getName(); - for (MyBatisResource mapperResourceDefinition : mapperResourceDefinitions) { - String filename = mapperResourceDefinition.getFilename(); - filename = filename.substring(0, filename.length() - 4); - if(mapperResourceDefinition.isMerged() || mapperNames.contains(filename)) { + + xml = xml.replace(FastmybatisConstants.EXT_MAPPER_PLACEHOLDER, extXml.toString()); + + return xml; + } + + /** + * 一个Mapper.java可以对应多个Mapper.xml。只要namespace相同,就会把它们的内容合并,最终形成一个完整的MapperResource
+ * 这样做的好处是每人维护一个文件相互不干扰,至少在提交代码是不会冲突,同时也遵循了开闭原则。 + * + * @throws IOException + * @throws DocumentException + */ + private String buildOtherMapperContent(Class mapperClass, Collection mapperResourceDefinitions) throws IOException, DocumentException { + StringBuilder xml = new StringBuilder(); + String trueNamespace = mapperClass.getName(); + for (MyBatisResource mapperResourceDefinition : mapperResourceDefinitions) { + String filename = mapperResourceDefinition.getFilename(); + filename = filename.substring(0, filename.length() - 4); + if (mapperResourceDefinition.isMerged() || mapperNames.contains(filename)) { continue; } InputStream in = mapperResourceDefinition.getInputStream(); Document document = this.buildSAXReader().read(in); Element mapperNode = document.getRootElement(); - + Attribute attrNamespace = mapperNode.attribute(FastmybatisConstants.ATTR_NAMESPACE); String namespaceValue = attrNamespace == null ? null : attrNamespace.getValue(); - - if(StringUtil.isEmpty(namespaceValue)) { + + if (StringUtil.isEmpty(namespaceValue)) { throw new MapperFileException("Mapper文件[" + mapperResourceDefinition.getFilename() + "]的namespace不能为空。"); } - - if(trueNamespace.equals(namespaceValue)) { + + if (trueNamespace.equals(namespaceValue)) { String contentXml = MybatisFileUtil.trimMapperNode(mapperNode); xml.append(contentXml); mapperResourceDefinition.setMerged(true); } } - return xml.toString(); - - } - - private SAXReader buildSAXReader() { - SAXReader reader = new SAXReader(); - reader.setEncoding(FastmybatisConstants.ENCODE); - try { - reader.setFeature(FastmybatisConstants.SAXREADER_FEATURE, false); + return xml.toString(); + + } + + private SAXReader buildSAXReader() { + SAXReader reader = new SAXReader(); + reader.setEncoding(FastmybatisConstants.ENCODE); + try { + reader.setFeature(FastmybatisConstants.SAXREADER_FEATURE, false); } catch (SAXException e) { LOG.error("reader.setFeature fail by ", e); } - return reader; - } + return reader; + } - public void setConfig(FastmybatisConfig config) { - this.config = config; - } + public void setConfig(FastmybatisConfig config) { + this.config = config; + } - public String getDbName() { - return dialect; - } + public String getDbName() { + return dialect; + } - public void setDbName(String dialect) { - this.dialect = dialect; - } + public void setDbName(String dialect) { + this.dialect = dialect; + } - public void setMapperExecutorPoolSize(int poolSize) { - config.setMapperExecutorPoolSize(poolSize); - } + public void setMapperExecutorPoolSize(int poolSize) { + config.setMapperExecutorPoolSize(poolSize); + } - public FastmybatisConfig getConfig() { - return config; - } + public FastmybatisConfig getConfig() { + return config; + } } diff --git a/fastmybatis-demo/fastmybatis-demo-springboot/src/main/resources/application.properties b/fastmybatis-demo/fastmybatis-demo-springboot/src/main/resources/application.properties index a05e27a..1878e83 100644 --- a/fastmybatis-demo/fastmybatis-demo-springboot/src/main/resources/application.properties +++ b/fastmybatis-demo/fastmybatis-demo-springboot/src/main/resources/application.properties @@ -15,7 +15,7 @@ spring.datasource.password=${mysql.password} mybatis.mapper-locations=classpath*:mybatis/mapper/*.xml # mybatis config file mybatis.config-location=classpath:mybatis/mybatisConfig.xml -# ???sql????? +# 禁止将sql写在注解中 mybatis.disable-sql-annotation=true # \u81EA\u52A8\u586B\u5145\u65F6\u95F4 diff --git a/fastmybatis-demo/fastmybatis-demo-springmvc/src/main/resources/spring/database-config.xml b/fastmybatis-demo/fastmybatis-demo-springmvc/src/main/resources/spring/database-config.xml index 7c1db48..431b7cd 100644 --- a/fastmybatis-demo/fastmybatis-demo-springmvc/src/main/resources/spring/database-config.xml +++ b/fastmybatis-demo/fastmybatis-demo-springmvc/src/main/resources/spring/database-config.xml @@ -66,6 +66,8 @@ + + diff --git a/fastmybatis-spring/src/main/java/com/gitee/fastmybatis/core/ext/SqlSessionFactoryBeanExt.java b/fastmybatis-spring/src/main/java/com/gitee/fastmybatis/core/ext/SqlSessionFactoryBeanExt.java index 3aa8010..0a6bb00 100644 --- a/fastmybatis-spring/src/main/java/com/gitee/fastmybatis/core/ext/SqlSessionFactoryBeanExt.java +++ b/fastmybatis-spring/src/main/java/com/gitee/fastmybatis/core/ext/SqlSessionFactoryBeanExt.java @@ -38,11 +38,6 @@ public class SqlSessionFactoryBeanExt extends SqlSessionFactoryBean { private String basePackage; - /** - * 是否禁止将sql写到mybatis的原生注解中,如禁止启动报错 - * - */ - private boolean disableSqlAnnotation = false; private String dialect; @@ -118,15 +113,6 @@ public class SqlSessionFactoryBeanExt extends SqlSessionFactoryBean { return mapperLocationsBuilder.getConfig(); } - - public boolean isDisableSqlAnnotation() { - return disableSqlAnnotation; - } - - public void setDisableSqlAnnotation(boolean disableSqlAnnotation) { - this.disableSqlAnnotation = disableSqlAnnotation; - } - public Resource[] getMapperLocations() { return mapperLocations; } -- Gitee From 2f4a73b95d77aeeb21d732de3984f579e938f7e1 Mon Sep 17 00:00:00 2001 From: fanbeibei Date: Thu, 27 Apr 2023 21:10:46 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E5=8E=BB=E6=8E=89import=20*?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fastmybatis/core/ext/MapperLocationsBuilder.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/fastmybatis-core/src/main/java/com/gitee/fastmybatis/core/ext/MapperLocationsBuilder.java b/fastmybatis-core/src/main/java/com/gitee/fastmybatis/core/ext/MapperLocationsBuilder.java index 38b331f..d66632d 100644 --- a/fastmybatis-core/src/main/java/com/gitee/fastmybatis/core/ext/MapperLocationsBuilder.java +++ b/fastmybatis-core/src/main/java/com/gitee/fastmybatis/core/ext/MapperLocationsBuilder.java @@ -10,7 +10,14 @@ import com.gitee.fastmybatis.core.ext.spi.SpiContext; import com.gitee.fastmybatis.core.util.IOUtil; import com.gitee.fastmybatis.core.util.MybatisFileUtil; import com.gitee.fastmybatis.core.util.StringUtil; -import org.apache.ibatis.annotations.*; +import org.apache.ibatis.annotations.Delete; +import org.apache.ibatis.annotations.DeleteProvider; +import org.apache.ibatis.annotations.Insert; +import org.apache.ibatis.annotations.InsertProvider; +import org.apache.ibatis.annotations.Select; +import org.apache.ibatis.annotations.SelectProvider; +import org.apache.ibatis.annotations.Update; +import org.apache.ibatis.annotations.UpdateProvider; import org.apache.ibatis.logging.Log; import org.apache.ibatis.logging.LogFactory; import org.dom4j.Attribute; -- Gitee