├── LICENSE ├── README.md ├── lit-code ├── pom.xml └── src │ ├── main │ └── java │ │ └── com │ │ └── github │ │ └── lit │ │ └── code │ │ ├── CodeGeneration.java │ │ ├── config │ │ ├── Configuration.java │ │ ├── ConfigurationBuilder.java │ │ └── JdbcConfig.java │ │ ├── context │ │ ├── Column.java │ │ ├── ConfigConst.java │ │ ├── GenerationException.java │ │ ├── Table.java │ │ └── Task.java │ │ ├── datebase │ │ ├── DataBaseProvider.java │ │ ├── DateBaseProviderFactory.java │ │ └── MySqlProvider.java │ │ ├── executor │ │ └── GenerationExecutor.java │ │ ├── parser │ │ ├── ConfigParser.java │ │ ├── ConstantParser.java │ │ ├── ConverterParser.java │ │ ├── JdbcParser.java │ │ ├── TableParser.java │ │ └── TasksParser.java │ │ ├── plugin │ │ ├── PluginExecutor.java │ │ └── SerialVersionUIDPlugin.java │ │ └── util │ │ ├── DBUtils.java │ │ └── FileUtils.java │ └── test │ ├── java │ └── com │ │ └── github │ │ └── lit │ │ └── code │ │ └── Generation.java │ └── resources │ ├── code.json │ └── templates │ ├── client.vm │ ├── mapper.vm │ ├── model.vm │ ├── qo.vm │ ├── rest.vm │ ├── service.vm │ ├── serviceImpl.vm │ └── xmlMapper.vm ├── lit-starters ├── lit-starter-jdbc │ ├── pom.xml │ └── src │ │ └── main │ │ ├── java │ │ └── com │ │ │ └── github │ │ │ └── lit │ │ │ └── starter │ │ │ └── jdbc │ │ │ └── JdbcSupportAutoConfiguration.java │ │ └── resources │ │ └── META-INF │ │ └── spring.factories └── pom.xml ├── lit-support ├── pom.xml └── src │ ├── main │ └── java │ │ └── com │ │ └── github │ │ └── lit │ │ └── support │ │ ├── data │ │ ├── AbstractSQL.java │ │ ├── Condition.java │ │ ├── Logic.java │ │ ├── SQL.java │ │ ├── SQLUtils.java │ │ ├── domain │ │ │ ├── Page.java │ │ │ ├── PageInfo.java │ │ │ ├── PageRequest.java │ │ │ ├── PageUtils.java │ │ │ ├── Pageable.java │ │ │ ├── Sort.java │ │ │ └── TableMetaDate.java │ │ ├── jdbc │ │ │ ├── AnnotationRowMapper.java │ │ │ ├── EnableJdbcSupport.java │ │ │ ├── JdbcRepository.java │ │ │ ├── JdbcRepositoryImpl.java │ │ │ └── JdbcSupportConfigure.java │ │ └── mybatis │ │ │ ├── BaseMapper.java │ │ │ ├── BaseSqlProvider.java │ │ │ ├── EnambeMybatisSupport.java │ │ │ ├── MyBatisSupportConfigure.java │ │ │ └── ResultMapInterceptor.java │ │ ├── exception │ │ ├── BizException.java │ │ ├── ExceptionDefinition.java │ │ ├── LitException.java │ │ └── SysException.java │ │ └── util │ │ ├── ClassUtils.java │ │ ├── DateTimeUtils.java │ │ ├── NameUtils.java │ │ ├── PropertyUtils.java │ │ ├── RandomUtils.java │ │ ├── SpelUtils.java │ │ ├── SpringContextUtils.java │ │ ├── TokenUtils.java │ │ ├── UUIDUtils.java │ │ ├── bean │ │ ├── BeanUtils.java │ │ └── IntrospectionCache.java │ │ ├── lamabda │ │ ├── SerializedFunction.java │ │ └── SerializedLambdaUtils.java │ │ └── secret │ │ ├── BCrypt.java │ │ └── EncryptUtils.java │ └── test │ ├── java │ └── com │ │ └── github │ │ └── lit │ │ └── support │ │ ├── configure │ │ └── SpringTestConfigure.java │ │ ├── jdbc │ │ └── JdbcRepositoryTest.java │ │ ├── model │ │ ├── Goods.java │ │ ├── GoodsCondition.java │ │ ├── ProductCondition.java │ │ └── SignProduct.java │ │ └── mybatis │ │ ├── GoodsMapper.java │ │ ├── MapperTest.java │ │ └── MybatisConfig.java │ └── resources │ └── sql │ └── init_schema.sql └── pom.xml /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # lit 工具集合 2 | 3 | > 此工具集是工作中对一些框架的封装, 简便使用 4 | 5 | ### 内容 6 | 7 | - lit-jdbc: 对spring jdbc 的封装, 自动完成常用增删改查操作, 简便sql拼写 8 | - lit-mybatis: 对mybatis封装了BaseMapper, 方便操作 9 | 10 | ### 如何使用 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /lit-code/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | lit 7 | com.github.liulus 8 | 2.5.0 9 | 10 | 4.0.0 11 | 12 | lit-code 13 | 14 | 15 | 16 | com.github.liulus 17 | lit-support 18 | ${project.version} 19 | 20 | 21 | 22 | com.google.code.gson 23 | gson 24 | 2.8.5 25 | 26 | 27 | 28 | org.apache.velocity 29 | velocity 30 | 1.7 31 | 32 | 33 | 34 | mysql 35 | mysql-connector-java 36 | test 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /lit-code/src/main/java/com/github/lit/code/CodeGeneration.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.code; 2 | 3 | import com.github.lit.code.config.Configuration; 4 | import com.github.lit.code.config.ConfigurationBuilder; 5 | import com.github.lit.code.context.GenerationException; 6 | import com.github.lit.code.datebase.DataBaseProvider; 7 | import com.github.lit.code.datebase.DateBaseProviderFactory; 8 | import com.github.lit.code.executor.GenerationExecutor; 9 | import com.github.lit.code.parser.ConfigParser; 10 | 11 | import java.util.logging.Logger; 12 | 13 | /** 14 | * User : liulu 15 | * Date : 2018/2/6 15:03 16 | * version $Id: CodeGeneration.java, v 0.1 Exp $ 17 | */ 18 | public class CodeGeneration { 19 | 20 | private static final Logger LOGGER = Logger.getLogger(CodeGeneration.class.getName()); 21 | 22 | public static void run() { 23 | run("code.json"); 24 | } 25 | 26 | public static void run(String configFile) { 27 | if (configFile == null || configFile.length() == 0) { 28 | throw new GenerationException("配置文件名称不能为空"); 29 | } 30 | Configuration configuration = ConfigurationBuilder.build(configFile); 31 | GenerationExecutor.execute(configuration); 32 | } 33 | 34 | public static void registerParser(ConfigParser configParser) { 35 | ConfigurationBuilder.registerParser(configParser); 36 | } 37 | 38 | public static void registerProvider(DataBaseProvider dataBaseProvider) { 39 | DateBaseProviderFactory.registerProvider(dataBaseProvider); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /lit-code/src/main/java/com/github/lit/code/config/Configuration.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.code.config; 2 | 3 | import com.github.lit.code.context.Table; 4 | import com.github.lit.code.context.Task; 5 | import lombok.Getter; 6 | import lombok.Setter; 7 | import lombok.ToString; 8 | 9 | import java.math.BigDecimal; 10 | import java.sql.JDBCType; 11 | import java.util.Date; 12 | import java.util.HashMap; 13 | import java.util.Map; 14 | import java.util.concurrent.ConcurrentHashMap; 15 | 16 | /** 17 | * User : liulu 18 | * Date : 2018/2/6 16:26 19 | * version $Id: Configuration.java, v 0.1 Exp $ 20 | */ 21 | @Getter 22 | @Setter 23 | @ToString 24 | public class Configuration { 25 | 26 | /** 27 | * 默认的转换映射 map 28 | */ 29 | private static final Map DEFAULT_CONVERT_MAP = new ConcurrentHashMap<>(); 30 | 31 | /** 32 | * 常量Map 33 | */ 34 | private Map constantMap = new HashMap<>(); 35 | 36 | /** 37 | * jdbcType 和 javaType 转换映射 Map 38 | */ 39 | private Map converterMap = new HashMap<>(); 40 | 41 | /** 42 | * 任务Map 43 | */ 44 | private Map taskMap = new HashMap<>(); 45 | 46 | /** 47 | * jdbc连接 48 | */ 49 | private JdbcConfig jdbcConfig; 50 | 51 | /** 52 | * 表配置 53 | */ 54 | private Table table; 55 | 56 | 57 | static { 58 | DEFAULT_CONVERT_MAP.put(JDBCType.REAL.getName(), Float.class.getName()); 59 | DEFAULT_CONVERT_MAP.put(JDBCType.DECIMAL.getName(), BigDecimal.class.getName()); 60 | DEFAULT_CONVERT_MAP.put(JDBCType.NUMERIC.getName(), BigDecimal.class.getName()); 61 | DEFAULT_CONVERT_MAP.put(JDBCType.CHAR.getName(), String.class.getName()); 62 | DEFAULT_CONVERT_MAP.put(JDBCType.LONGVARCHAR.getName(), String.class.getName()); 63 | DEFAULT_CONVERT_MAP.put(JDBCType.CLOB.getName(), String.class.getName()); 64 | DEFAULT_CONVERT_MAP.put(JDBCType.BINARY.getName(), Byte.class.getName() + "[]"); 65 | DEFAULT_CONVERT_MAP.put(JDBCType.VARBINARY.getName(), Byte.class.getName() + "[]"); 66 | DEFAULT_CONVERT_MAP.put(JDBCType.LONGVARBINARY.getName(), Byte.class.getName() + "[]"); 67 | DEFAULT_CONVERT_MAP.put(JDBCType.BLOB.getName(), Byte.class.getName() + "[]"); 68 | DEFAULT_CONVERT_MAP.put(JDBCType.DATE.getName(), Date.class.getName()); 69 | DEFAULT_CONVERT_MAP.put(JDBCType.TIME.getName(), Date.class.getName()); 70 | DEFAULT_CONVERT_MAP.put(JDBCType.TIMESTAMP.getName(), Date.class.getName()); 71 | 72 | // mySql 73 | DEFAULT_CONVERT_MAP.put("TINYTEXT", String.class.getName()); 74 | DEFAULT_CONVERT_MAP.put("TEXT", String.class.getName()); 75 | DEFAULT_CONVERT_MAP.put("LONGTEXT", String.class.getName()); 76 | } 77 | 78 | 79 | public void addConstant(String key, String value) { 80 | constantMap.put(key, value); 81 | } 82 | 83 | public String getConstant(String key) { 84 | return constantMap.get(key); 85 | } 86 | 87 | public String getConstant(String key, String defaultValue) { 88 | String value = constantMap.get(key); 89 | if (value == null || value.length() == 0) { 90 | value = defaultValue; 91 | } 92 | return value; 93 | } 94 | 95 | public Boolean getBooleanConstant(String key) { 96 | String value = constantMap.get(key); 97 | if (value == null || value.length() == 0) { 98 | return false; 99 | } 100 | return Boolean.valueOf(value); 101 | } 102 | 103 | public Boolean getBooleanConstant(String key, Boolean defaultValue) { 104 | String value = constantMap.get(key); 105 | if (value == null || value.length() == 0) { 106 | return defaultValue; 107 | } 108 | return Boolean.valueOf(value); 109 | } 110 | 111 | public void addTask(Task task) { 112 | if (task == null) { 113 | return; 114 | } 115 | taskMap.put(task.getName(), task); 116 | } 117 | 118 | public Task getTask(String key) { 119 | return taskMap.get(key); 120 | } 121 | 122 | public void addConverter(String key, String value) { 123 | converterMap.put(key, value); 124 | } 125 | 126 | public String getConverter(String key) { 127 | String value = converterMap.get(key); 128 | if (value == null || value.isEmpty()) { 129 | value = DEFAULT_CONVERT_MAP.get(key); 130 | } 131 | return value; 132 | } 133 | 134 | } 135 | -------------------------------------------------------------------------------- /lit-code/src/main/java/com/github/lit/code/config/ConfigurationBuilder.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.code.config; 2 | 3 | import com.github.lit.code.context.ConfigConst; 4 | import com.github.lit.code.context.GenerationException; 5 | import com.github.lit.code.parser.*; 6 | import com.github.lit.support.util.ClassUtils; 7 | import com.github.lit.support.util.TokenUtils; 8 | import com.google.gson.JsonElement; 9 | import com.google.gson.JsonObject; 10 | import com.google.gson.JsonParser; 11 | 12 | import java.io.InputStream; 13 | import java.io.InputStreamReader; 14 | import java.util.ArrayList; 15 | import java.util.List; 16 | import java.util.Map; 17 | import java.util.logging.Logger; 18 | 19 | /** 20 | * User : liulu 21 | * Date : 2018/2/7 14:49 22 | * version $Id: ConfigurationBuilder.java, v 0.1 Exp $ 23 | */ 24 | public class ConfigurationBuilder { 25 | 26 | private static final Logger LOGGER = Logger.getLogger(ConfigurationBuilder.class.getName()); 27 | 28 | private static final List CONFIG_PARSERS = new ArrayList<>(); 29 | 30 | static { 31 | // CONFIG_PARSERS.add(new ConstantParser()); 32 | CONFIG_PARSERS.add(new JdbcParser()); 33 | CONFIG_PARSERS.add(new ConverterParser()); 34 | CONFIG_PARSERS.add(new TableParser()); 35 | CONFIG_PARSERS.add(new TasksParser()); 36 | } 37 | 38 | public static Configuration build(String configFile) { 39 | if (configFile.startsWith("/")) { 40 | configFile = configFile.substring(1); 41 | } 42 | InputStream inputStream = ClassUtils.getDefaultClassLoader().getResourceAsStream(configFile); 43 | if (inputStream == null) { 44 | throw new GenerationException(String.format("未能找到配置文件 %s, 请确认该文件放在 classpath 路径下", configFile)); 45 | } 46 | 47 | Configuration configuration = new Configuration(); 48 | JsonElement rootElement = new JsonParser().parse(new InputStreamReader(inputStream)); 49 | if (rootElement.isJsonArray()) { 50 | throw new GenerationException("配置文件不能是数组"); 51 | } 52 | 53 | // 提前解析出所有的常量 54 | JsonObject constant = rootElement.getAsJsonObject().getAsJsonObject().getAsJsonObject(ConfigConst.CONSTANT); 55 | for (Map.Entry entry : constant.entrySet()) { 56 | configuration.addConstant(entry.getKey(), entry.getValue().getAsString()); 57 | } 58 | 59 | // 替换 json 配置中的 ${} 占位符 60 | String rootConfigJson = TokenUtils.parseToken(configuration.getConstantMap(), rootElement.toString()); 61 | JsonObject rootObject = new JsonParser().parse(rootConfigJson).getAsJsonObject(); 62 | 63 | LOGGER.info("开始解析配置文件: " + configFile); 64 | for (ConfigParser configParser : CONFIG_PARSERS) { 65 | JsonElement jsonElement = rootObject.get(configParser.getConfigKey()); 66 | if (jsonElement != null) { 67 | configParser.parser(configuration, jsonElement); 68 | } 69 | } 70 | LOGGER.info("完成配置文件: " + configFile + " 的解析!"); 71 | return configuration; 72 | } 73 | 74 | 75 | public static void registerParser(ConfigParser configParser) { 76 | CONFIG_PARSERS.add(configParser); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /lit-code/src/main/java/com/github/lit/code/config/JdbcConfig.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.code.config; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import lombok.ToString; 6 | 7 | import java.io.Serializable; 8 | 9 | /** 10 | * User : liulu 11 | * Date : 2018/2/6 16:28 12 | * version $Id: JdbcConfig.java, v 0.1 Exp $ 13 | */ 14 | @Getter 15 | @Setter 16 | @ToString 17 | public class JdbcConfig implements Serializable{ 18 | 19 | private static final long serialVersionUID = -488479893077026027L; 20 | 21 | private String dbName; 22 | 23 | private String driverClass; 24 | 25 | private String url; 26 | 27 | private String user; 28 | 29 | private String password; 30 | } 31 | -------------------------------------------------------------------------------- /lit-code/src/main/java/com/github/lit/code/context/Column.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.code.context; 2 | 3 | import com.github.lit.support.util.NameUtils; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | 8 | import java.io.Serializable; 9 | 10 | /** 11 | * User : liulu 12 | * Date : 2018/2/8 11:34 13 | * version $Id: Column.java, v 0.1 Exp $ 14 | */ 15 | @Getter 16 | @Setter 17 | @ToString 18 | public class Column implements Serializable { 19 | 20 | private static final long serialVersionUID = 4076352228046456676L; 21 | 22 | private String name; 23 | 24 | private Integer displaySize; 25 | 26 | private Integer scale; 27 | 28 | private String comment; 29 | 30 | private Boolean primaryKey; 31 | 32 | private Boolean autoIncrement; 33 | 34 | private String jdbcType; 35 | 36 | private String javaType; 37 | 38 | private String javaClass; 39 | 40 | public String getCamelName() { 41 | return NameUtils.getCamelName(name); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /lit-code/src/main/java/com/github/lit/code/context/ConfigConst.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.code.context; 2 | 3 | /** 4 | * User : liulu 5 | * Date : 2018/3/6 16:36 6 | * version $Id: ConfigConst.java, v 0.1 Exp $ 7 | */ 8 | public interface ConfigConst { 9 | 10 | String CONSTANT = "constant"; 11 | 12 | String JDBC = "jdbc"; 13 | 14 | String CONVERTER = "converter"; 15 | 16 | String TABLE = "table"; 17 | 18 | String TASKS = "tasks"; 19 | 20 | 21 | 22 | } 23 | -------------------------------------------------------------------------------- /lit-code/src/main/java/com/github/lit/code/context/GenerationException.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.code.context; 2 | 3 | /** 4 | * User : liulu 5 | * Date : 2018/2/7 14:36 6 | * version $Id: GenerationException.java, v 0.1 Exp $ 7 | */ 8 | public class GenerationException extends RuntimeException{ 9 | 10 | private static final long serialVersionUID = 6061456844067018240L; 11 | 12 | public GenerationException() { 13 | super(); 14 | } 15 | 16 | public GenerationException(String message) { 17 | super(message); 18 | } 19 | 20 | public GenerationException(String message, Throwable cause) { 21 | super(message, cause); 22 | } 23 | 24 | public GenerationException(Throwable cause) { 25 | super(cause); 26 | } 27 | 28 | protected GenerationException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { 29 | super(message, cause, enableSuppression, writableStackTrace); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /lit-code/src/main/java/com/github/lit/code/context/Table.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.code.context; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import lombok.ToString; 6 | 7 | import java.io.Serializable; 8 | import java.util.HashSet; 9 | import java.util.List; 10 | import java.util.Set; 11 | 12 | /** 13 | * User : liulu 14 | * Date : 2018/2/7 18:51 15 | * version $Id: Table.java, v 0.1 Exp $ 16 | */ 17 | @Getter 18 | @Setter 19 | @ToString 20 | public class Table implements Serializable { 21 | 22 | private static final long serialVersionUID = -3416826548050707151L; 23 | 24 | private String catalog; 25 | 26 | private String schema; 27 | 28 | private String quoteString; 29 | 30 | private String name; 31 | 32 | private String primaryKey; 33 | 34 | private String desc; 35 | 36 | private List columns; 37 | 38 | private List tasks; 39 | 40 | 41 | public String getFullTableName() { 42 | String result = " "; 43 | if (catalog != null && !catalog.isEmpty()) { 44 | result += catalog + "."; 45 | } 46 | 47 | if (schema != null && !schema.isEmpty()) { 48 | result += schema + "."; 49 | } 50 | 51 | return result + quoteString + name + quoteString + " "; 52 | 53 | 54 | } 55 | 56 | public Set getImportClasses() { 57 | 58 | Set importClasses = new HashSet<>(); 59 | 60 | for (Column column : columns) { 61 | if (!column.getJavaClass().startsWith("java.lang")) { 62 | importClasses.add(column.getJavaClass()); 63 | } 64 | } 65 | 66 | return importClasses; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /lit-code/src/main/java/com/github/lit/code/context/Task.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.code.context; 2 | 3 | import com.github.lit.support.util.NameUtils; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | 8 | import java.io.File; 9 | import java.io.Serializable; 10 | import java.util.List; 11 | import java.util.logging.Logger; 12 | 13 | /** 14 | * User : liulu 15 | * Date : 2018/2/7 17:02 16 | * version $Id: Task.java, v 0.1 Exp $ 17 | */ 18 | @Getter 19 | @Setter 20 | @ToString 21 | public class Task implements Serializable { 22 | 23 | private static final Logger LOGGER = Logger.getLogger(Task.class.getName()); 24 | 25 | private static final long serialVersionUID = 5454351511354251547L; 26 | 27 | private String name; 28 | 29 | private String tableName; 30 | 31 | private String generateClass; 32 | 33 | private String template; 34 | 35 | private String prefixRemove = ""; 36 | 37 | private String suffixRemove = ""; 38 | 39 | private String delimiter = "_"; 40 | 41 | private String prefixAdd = ""; 42 | 43 | private String suffixAdd = ""; 44 | 45 | private String fileType = ".java"; 46 | 47 | private Boolean upperCase = false; 48 | 49 | private Boolean lowerCase = false; 50 | 51 | private Boolean camel = false; 52 | 53 | private String fileSeparator = ""; 54 | 55 | private String module = ""; 56 | 57 | private String srcDir = "src/main/java"; 58 | 59 | private String _package = ""; 60 | 61 | private List plugins; 62 | 63 | 64 | public String getShortClassName() { 65 | String resultName = NameUtils.getFirstUpperName(NameUtils.getCamelName(tableName, delimiter)); 66 | return prefixAdd + resultName + suffixAdd; 67 | } 68 | 69 | public String getLongClassName() { 70 | return _package + "." + getShortClassName(); 71 | } 72 | 73 | public String getFirstLowerClassName() { 74 | if (prefixAdd == null || prefixAdd.isEmpty()) { 75 | return NameUtils.getCamelName(tableName) + suffixAdd; 76 | } 77 | return NameUtils.getFirstLowerName(getShortClassName()); 78 | } 79 | 80 | public String getUnderLineSplitName() { 81 | return NameUtils.getLowerDelimiterName(getShortClassName(), "_"); 82 | } 83 | 84 | public String getMiddleLineSplitName() { 85 | return NameUtils.getLowerDelimiterName(getShortClassName(), "-"); 86 | } 87 | 88 | public String getPathSplitName() { 89 | return NameUtils.getLowerDelimiterName(getShortClassName(), "/"); 90 | } 91 | 92 | public String getUpperName() { 93 | return getShortClassName().toUpperCase(); 94 | } 95 | 96 | public String getLowerName() { 97 | return getShortClassName().toLowerCase(); 98 | } 99 | 100 | 101 | public String processTableName(String tableName) { 102 | if (prefixRemove != null && !prefixRemove.isEmpty()) { 103 | if (tableName.startsWith(prefixRemove)) { 104 | tableName = tableName.substring(prefixRemove.length()); 105 | } else { 106 | LOGGER.warning(String.format("table %s 设置移除的前缀 %s 无效!", tableName, prefixRemove)); 107 | } 108 | } 109 | if (suffixRemove != null && !suffixRemove.isEmpty()) { 110 | if (tableName.endsWith(suffixRemove)) { 111 | tableName = tableName.substring(0, tableName.length() - suffixRemove.length()); 112 | } 113 | } 114 | if (tableName.startsWith(delimiter)) { 115 | tableName = tableName.substring(delimiter.length()); 116 | } 117 | if (tableName.endsWith(delimiter)) { 118 | tableName = tableName.substring(0, tableName.length() - delimiter.length()); 119 | } 120 | return tableName; 121 | } 122 | 123 | 124 | public String getFileName() { 125 | 126 | String resultName = null; 127 | 128 | if (camel) { 129 | resultName = getShortClassName(); 130 | } else if (upperCase) { 131 | resultName = prefixAdd + (tableName.replace(delimiter, fileSeparator)).toUpperCase() + suffixAdd; 132 | } else if (lowerCase) { 133 | resultName = prefixAdd + (tableName.replace(delimiter, fileSeparator)).toLowerCase() + suffixAdd; 134 | } 135 | 136 | // 默认设置为首字母大写驼峰 137 | if (resultName == null) { 138 | resultName = getShortClassName(); 139 | } 140 | 141 | String longName = (get_package() + "." + resultName).replace(".", File.separator); 142 | if (!srcDir.startsWith(File.separator)) { 143 | srcDir = File.separator + srcDir; 144 | } 145 | if (!srcDir.endsWith(File.separator)) { 146 | srcDir = srcDir + File.separator; 147 | } 148 | if (!fileType.startsWith(".")) { 149 | fileType = "." + fileType; 150 | } 151 | return srcDir + longName + fileType; 152 | } 153 | 154 | public String getPackageName() { 155 | return _package; 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /lit-code/src/main/java/com/github/lit/code/datebase/DataBaseProvider.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.code.datebase; 2 | 3 | import com.github.lit.code.context.Table; 4 | 5 | import java.sql.Connection; 6 | import java.sql.SQLException; 7 | import java.util.Map; 8 | 9 | /** 10 | * User : liulu 11 | * Date : 2018/2/10 15:48 12 | * version $Id: DataBaseProvider.java, v 0.1 Exp $ 13 | */ 14 | public interface DataBaseProvider { 15 | 16 | String getDbName(); 17 | 18 | Map getColumnComment(Connection connection, Table table) throws SQLException; 19 | } 20 | -------------------------------------------------------------------------------- /lit-code/src/main/java/com/github/lit/code/datebase/DateBaseProviderFactory.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.code.datebase; 2 | 3 | import java.util.Map; 4 | import java.util.concurrent.ConcurrentHashMap; 5 | 6 | /** 7 | * User : liulu 8 | * Date : 2018/2/10 16:06 9 | * version $Id: DateBaseProviderFactory.java, v 0.1 Exp $ 10 | */ 11 | public class DateBaseProviderFactory { 12 | 13 | private static final Map PROVIDER_MAP = new ConcurrentHashMap<>(); 14 | 15 | static { 16 | registerProvider(new MySqlProvider()); 17 | } 18 | 19 | public static void registerProvider(DataBaseProvider dataBaseProvider) { 20 | PROVIDER_MAP.put(dataBaseProvider.getDbName().toUpperCase(), dataBaseProvider); 21 | } 22 | 23 | 24 | public static DataBaseProvider getDataBaseProvider(String dbName) { 25 | return PROVIDER_MAP.get(dbName.toUpperCase()); 26 | } 27 | 28 | 29 | 30 | } 31 | -------------------------------------------------------------------------------- /lit-code/src/main/java/com/github/lit/code/datebase/MySqlProvider.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.code.datebase; 2 | 3 | import com.github.lit.code.context.Table; 4 | 5 | import java.sql.Connection; 6 | import java.sql.PreparedStatement; 7 | import java.sql.ResultSet; 8 | import java.sql.SQLException; 9 | import java.util.Map; 10 | import java.util.concurrent.ConcurrentHashMap; 11 | 12 | /** 13 | * User : liulu 14 | * Date : 2018/2/10 15:50 15 | * version $Id: MySqlProvider.java, v 0.1 Exp $ 16 | */ 17 | public class MySqlProvider implements DataBaseProvider { 18 | @Override 19 | public String getDbName() { 20 | return "MYSQL"; 21 | } 22 | 23 | @Override 24 | public Map getColumnComment(Connection connection, Table table) throws SQLException { 25 | 26 | String sql = "select column_name, column_comment from information_schema.columns where table_schema = ? and table_name = ?"; 27 | PreparedStatement ps = connection.prepareStatement(sql); 28 | ps.setString(1, table.getCatalog()); 29 | ps.setString(2, table.getName()); 30 | ResultSet resultSet = ps.executeQuery(); 31 | 32 | Map result = new ConcurrentHashMap<>(); 33 | 34 | while (resultSet.next()) { 35 | result.put(resultSet.getString("column_name").toLowerCase(), resultSet.getString("column_comment")); 36 | } 37 | 38 | return result; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /lit-code/src/main/java/com/github/lit/code/executor/GenerationExecutor.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.code.executor; 2 | 3 | import com.github.lit.code.config.Configuration; 4 | import com.github.lit.code.context.Table; 5 | import com.github.lit.code.context.Task; 6 | import com.github.lit.code.plugin.PluginExecutor; 7 | import com.github.lit.code.util.FileUtils; 8 | import com.github.lit.support.util.ClassUtils; 9 | import org.apache.velocity.VelocityContext; 10 | import org.apache.velocity.app.Velocity; 11 | import org.apache.velocity.context.Context; 12 | 13 | import java.io.File; 14 | import java.io.StringWriter; 15 | import java.util.List; 16 | import java.util.logging.Logger; 17 | 18 | /** 19 | * User : liulu 20 | * Date : 2018/2/7 15:00 21 | * version $Id: GenerationExecutor.java, v 0.1 Exp $ 22 | */ 23 | public class GenerationExecutor { 24 | 25 | private static final Logger LOGGER = Logger.getLogger(GenerationExecutor.class.getName()); 26 | 27 | public static void execute(Configuration configuration) { 28 | 29 | Table table = configuration.getTable(); 30 | Boolean overwrite = configuration.getBooleanConstant("overwrite", true); 31 | Boolean onChildModule = configuration.getBooleanConstant("onChildModule"); 32 | String rootDir = configuration.getConstant("rootDir", System.getProperty("user.dir")); 33 | if (onChildModule) { 34 | rootDir = rootDir.substring(0, rootDir.lastIndexOf(File.separator)); 35 | } 36 | 37 | VelocityContext context = new VelocityContext(); 38 | context.put("table", table); 39 | context.put("constant", configuration.getConstantMap()); 40 | 41 | List tableTasks = table.getTasks(); 42 | for (String tableTask : tableTasks) { 43 | Task task = configuration.getTask(tableTask); 44 | if (task == null) { 45 | continue; 46 | } 47 | task.setTableName(task.processTableName(table.getName())); 48 | context.put(task.getName(), task); 49 | 50 | executePlugin(configuration, context, task); 51 | 52 | String targetDir = rootDir + File.separator + task.getModule(); 53 | String filePath = targetDir + task.getFileName(); 54 | 55 | String templateText = FileUtils.readToString(task.getTemplate()); 56 | 57 | StringWriter stringWriter = new StringWriter(); 58 | Velocity.evaluate(context, stringWriter, "lit-code", templateText); 59 | String resultText = stringWriter.toString(); 60 | FileUtils.writeToFile(resultText, filePath, overwrite); 61 | } 62 | } 63 | 64 | 65 | private static void executePlugin(Configuration configuration, Context context, Task task) { 66 | 67 | List plugins = task.getPlugins(); 68 | if (plugins == null || plugins.isEmpty()) { 69 | return; 70 | } 71 | 72 | for (String plugin : plugins) { 73 | PluginExecutor pluginExecutor = (PluginExecutor) ClassUtils.newInstance(plugin); 74 | pluginExecutor.execute(configuration, context, task); 75 | } 76 | } 77 | 78 | 79 | } 80 | -------------------------------------------------------------------------------- /lit-code/src/main/java/com/github/lit/code/parser/ConfigParser.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.code.parser; 2 | 3 | import com.github.lit.code.config.Configuration; 4 | import com.google.gson.JsonElement; 5 | 6 | /** 7 | * User : liulu 8 | * Date : 2018/2/6 16:31 9 | * version $Id: ConfigParser.java, v 0.1 Exp $ 10 | */ 11 | public interface ConfigParser { 12 | 13 | String getConfigKey(); 14 | 15 | void parser(Configuration configuration, JsonElement jsonElement); 16 | } 17 | -------------------------------------------------------------------------------- /lit-code/src/main/java/com/github/lit/code/parser/ConstantParser.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.code.parser; 2 | 3 | import com.github.lit.code.config.Configuration; 4 | import com.github.lit.code.context.ConfigConst; 5 | import com.google.gson.JsonElement; 6 | 7 | import java.util.Map; 8 | 9 | /** 10 | * User : liulu 11 | * Date : 2018/2/7 15:13 12 | * version $Id: ConstantParser.java, v 0.1 Exp $ 13 | */ 14 | public class ConstantParser implements ConfigParser { 15 | 16 | @Override 17 | public String getConfigKey() { 18 | return ConfigConst.CONSTANT; 19 | } 20 | 21 | @Override 22 | public void parser(Configuration configuration, JsonElement jsonElement) { 23 | if (jsonElement.isJsonArray()) { 24 | return; 25 | } 26 | for (Map.Entry entry : jsonElement.getAsJsonObject().entrySet()) { 27 | String value = entry.getValue().getAsString(); 28 | if (value == null || value.length() == 0 || "null".equals(value)) { 29 | continue; 30 | } 31 | configuration.addConstant(entry.getKey(), value); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /lit-code/src/main/java/com/github/lit/code/parser/ConverterParser.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.code.parser; 2 | 3 | import com.github.lit.code.config.Configuration; 4 | import com.github.lit.code.context.ConfigConst; 5 | import com.github.lit.code.context.GenerationException; 6 | import com.google.gson.JsonElement; 7 | 8 | import java.util.Map; 9 | 10 | /** 11 | * User : liulu 12 | * Date : 2018/2/9 15:12 13 | * version $Id: ConverterParser.java, v 0.1 Exp $ 14 | */ 15 | public class ConverterParser implements ConfigParser { 16 | 17 | @Override 18 | public String getConfigKey() { 19 | return ConfigConst.CONVERTER; 20 | } 21 | 22 | @Override 23 | public void parser(Configuration configuration, JsonElement jsonElement) { 24 | if (jsonElement.isJsonArray()) { 25 | throw new GenerationException("列转换 配置项不能是数组!"); 26 | } 27 | for (Map.Entry entry : jsonElement.getAsJsonObject().entrySet()) { 28 | if (entry.getValue() == null) { 29 | continue; 30 | } 31 | configuration.addConverter(entry.getKey().toUpperCase(), entry.getValue().getAsString()); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /lit-code/src/main/java/com/github/lit/code/parser/JdbcParser.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.code.parser; 2 | 3 | import com.github.lit.code.config.Configuration; 4 | import com.github.lit.code.config.JdbcConfig; 5 | import com.github.lit.code.context.ConfigConst; 6 | import com.github.lit.code.context.GenerationException; 7 | import com.google.gson.Gson; 8 | import com.google.gson.JsonElement; 9 | 10 | /** 11 | * User : liulu 12 | * Date : 2018/2/6 15:10 13 | * version $Id: JdbcParser.java, v 0.1 Exp $ 14 | */ 15 | public class JdbcParser implements ConfigParser { 16 | 17 | @Override 18 | public String getConfigKey() { 19 | return ConfigConst.JDBC; 20 | } 21 | 22 | @Override 23 | public void parser(Configuration configuration, JsonElement jsonElement) { 24 | if (jsonElement.isJsonArray()) { 25 | throw new GenerationException("table 配置项不能是数组!"); 26 | } 27 | 28 | JdbcConfig jdbcConfig = new Gson().fromJson(jsonElement.toString(), JdbcConfig.class); 29 | if (jdbcConfig.getDbName() != null && !jdbcConfig.getDbName().isEmpty()) { 30 | jdbcConfig.setDbName(jdbcConfig.getDbName().toUpperCase()); 31 | } 32 | configuration.setJdbcConfig(jdbcConfig); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /lit-code/src/main/java/com/github/lit/code/parser/TableParser.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.code.parser; 2 | 3 | import com.github.lit.code.config.Configuration; 4 | import com.github.lit.code.config.JdbcConfig; 5 | import com.github.lit.code.context.Column; 6 | import com.github.lit.code.context.ConfigConst; 7 | import com.github.lit.code.context.GenerationException; 8 | import com.github.lit.code.context.Table; 9 | import com.github.lit.code.datebase.DataBaseProvider; 10 | import com.github.lit.code.datebase.DateBaseProviderFactory; 11 | import com.github.lit.code.util.DBUtils; 12 | import com.google.gson.Gson; 13 | import com.google.gson.JsonElement; 14 | 15 | import java.sql.Connection; 16 | import java.sql.PreparedStatement; 17 | import java.sql.ResultSet; 18 | import java.sql.ResultSetMetaData; 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | import java.util.Map; 22 | import java.util.Objects; 23 | import java.util.logging.Logger; 24 | 25 | /** 26 | * User : liulu 27 | * Date : 2018/2/7 18:58 28 | * version $Id: TableParser.java, v 0.1 Exp $ 29 | */ 30 | public class TableParser implements ConfigParser { 31 | 32 | private static final Logger LOGGER = Logger.getLogger(TableParser.class.getName()); 33 | 34 | @Override 35 | public String getConfigKey() { 36 | return ConfigConst.TABLE; 37 | } 38 | 39 | @Override 40 | public void parser(Configuration configuration, JsonElement jsonElement) { 41 | 42 | JdbcConfig jdbcConfig = configuration.getJdbcConfig(); 43 | if (jdbcConfig == null) { 44 | throw new GenerationException("未找到数据库连接配置, 不能解析表信息! 如果不需要解析表信息, 请将配置文件中的 table 配置删除!"); 45 | } 46 | if (jsonElement.isJsonArray()) { 47 | throw new GenerationException("table 配置项不能是数组!"); 48 | } 49 | 50 | Table table = new Gson().fromJson(jsonElement.toString(), Table.class); 51 | configuration.setTable(table); 52 | 53 | // 初始化数据连接 54 | DBUtils.createConnection(configuration.getJdbcConfig()); 55 | initTableMetaData(table); 56 | 57 | // 转换自定义 jdbcType 和 javaType 的映射 58 | for (Column column : table.getColumns()) { 59 | String javaClass = configuration.getConverter(column.getJdbcType()); 60 | if (javaClass != null && !javaClass.isEmpty()) { 61 | column.setJavaClass(javaClass); 62 | } 63 | column.setJavaType(column.getJavaClass().substring(column.getJavaClass().lastIndexOf(".") + 1)); 64 | } 65 | } 66 | 67 | /** 68 | * @param table 69 | */ 70 | private void initTableMetaData(Table table) { 71 | 72 | Connection connection = DBUtils.getConnection(); 73 | try { 74 | if (table.getCatalog() == null || table.getCatalog().isEmpty()) { 75 | table.setCatalog(connection.getCatalog()); 76 | } 77 | if (table.getSchema() == null || table.getSchema().isEmpty()) { 78 | table.setSchema(connection.getSchema()); 79 | } 80 | if (table.getQuoteString() == null || table.getQuoteString().isEmpty()) { 81 | table.setQuoteString(connection.getMetaData().getIdentifierQuoteString()); 82 | } 83 | String dbName = connection.getMetaData().getDatabaseProductName(); 84 | DataBaseProvider provider = DateBaseProviderFactory.getDataBaseProvider(dbName); 85 | Map columnCommentMap = null; 86 | if (provider != null) { 87 | columnCommentMap = provider.getColumnComment(connection, table); 88 | } else { 89 | LOGGER.warning("未能找到 " + dbName + " 数据库查询列备注信息的provider!"); 90 | } 91 | 92 | ResultSet primaryKeys = connection.getMetaData().getPrimaryKeys(table.getCatalog(), table.getSchema(), table.getName()); 93 | while (primaryKeys.next()) { 94 | table.setPrimaryKey(primaryKeys.getString("COLUMN_NAME").toLowerCase()); 95 | } 96 | 97 | String querySql = "select * from" + table.getFullTableName() + "where 1=2"; 98 | LOGGER.info("查询表元数据, 执行sql: " + querySql); 99 | PreparedStatement ps = connection.prepareStatement(querySql); 100 | ResultSetMetaData tableMetaData = ps.executeQuery().getMetaData(); 101 | 102 | List columns = new ArrayList<>(tableMetaData.getColumnCount()); 103 | for (int i = 0; i < tableMetaData.getColumnCount(); i++) { 104 | Column column = new Column(); 105 | column.setName(tableMetaData.getColumnName(i + 1).toLowerCase()); // 列名 - 小写 106 | column.setJdbcType(tableMetaData.getColumnTypeName(i + 1)); // jdbcType eg: VARCHAR 107 | column.setJavaClass(tableMetaData.getColumnClassName(i + 1)); // jdbcType 对应的 javaClass eg: java.lang.String 108 | column.setDisplaySize(tableMetaData.getColumnDisplaySize(i + 1)); 109 | column.setScale(tableMetaData.getScale(i + 1)); 110 | column.setAutoIncrement(tableMetaData.isAutoIncrement(i + 1)); //是否是自增列 111 | // 列备注 112 | if (columnCommentMap != null) { 113 | String comment = columnCommentMap.get(column.getName()); 114 | if (comment != null && !comment.isEmpty()) { 115 | column.setComment(comment); 116 | } 117 | } 118 | // 列是否主键 119 | if (table.getPrimaryKey() == null || table.getPrimaryKey().isEmpty()) { 120 | column.setPrimaryKey(false); 121 | } else { 122 | column.setPrimaryKey(Objects.equals(column.getName(), table.getPrimaryKey())); 123 | } 124 | 125 | columns.add(column); 126 | } 127 | table.setColumns(columns); 128 | } catch (Exception e) { 129 | throw new GenerationException("初始化表元数据信息异常", e); 130 | } finally { 131 | DBUtils.closeConnection(); 132 | } 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /lit-code/src/main/java/com/github/lit/code/parser/TasksParser.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.code.parser; 2 | 3 | import com.github.lit.code.config.Configuration; 4 | import com.github.lit.code.context.ConfigConst; 5 | import com.github.lit.code.context.GenerationException; 6 | import com.github.lit.code.context.Task; 7 | import com.google.gson.Gson; 8 | import com.google.gson.JsonElement; 9 | 10 | /** 11 | * User : liulu 12 | * Date : 2018/2/7 16:41 13 | * version $Id: TasksParser.java, v 0.1 Exp $ 14 | */ 15 | public class TasksParser implements ConfigParser { 16 | 17 | @Override 18 | public String getConfigKey() { 19 | return ConfigConst.TASKS; 20 | } 21 | 22 | @Override 23 | public void parser(Configuration configuration, JsonElement jsonElement) { 24 | if (jsonElement.isJsonObject()) { 25 | throw new GenerationException("tasks 配置项必须是数组"); 26 | } 27 | 28 | Gson gson = new Gson(); 29 | for (JsonElement subElement : jsonElement.getAsJsonArray()) { 30 | if (subElement.isJsonArray()) { 31 | throw new GenerationException("tasks子项不能为数组!"); 32 | } 33 | Task task = gson.fromJson(subElement.toString(), Task.class); 34 | String _Package = subElement.getAsJsonObject().get("package").getAsString(); 35 | task.set_package(_Package); 36 | configuration.addTask(task); 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /lit-code/src/main/java/com/github/lit/code/plugin/PluginExecutor.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.code.plugin; 2 | 3 | import com.github.lit.code.config.Configuration; 4 | import com.github.lit.code.context.Task; 5 | import org.apache.velocity.context.Context; 6 | 7 | /** 8 | * User : liulu 9 | * Date : 2018/3/16 13:29 10 | * version $Id: PluginExecutor.java, v 0.1 Exp $ 11 | */ 12 | public interface PluginExecutor { 13 | 14 | void execute(Configuration configuration, Context context, Task task); 15 | 16 | 17 | } 18 | -------------------------------------------------------------------------------- /lit-code/src/main/java/com/github/lit/code/plugin/SerialVersionUIDPlugin.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.code.plugin; 2 | 3 | import com.github.lit.code.config.Configuration; 4 | import com.github.lit.code.context.Task; 5 | import org.apache.velocity.context.Context; 6 | 7 | import java.util.UUID; 8 | 9 | /** 10 | * User : liulu 11 | * Date : 2018/3/16 13:37 12 | * version $Id: SerialVersionUIDPlugin.java, v 0.1 Exp $ 13 | */ 14 | public class SerialVersionUIDPlugin implements PluginExecutor { 15 | 16 | @Override 17 | public void execute(Configuration configuration, Context context, Task task) { 18 | long serialVersionUID = Math.abs(UUID.randomUUID().getLeastSignificantBits()); 19 | context.put("serialVersionUID", -serialVersionUID); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /lit-code/src/main/java/com/github/lit/code/util/DBUtils.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.code.util; 2 | 3 | import com.github.lit.code.config.JdbcConfig; 4 | import com.github.lit.code.context.GenerationException; 5 | 6 | import java.sql.Connection; 7 | import java.sql.DriverManager; 8 | import java.sql.SQLException; 9 | 10 | /** 11 | * User : liulu 12 | * Date : 2018/2/9 15:20 13 | * version $Id: DBUtils.java, v 0.1 Exp $ 14 | */ 15 | public class DBUtils { 16 | 17 | private static Connection connection; 18 | 19 | private static String getDriverClass(String dbName) { 20 | if (dbName == null || dbName.isEmpty()) { 21 | return dbName; 22 | } 23 | switch (dbName.toUpperCase()) { 24 | case "MYSQL": 25 | return "com.mysql.jdbc.Driver"; 26 | case "ORACLE": 27 | return "oracle.jdbc.driver.OracleDriver"; 28 | default: 29 | return ""; 30 | } 31 | } 32 | 33 | 34 | public synchronized static void createConnection(JdbcConfig jdbcConfig) { 35 | 36 | try { 37 | if (jdbcConfig.getDriverClass() == null && jdbcConfig.getDbName() != null) { 38 | jdbcConfig.setDriverClass(getDriverClass(jdbcConfig.getDbName())); 39 | Class.forName(jdbcConfig.getDriverClass()); 40 | } 41 | connection = DriverManager.getConnection(jdbcConfig.getUrl(), jdbcConfig.getUser(), jdbcConfig.getPassword()); 42 | if (jdbcConfig.getDbName() == null || jdbcConfig.getDbName().isEmpty()) { 43 | jdbcConfig.setDbName(connection.getMetaData().getDatabaseProductName().toUpperCase()); 44 | } 45 | } catch (Exception e) { 46 | throw new GenerationException("创建数据库连接失败! 检查连接信息是否正确!", e); 47 | } 48 | } 49 | 50 | public static Connection getConnection() { 51 | try { 52 | if (connection == null || connection.isClosed()) { 53 | throw new GenerationException("数据库连接已失效, 请重新创建!"); 54 | } 55 | return connection; 56 | } catch (SQLException e) { 57 | throw new GenerationException("数据库连接异常!", e); 58 | } 59 | } 60 | 61 | public static void closeConnection() { 62 | try { 63 | connection.close(); 64 | } catch (SQLException e) { 65 | // 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /lit-code/src/main/java/com/github/lit/code/util/FileUtils.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.code.util; 2 | 3 | import java.io.*; 4 | import java.util.logging.Logger; 5 | 6 | /** 7 | * User : liulu 8 | * Date : 2018/2/6 15:39 9 | * version $Id: ResourceUtils.java, v 0.1 Exp $ 10 | */ 11 | public class FileUtils { 12 | 13 | private static final Logger LOGGER = Logger.getLogger(FileUtils.class.getName()); 14 | 15 | public static String readToString (String filePath) { 16 | if (!filePath.startsWith(File.separator)) { 17 | filePath = File.separator + filePath; 18 | } 19 | InputStream inputStream = FileUtils.class.getResourceAsStream(filePath); 20 | if (inputStream == null) { 21 | return ""; 22 | } 23 | return readToString(inputStream); 24 | } 25 | 26 | public static String readToString(InputStream inputStream) { 27 | 28 | byte[] b = new byte[1024 * 4]; 29 | ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 30 | try { 31 | for (int len; ; ) { 32 | len = inputStream.read(b, 0, b.length); 33 | if (len == -1) { 34 | break; 35 | } 36 | outputStream.write(b, 0, len); 37 | } 38 | return outputStream.toString("UTF-8"); 39 | } catch (IOException e) { 40 | // 41 | } finally { 42 | try { 43 | inputStream.close(); 44 | outputStream.close(); 45 | } catch (IOException e) { 46 | // 47 | } 48 | } 49 | return ""; 50 | } 51 | 52 | public static void writeToFile (String text, String filePath, boolean overwrite) { 53 | 54 | try { 55 | File file = new File(filePath); 56 | if (file.exists() && !overwrite) { 57 | LOGGER.info(String.format("file %s is exist, do nothing", filePath)); 58 | return; 59 | } 60 | if (!file.getParentFile().exists()) { 61 | file.getParentFile().mkdirs(); 62 | } 63 | 64 | FileWriter fileWriter = new FileWriter(file); 65 | fileWriter.write(text); 66 | fileWriter.flush(); 67 | fileWriter.close(); 68 | LOGGER.info(String.format("generate file: %s ", filePath)); 69 | } catch (IOException e) { 70 | // 71 | } 72 | 73 | } 74 | 75 | 76 | } 77 | -------------------------------------------------------------------------------- /lit-code/src/test/java/com/github/lit/code/Generation.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.code; 2 | 3 | /** 4 | * User : liulu 5 | * Date : 2018/3/16 11:45 6 | * version $Id: Generation.java, v 0.1 Exp $ 7 | */ 8 | public class Generation { 9 | 10 | 11 | public static void main(String[] args) { 12 | CodeGeneration.run(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /lit-code/src/test/resources/code.json: -------------------------------------------------------------------------------- 1 | { 2 | "constant": { 3 | "overwrite": true, 4 | "onChildModule": false, 5 | "rootDir": "/Users/liulu/Documents/project/git/qianniu", 6 | "baseModule": "qn-common", 7 | "basePackage": "com.ipampas.qianniu", 8 | "modelPackage": "product" 9 | }, 10 | "jdbc": { 11 | "url": "jdbc:mysql://10.10.100.56:3306/qianniu_dev?useSSL=false&useUnicode=true&characterEncoding=UTF-8", 12 | "user": "root", 13 | "password": "123456" 14 | }, 15 | "table": { 16 | "name": "sign_product", 17 | "desc": "3.0产品", 18 | "tasks": [ 19 | "model", 20 | "qo", 21 | "mapper", 22 | "xmlMapper", 23 | "service", 24 | "serviceImpl" 25 | ] 26 | }, 27 | "tasks": [ 28 | { 29 | "name": "model", 30 | "plugins": [ 31 | "com.github.lit.code.plugin.SerialVersionUIDPlugin" 32 | ], 33 | "template": "/templates/model.vm", 34 | "module": "${baseModule}", 35 | "package": "${basePackage}.model.${modelPackage}" 36 | }, 37 | { 38 | "name": "qo", 39 | "plugins": [ 40 | "com.github.lit.code.plugin.SerialVersionUIDPlugin" 41 | ], 42 | "template": "/templates/qo.vm", 43 | "suffixAdd": "Qo", 44 | "module": "${baseModule}", 45 | "package": "${basePackage}.model.${modelPackage}" 46 | }, 47 | { 48 | "name": "mapper", 49 | "template": "/templates/mapper.vm", 50 | "suffixAdd": "Mapper", 51 | "module": "${baseModule}", 52 | "package": "${basePackage}.mapper.${modelPackage}" 53 | }, 54 | { 55 | "name": "xmlMapper", 56 | "template": "/templates/xmlMapper.vm", 57 | "suffixAdd": "Mapper", 58 | "fileType": ".xml", 59 | "module": "${baseModule}", 60 | "srcDir": "src/main/resources", 61 | "package": "${basePackage}.mapper.${modelPackage}" 62 | }, 63 | { 64 | "name": "service", 65 | "template": "/templates/service.vm", 66 | "suffixAdd": "Service", 67 | "module": "${baseModule}", 68 | "package": "${basePackage}.service.${modelPackage}" 69 | }, 70 | { 71 | "name": "serviceImpl", 72 | "suffixAdd": "ServiceImpl", 73 | "template": "/templates/serviceImpl.vm", 74 | "module": "${baseModule}", 75 | "package": "${basePackage}.service.${modelPackage}.impl" 76 | } 77 | ] 78 | } -------------------------------------------------------------------------------- /lit-code/src/test/resources/templates/client.vm: -------------------------------------------------------------------------------- 1 | package ${packageName}; 2 | 3 | import com.ipampas.framework.model.Page; 4 | import ${model.longClassName}; 5 | import ${qo.longClassName}; 6 | import org.springframework.cloud.netflix.feign.FeignClient; 7 | import org.springframework.web.bind.annotation.*; 8 | 9 | /** 10 | * ${table.desc} 接口客户端 11 | * 12 | * Author: Created by code generator 13 | * Date: ${date} 14 | */ 15 | @FeignClient("panshi-server") 16 | public interface ${client.shortClassName} { 17 | 18 | 19 | @PostMapping("/${model.pathThroughClassName}/list") 20 | Page<${model.shortClassName}> findPageList(@RequestBody ${qo.shortClassName} ${qo.firstLowerClassName}); 21 | 22 | 23 | @GetMapping("/${model.pathThroughClassName}/{id}") 24 | ${model.shortClassName} get(@PathVariable("id") Long id); 25 | 26 | 27 | @PostMapping("/${model.pathThroughClassName}") 28 | Long insert(@RequestBody ${model.shortClassName} ${model.firstLowerClassName}); 29 | 30 | 31 | @PutMapping("/${model.pathThroughClassName}") 32 | Integer update(@RequestBody ${model.shortClassName} ${model.firstLowerClassName}); 33 | 34 | 35 | @DeleteMapping("/${model.pathThroughClassName}/{id}") 36 | Integer deleteById(@PathVariable("id") Long id); 37 | 38 | 39 | } -------------------------------------------------------------------------------- /lit-code/src/test/resources/templates/mapper.vm: -------------------------------------------------------------------------------- 1 | package ${mapper.packageName}; 2 | 3 | import ${model.longClassName}; 4 | import ${qo.longClassName}; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * ${table.desc} mapper 接口 10 | * 11 | * @author generator 12 | * @version 1.0.0 13 | */ 14 | public interface ${mapper.shortClassName} { 15 | 16 | /** 17 | * 新增${table.desc} 18 | * 19 | * @param ${model.firstLowerClassName} 20 | * @return 21 | */ 22 | int insert(${model.shortClassName} ${model.firstLowerClassName}); 23 | 24 | /** 25 | * 删除${table.desc} 26 | * 27 | * @param id 28 | * @return 29 | */ 30 | int deleteById(Long id); 31 | 32 | /** 33 | * 修改${table.desc}, 忽略null值 34 | * 35 | * @param ${model.firstLowerClassName} 36 | * @return 37 | */ 38 | int updateById(${model.shortClassName} ${model.firstLowerClassName}); 39 | 40 | /** 41 | * 查询${table.desc} 42 | * 43 | * @param id 44 | * @return ${table.desc} 45 | */ 46 | ${model.shortClassName} findById(Long id); 47 | 48 | /** 49 | * 分页查询${table.desc}列表 50 | * 51 | * @param ${qo.firstLowerClassName} 查询对象 52 | * @return ${table.desc}列表 53 | */ 54 | List<${model.shortClassName}> findList(${qo.shortClassName} ${qo.firstLowerClassName}); 55 | 56 | 57 | } -------------------------------------------------------------------------------- /lit-code/src/test/resources/templates/model.vm: -------------------------------------------------------------------------------- 1 | package ${model.packageName}; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | #foreach($im in ${table.importClasses}) 7 | import ${im}; 8 | #end 9 | 10 | /** 11 | * ${table.desc} 12 | * 13 | * @author generator 14 | * @version 1.0.0 15 | */ 16 | @Data 17 | public class ${model.shortClassName} implements Serializable{ 18 | 19 | /** serialVersionUID */ 20 | private static final long serialVersionUID = ${serialVersionUID}L; 21 | 22 | #foreach($column in ${table.columns}) 23 | #if(${column.comment} && $column.name != 'tenant_id') 24 | /** ${column.comment} */ 25 | #end 26 | #if($column.name != 'tenant_id') 27 | private ${column.javaType} ${column.camelName}; 28 | 29 | #end 30 | #end 31 | } -------------------------------------------------------------------------------- /lit-code/src/test/resources/templates/qo.vm: -------------------------------------------------------------------------------- 1 | package ${qo.packageName}; 2 | 3 | import com.ipampas.framework.model.Page; 4 | import lombok.Data; 5 | 6 | /** 7 | * ${table.desc} 8 | * 9 | * @author generator 10 | * @version 1.0.0 11 | */ 12 | @Data 13 | public class ${qo.shortClassName} extends Page { 14 | 15 | /** serialVersionUID */ 16 | private static final long serialVersionUID = ${serialVersionUID}L; 17 | 18 | 19 | } -------------------------------------------------------------------------------- /lit-code/src/test/resources/templates/rest.vm: -------------------------------------------------------------------------------- 1 | package ${packageName}; 2 | 3 | import com.github.pagehelper.Page; 4 | import ${model.longClassName}; 5 | import ${qo.longClassName}; 6 | import ${service.longClassName}; 7 | import org.springframework.web.bind.annotation.*; 8 | 9 | import javax.annotation.Resource; 10 | 11 | /** 12 | * ${table.desc} rest 接口 13 | * 14 | * Author: Created by code generator 15 | * Date: ${date} 16 | */ 17 | @RestController 18 | @RequestMapping("/${model.pathThroughClassName}") 19 | public class ${rest.shortClassName} { 20 | 21 | @Resource 22 | private ${service.shortClassName} ${service.firstLowerClassName}; 23 | 24 | 25 | @PostMapping("/list") 26 | public com.ipampas.framework.model.Page<${model.shortClassName}> list(@RequestBody ${qo.shortClassName} ${qo.firstLowerClassName}) { 27 | Page<${model.shortClassName}> list = (Page<${model.shortClassName}>) ${service.firstLowerClassName}.findPageList(${qo.firstLowerClassName}); 28 | 29 | // myBatis 分页对象转为 pps 统一分页对象 30 | com.ipampas.framework.model.Page<${model.shortClassName}> result = new com.ipampas.framework.model.Page<>(); 31 | result.setPageNo(list.getPageNum()); 32 | result.setPageRecords(list); 33 | result.setPageSize(list.getPageSize()); 34 | result.setTotalRecords(list.getTotal()); 35 | 36 | return result; 37 | } 38 | 39 | @GetMapping("/{id}") 40 | public ${model.shortClassName} detail(@PathVariable Long id) { 41 | return ${service.firstLowerClassName}.findById(id); 42 | } 43 | 44 | @PostMapping 45 | public Long add(@RequestBody ${model.shortClassName} ${model.firstLowerClassName}) { 46 | return ${service.firstLowerClassName}.insert(${model.firstLowerClassName}); 47 | } 48 | 49 | @PutMapping 50 | public Integer update(@RequestBody ${model.shortClassName} ${model.firstLowerClassName}) { 51 | return ${service.firstLowerClassName}.updateById(${model.firstLowerClassName}); 52 | } 53 | 54 | @DeleteMapping("{id}") 55 | public Integer deleteById(@PathVariable Long id) { 56 | return ${service.firstLowerClassName}.deleteById(id); 57 | } 58 | 59 | 60 | } 61 | 62 | -------------------------------------------------------------------------------- /lit-code/src/test/resources/templates/service.vm: -------------------------------------------------------------------------------- 1 | package ${service.packageName}; 2 | 3 | import com.ipampas.framework.model.Page; 4 | import ${model.longClassName}; 5 | import ${qo.longClassName}; 6 | 7 | 8 | /** 9 | * ${table.desc} service 接口 10 | * 11 | * @author generator 12 | * @version 1.0.0 13 | */ 14 | public interface ${service.shortClassName} { 15 | 16 | /** 17 | * 新增${table.desc} 18 | * 19 | * @param ${model.firstLowerClassName} 20 | * @return 新记录的Id 21 | */ 22 | Long create(${model.shortClassName} ${model.firstLowerClassName}); 23 | 24 | /** 25 | * 删除${table.desc} 26 | * 27 | * @param id 28 | * @return 29 | */ 30 | int removeById(Long id); 31 | 32 | /** 33 | * 修改${table.desc}, 忽略null值 34 | * 35 | * @param ${model.firstLowerClassName} 36 | * @return 37 | */ 38 | int modify(${model.shortClassName} ${model.firstLowerClassName}); 39 | 40 | /** 41 | * 查询${table.desc} 42 | * 43 | * @param id 44 | * @return ${table.desc} 45 | */ 46 | ${model.shortClassName} findById(Long id); 47 | 48 | /** 49 | * 分页查询${table.desc}列表 50 | * 51 | * @param ${qo.firstLowerClassName} 查询对象 52 | * @return ${table.desc}列表 53 | */ 54 | Page<${model.shortClassName}> findPageList(${qo.shortClassName} ${qo.firstLowerClassName}); 55 | 56 | } -------------------------------------------------------------------------------- /lit-code/src/test/resources/templates/serviceImpl.vm: -------------------------------------------------------------------------------- 1 | package ${serviceImpl.packageName}; 2 | 3 | import com.github.pagehelper.PageHelper; 4 | import com.ipampas.framework.model.Page; 5 | import com.ipampas.qianniu.util.PageUtils; 6 | import ${model.longClassName}; 7 | import ${qo.longClassName}; 8 | import ${mapper.longClassName}; 9 | import ${service.longClassName}; 10 | import lombok.extern.slf4j.Slf4j; 11 | import org.springframework.stereotype.Service; 12 | import org.springframework.transaction.annotation.Transactional; 13 | 14 | import javax.annotation.Resource; 15 | import java.util.List; 16 | 17 | /** 18 | * ${table.desc} service 接口实现 19 | * 20 | * @author generator 21 | * @version 1.0.0 22 | */ 23 | @Service 24 | @Slf4j 25 | @Transactional 26 | public class ${serviceImpl.shortClassName} implements ${service.shortClassName} { 27 | 28 | @Resource 29 | private ${mapper.shortClassName} ${mapper.firstLowerClassName}; 30 | 31 | 32 | @Override 33 | public Long create(${model.shortClassName} ${model.firstLowerClassName}) { 34 | ${mapper.firstLowerClassName}.insert(${model.firstLowerClassName}); 35 | return ${model.firstLowerClassName}.getId(); 36 | } 37 | 38 | @Override 39 | public int removeById(Long id) { 40 | return ${mapper.firstLowerClassName}.deleteById(id); 41 | } 42 | 43 | @Override 44 | public int modify(${model.shortClassName} ${model.firstLowerClassName}) { 45 | return ${mapper.firstLowerClassName}.updateById(${model.firstLowerClassName}); 46 | } 47 | 48 | @Override 49 | public ${model.shortClassName} findById(Long id) { 50 | return ${mapper.firstLowerClassName}.findById(id); 51 | } 52 | 53 | @Override 54 | public Page<${model.shortClassName}> findPageList(${qo.shortClassName} ${qo.firstLowerClassName}) { 55 | PageHelper.startPage(${qo.firstLowerClassName}.getPageNo(), ${qo.firstLowerClassName}.getPageSize()); 56 | List<${model.shortClassName}> pageList = ${mapper.firstLowerClassName}.findList(${qo.firstLowerClassName}); 57 | return PageUtils.transToPage(pageList); 58 | } 59 | 60 | 61 | } -------------------------------------------------------------------------------- /lit-code/src/test/resources/templates/xmlMapper.vm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | #foreach($column in ${table.columns}) 7 | #if(${column.primaryKey}) 8 | #set($primaryKey = $column) 9 | 10 | #elseif($column.name != 'tenant_id') 11 | 12 | #end 13 | #end 14 | 15 | 16 | 17 | #set($columnSize = ${table.columns.size()}) 18 | #foreach($column in ${table.columns}) 19 | #if($column.name != 'tenant_id')${column.name}#end#if($velocityCount < $columnSize && $column.name != 'tenant_id'), #end 20 | #end 21 | 22 | 23 | 24 | 30 | 31 | 36 | 37 | 38 | insert into ${table.name} 39 | 40 | #foreach($column in ${table.columns}) 41 | #if($column.name != 'tenant_id') 42 | 43 | ${column.name}, 44 | 45 | #else 46 | tenant_id, 47 | #end 48 | #end 49 | 50 | 51 | #foreach($column in ${table.columns}) 52 | #if(${column.name} == 'tenant_id') 53 | #{tenantId}, 54 | #else 55 | 56 | #{${column.camelName}}, 57 | 58 | #end 59 | #end 60 | 61 | 62 | 63 | 64 | update ${table.name} 65 | 66 | #foreach($column in ${table.columns}) 67 | #if(!${column.isPrimaryKey}) 68 | #if($column.name != 'tenant_id') 69 | 70 | ${column.name} = #{${column.camelName}}, 71 | 72 | #end 73 | #end 74 | #end 75 | 76 | where ${primaryKey.name} = #{${primaryKey.camelName}} and tenant_id = #{tenantId} 77 | 78 | 79 | 80 | delete from ${table.name} where ${primaryKey.name} = #{id} and tenant_id = #{tenantId} 81 | 82 | 83 | -------------------------------------------------------------------------------- /lit-starters/lit-starter-jdbc/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | lit-starters 7 | com.github.liulus 8 | 2.5.0 9 | 10 | 4.0.0 11 | 12 | lit-starter-jdbc 13 | 14 | 15 | 16 | com.github.liulus 17 | lit-support 18 | ${project.version} 19 | 20 | 21 | 22 | javax.persistence 23 | persistence-api 24 | 1.0 25 | 26 | 27 | 28 | org.springframework 29 | spring-jdbc 30 | ${spring.version} 31 | 32 | 33 | org.springframework.boot 34 | spring-boot-autoconfigure 35 | ${spring.boot.version} 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /lit-starters/lit-starter-jdbc/src/main/java/com/github/lit/starter/jdbc/JdbcSupportAutoConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.starter.jdbc; 2 | 3 | import com.github.lit.support.data.jdbc.EnableJdbcSupport; 4 | import org.springframework.boot.autoconfigure.AutoConfigureOrder; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.core.Ordered; 7 | 8 | /** 9 | * @author liulu 10 | * @version v1.0 11 | * date 2018-12-22 19:27 12 | */ 13 | @Configuration 14 | @EnableJdbcSupport 15 | @AutoConfigureOrder(Ordered.LOWEST_PRECEDENCE) 16 | public class JdbcSupportAutoConfiguration { 17 | 18 | 19 | } 20 | -------------------------------------------------------------------------------- /lit-starters/lit-starter-jdbc/src/main/resources/META-INF/spring.factories: -------------------------------------------------------------------------------- 1 | org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.github.lit.starter.jdbc.JdbcSupportAutoConfiguration -------------------------------------------------------------------------------- /lit-starters/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | lit 7 | com.github.liulus 8 | 2.5.0 9 | 10 | pom 11 | 4.0.0 12 | 13 | lit-starters 14 | 15 | 16 | lit-starter-jdbc 17 | 18 | 19 | -------------------------------------------------------------------------------- /lit-support/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | lit 7 | com.github.liulus 8 | 2.5.0 9 | 10 | 4.0.0 11 | 12 | lit-support 13 | 14 | 15 | 16 | javax.persistence 17 | persistence-api 18 | 1.0 19 | true 20 | 21 | 22 | javax.servlet 23 | javax.servlet-api 24 | 3.1.0 25 | true 26 | 27 | 28 | org.slf4j 29 | slf4j-api 30 | true 31 | 32 | 33 | com.fasterxml.jackson.core 34 | jackson-databind 35 | ${jackson.version} 36 | true 37 | 38 | 39 | org.springframework 40 | spring-jdbc 41 | ${spring.version} 42 | true 43 | 44 | 45 | org.springframework 46 | spring-webmvc 47 | ${spring.version} 48 | true 49 | 50 | 51 | org.springframework 52 | spring-aspects 53 | ${spring.version} 54 | true 55 | 56 | 57 | com.google.guava 58 | guava 59 | 22.0 60 | true 61 | 62 | 63 | org.mybatis 64 | mybatis 65 | ${mybatis.version} 66 | true 67 | 68 | 69 | 70 | 71 | org.springframework 72 | spring-test 73 | ${spring.version} 74 | test 75 | 76 | 77 | ch.qos.logback 78 | logback-classic 79 | ${logback.version} 80 | test 81 | 82 | 83 | org.slf4j 84 | jcl-over-slf4j 85 | ${slf4j.version} 86 | test 87 | 88 | 89 | ch.vorburger.mariaDB4j 90 | mariaDB4j 91 | 2.2.3 92 | test 93 | 94 | 95 | mysql 96 | mysql-connector-java 97 | test 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /lit-support/src/main/java/com/github/lit/support/data/AbstractSQL.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.support.data; 2 | 3 | import java.io.IOException; 4 | import java.util.ArrayList; 5 | import java.util.Arrays; 6 | import java.util.Collections; 7 | import java.util.List; 8 | 9 | /** 10 | * 引用 org.apache.ibatis.jdbc.AbstractSQL 11 | * 12 | * @author mybatis 13 | * @version v1.0 14 | * @see org.apache.ibatis.jdbc.AbstractSQL 15 | * date 2018-12-10 14:12 16 | */ 17 | public abstract class AbstractSQL { 18 | 19 | private static final String AND = ") AND ("; 20 | private static final String OR = ") OR ("; 21 | 22 | private final SQLStatement sql = new SQLStatement(); 23 | 24 | public abstract T getSelf(); 25 | 26 | public T UPDATE(String table) { 27 | sql().statementType = SQLStatement.StatementType.UPDATE; 28 | sql().tables.add(table); 29 | return getSelf(); 30 | } 31 | 32 | public T SET(String sets) { 33 | sql().sets.add(sets); 34 | return getSelf(); 35 | } 36 | 37 | /** 38 | * @since 3.4.2 39 | */ 40 | public T SET(String... sets) { 41 | sql().sets.addAll(Arrays.asList(sets)); 42 | return getSelf(); 43 | } 44 | 45 | public T INSERT_INTO(String tableName) { 46 | sql().statementType = SQLStatement.StatementType.INSERT; 47 | sql().tables.add(tableName); 48 | return getSelf(); 49 | } 50 | 51 | public T VALUES(String columns, String values) { 52 | sql().columns.add(columns); 53 | sql().values.add(values); 54 | return getSelf(); 55 | } 56 | 57 | /** 58 | * @since 3.4.2 59 | */ 60 | public T INTO_COLUMNS(String... columns) { 61 | sql().columns.addAll(Arrays.asList(columns)); 62 | return getSelf(); 63 | } 64 | 65 | /** 66 | * @since 3.4.2 67 | */ 68 | public T INTO_VALUES(String... values) { 69 | sql().values.addAll(Arrays.asList(values)); 70 | return getSelf(); 71 | } 72 | 73 | public T SELECT(String columns) { 74 | sql().statementType = SQLStatement.StatementType.SELECT; 75 | sql().select.add(columns); 76 | return getSelf(); 77 | } 78 | 79 | /** 80 | * @since 3.4.2 81 | */ 82 | public T SELECT(String... columns) { 83 | sql().statementType = SQLStatement.StatementType.SELECT; 84 | sql().select.addAll(Arrays.asList(columns)); 85 | return getSelf(); 86 | } 87 | 88 | public T SELECT_DISTINCT(String columns) { 89 | sql().distinct = true; 90 | SELECT(columns); 91 | return getSelf(); 92 | } 93 | 94 | /** 95 | * @since 3.4.2 96 | */ 97 | public T SELECT_DISTINCT(String... columns) { 98 | sql().distinct = true; 99 | SELECT(columns); 100 | return getSelf(); 101 | } 102 | 103 | public T DELETE_FROM(String table) { 104 | sql().statementType = SQLStatement.StatementType.DELETE; 105 | sql().tables.add(table); 106 | return getSelf(); 107 | } 108 | 109 | public T FROM(String table) { 110 | sql().tables.add(table); 111 | return getSelf(); 112 | } 113 | 114 | /** 115 | * @since 3.4.2 116 | */ 117 | public T FROM(String... tables) { 118 | sql().tables.addAll(Arrays.asList(tables)); 119 | return getSelf(); 120 | } 121 | 122 | public T JOIN(String join) { 123 | sql().join.add(join); 124 | return getSelf(); 125 | } 126 | 127 | /** 128 | * @since 3.4.2 129 | */ 130 | public T JOIN(String... joins) { 131 | sql().join.addAll(Arrays.asList(joins)); 132 | return getSelf(); 133 | } 134 | 135 | public T INNER_JOIN(String join) { 136 | sql().innerJoin.add(join); 137 | return getSelf(); 138 | } 139 | 140 | /** 141 | * @since 3.4.2 142 | */ 143 | public T INNER_JOIN(String... joins) { 144 | sql().innerJoin.addAll(Arrays.asList(joins)); 145 | return getSelf(); 146 | } 147 | 148 | public T LEFT_OUTER_JOIN(String join) { 149 | sql().leftOuterJoin.add(join); 150 | return getSelf(); 151 | } 152 | 153 | /** 154 | * @since 3.4.2 155 | */ 156 | public T LEFT_OUTER_JOIN(String... joins) { 157 | sql().leftOuterJoin.addAll(Arrays.asList(joins)); 158 | return getSelf(); 159 | } 160 | 161 | public T RIGHT_OUTER_JOIN(String join) { 162 | sql().rightOuterJoin.add(join); 163 | return getSelf(); 164 | } 165 | 166 | /** 167 | * @since 3.4.2 168 | */ 169 | public T RIGHT_OUTER_JOIN(String... joins) { 170 | sql().rightOuterJoin.addAll(Arrays.asList(joins)); 171 | return getSelf(); 172 | } 173 | 174 | public T OUTER_JOIN(String join) { 175 | sql().outerJoin.add(join); 176 | return getSelf(); 177 | } 178 | 179 | /** 180 | * @since 3.4.2 181 | */ 182 | public T OUTER_JOIN(String... joins) { 183 | sql().outerJoin.addAll(Arrays.asList(joins)); 184 | return getSelf(); 185 | } 186 | 187 | public T WHERE(String conditions) { 188 | sql().where.add(conditions); 189 | sql().lastList = sql().where; 190 | return getSelf(); 191 | } 192 | 193 | /** 194 | * @since 3.4.2 195 | */ 196 | public T WHERE(String... conditions) { 197 | sql().where.addAll(Arrays.asList(conditions)); 198 | sql().lastList = sql().where; 199 | return getSelf(); 200 | } 201 | 202 | public T OR() { 203 | sql().lastList.add(OR); 204 | return getSelf(); 205 | } 206 | 207 | public T AND() { 208 | sql().lastList.add(AND); 209 | return getSelf(); 210 | } 211 | 212 | public T GROUP_BY(String columns) { 213 | sql().groupBy.add(columns); 214 | return getSelf(); 215 | } 216 | 217 | /** 218 | * @since 3.4.2 219 | */ 220 | public T GROUP_BY(String... columns) { 221 | sql().groupBy.addAll(Arrays.asList(columns)); 222 | return getSelf(); 223 | } 224 | 225 | public T HAVING(String conditions) { 226 | sql().having.add(conditions); 227 | sql().lastList = sql().having; 228 | return getSelf(); 229 | } 230 | 231 | /** 232 | * @since 3.4.2 233 | */ 234 | public T HAVING(String... conditions) { 235 | sql().having.addAll(Arrays.asList(conditions)); 236 | sql().lastList = sql().having; 237 | return getSelf(); 238 | } 239 | 240 | public T ORDER_BY(String columns) { 241 | sql().orderBy.add(columns); 242 | return getSelf(); 243 | } 244 | 245 | /** 246 | * @since 3.4.2 247 | */ 248 | public T ORDER_BY(String... columns) { 249 | sql().orderBy.addAll(Arrays.asList(columns)); 250 | return getSelf(); 251 | } 252 | 253 | private SQLStatement sql() { 254 | return sql; 255 | } 256 | 257 | public A usingAppender(A a) { 258 | if (sql().statementType == SQLStatement.StatementType.COUNT) { 259 | sql().statementType = SQLStatement.StatementType.SELECT; 260 | } 261 | sql().sql(a); 262 | return a; 263 | } 264 | 265 | @Override 266 | public String toString() { 267 | if (sql().statementType == SQLStatement.StatementType.COUNT) { 268 | sql().statementType = SQLStatement.StatementType.SELECT; 269 | } 270 | StringBuilder sb = new StringBuilder(); 271 | sql().sql(sb); 272 | 273 | return sb.toString(); 274 | } 275 | 276 | public String countSql() { 277 | if (sql().statementType == SQLStatement.StatementType.SELECT) { 278 | sql().statementType = SQLStatement.StatementType.COUNT; 279 | } 280 | StringBuilder sb = new StringBuilder(); 281 | sql().sql(sb); 282 | 283 | return sb.toString(); 284 | } 285 | 286 | private static class SafeAppendable { 287 | private final Appendable a; 288 | private boolean empty = true; 289 | 290 | public SafeAppendable(Appendable a) { 291 | super(); 292 | this.a = a; 293 | } 294 | 295 | public SafeAppendable append(CharSequence s) { 296 | try { 297 | if (empty && s.length() > 0) { 298 | empty = false; 299 | } 300 | a.append(s); 301 | } catch (IOException e) { 302 | throw new RuntimeException(e); 303 | } 304 | return this; 305 | } 306 | 307 | public boolean isEmpty() { 308 | return empty; 309 | } 310 | 311 | } 312 | 313 | private static class SQLStatement { 314 | 315 | public enum StatementType { 316 | DELETE, INSERT, SELECT, UPDATE, COUNT 317 | } 318 | 319 | SQLStatement.StatementType statementType; 320 | List sets = new ArrayList<>(); 321 | List select = new ArrayList<>(); 322 | List count = Collections.singletonList("count(*)"); 323 | List tables = new ArrayList<>(); 324 | List join = new ArrayList<>(); 325 | List innerJoin = new ArrayList<>(); 326 | List outerJoin = new ArrayList<>(); 327 | List leftOuterJoin = new ArrayList<>(); 328 | List rightOuterJoin = new ArrayList<>(); 329 | List where = new ArrayList<>(); 330 | List having = new ArrayList<>(); 331 | List groupBy = new ArrayList<>(); 332 | List orderBy = new ArrayList<>(); 333 | List lastList = new ArrayList<>(); 334 | List columns = new ArrayList<>(); 335 | List values = new ArrayList<>(); 336 | boolean distinct; 337 | 338 | public SQLStatement() { 339 | // Prevent Synthetic Access 340 | } 341 | 342 | private void sqlClause(SafeAppendable builder, String keyword, List parts, String open, String close, 343 | String conjunction) { 344 | if (!parts.isEmpty()) { 345 | if (!builder.isEmpty()) { 346 | builder.append(" "); 347 | } 348 | builder.append(keyword); 349 | builder.append(" "); 350 | builder.append(open); 351 | String last = "________"; 352 | for (int i = 0, n = parts.size(); i < n; i++) { 353 | String part = parts.get(i); 354 | if (i > 0 && !part.equals(AND) && !part.equals(OR) && !last.equals(AND) && !last.equals(OR)) { 355 | builder.append(conjunction); 356 | } 357 | builder.append(part); 358 | last = part; 359 | } 360 | builder.append(close); 361 | } 362 | } 363 | 364 | private String selectSQL(SafeAppendable builder) { 365 | if (distinct) { 366 | sqlClause(builder, "SELECT DISTINCT", select, "", "", ", "); 367 | } else { 368 | sqlClause(builder, "SELECT", select, "", "", ", "); 369 | } 370 | 371 | sqlClause(builder, "FROM", tables, "", "", ", "); 372 | joins(builder); 373 | sqlClause(builder, "WHERE", where, "(", ")", " AND "); 374 | sqlClause(builder, "GROUP BY", groupBy, "", "", ", "); 375 | sqlClause(builder, "HAVING", having, "(", ")", " AND "); 376 | sqlClause(builder, "ORDER BY", orderBy, "", "", ", "); 377 | return builder.toString(); 378 | } 379 | 380 | private String countSQL(SafeAppendable builder) { 381 | sqlClause(builder, "SELECT", count, "", "", ", "); 382 | sqlClause(builder, "FROM", tables, "", "", ", "); 383 | joins(builder); 384 | sqlClause(builder, "WHERE", where, "(", ")", " AND "); 385 | sqlClause(builder, "GROUP BY", groupBy, "", "", ", "); 386 | sqlClause(builder, "HAVING", having, "(", ")", " AND "); 387 | return builder.toString(); 388 | } 389 | 390 | private void joins(SafeAppendable builder) { 391 | sqlClause(builder, "JOIN", join, "", "", " JOIN "); 392 | sqlClause(builder, "INNER JOIN", innerJoin, "", "", " INNER JOIN "); 393 | sqlClause(builder, "OUTER JOIN", outerJoin, "", "", " OUTER JOIN "); 394 | sqlClause(builder, "LEFT OUTER JOIN", leftOuterJoin, "", "", " LEFT OUTER JOIN "); 395 | sqlClause(builder, "RIGHT OUTER JOIN", rightOuterJoin, "", "", " RIGHT OUTER JOIN "); 396 | } 397 | 398 | private String insertSQL(SafeAppendable builder) { 399 | sqlClause(builder, "INSERT INTO", tables, "", "", ""); 400 | sqlClause(builder, "", columns, "(", ")", ", "); 401 | sqlClause(builder, "VALUES", values, "(", ")", ", "); 402 | return builder.toString(); 403 | } 404 | 405 | private String deleteSQL(SafeAppendable builder) { 406 | sqlClause(builder, "DELETE FROM", tables, "", "", ""); 407 | sqlClause(builder, "WHERE", where, "(", ")", " AND "); 408 | return builder.toString(); 409 | } 410 | 411 | private String updateSQL(SafeAppendable builder) { 412 | sqlClause(builder, "UPDATE", tables, "", "", ""); 413 | joins(builder); 414 | sqlClause(builder, "SET", sets, "", "", ", "); 415 | sqlClause(builder, "WHERE", where, "(", ")", " AND "); 416 | return builder.toString(); 417 | } 418 | 419 | public String sql(Appendable a) { 420 | SafeAppendable builder = new SafeAppendable(a); 421 | if (statementType == null) { 422 | return null; 423 | } 424 | 425 | String answer; 426 | 427 | switch (statementType) { 428 | case DELETE: 429 | answer = deleteSQL(builder); 430 | break; 431 | 432 | case INSERT: 433 | answer = insertSQL(builder); 434 | break; 435 | 436 | case SELECT: 437 | answer = selectSQL(builder); 438 | break; 439 | 440 | case UPDATE: 441 | answer = updateSQL(builder); 442 | break; 443 | 444 | case COUNT: 445 | answer = countSQL(builder); 446 | break; 447 | 448 | default: 449 | answer = null; 450 | } 451 | 452 | return answer; 453 | } 454 | } 455 | } 456 | -------------------------------------------------------------------------------- /lit-support/src/main/java/com/github/lit/support/data/Condition.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.support.data; 2 | 3 | import java.lang.annotation.Retention; 4 | import java.lang.annotation.Target; 5 | 6 | import static java.lang.annotation.ElementType.FIELD; 7 | import static java.lang.annotation.ElementType.METHOD; 8 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 9 | 10 | /** 11 | * User : liulu 12 | * Date : 2018/7/11 18:18 13 | * version $Id: LogicCondition.java, v 0.1 Exp $ 14 | */ 15 | @Target({METHOD, FIELD}) 16 | @Retention(RUNTIME) 17 | public @interface Condition { 18 | 19 | String property() default ""; 20 | 21 | Logic logic() default Logic.EQ; 22 | 23 | boolean ignoreEmpty() default true; 24 | 25 | 26 | } 27 | -------------------------------------------------------------------------------- /lit-support/src/main/java/com/github/lit/support/data/Logic.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.support.data; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | 6 | /** 7 | * User : liulu 8 | * Date : 2017/3/18 13:19 9 | * version $Id: Logic.java, v 0.1 Exp $ 10 | */ 11 | @Getter 12 | @AllArgsConstructor 13 | public enum Logic { 14 | 15 | EQ(" = ", "equal"), 16 | 17 | NOT_EQ(" != ", "not equal"), 18 | 19 | LT(" < ", "less than"), 20 | 21 | GT(" > ", "grater than"), 22 | 23 | LTEQ(" <= ", "less than or equal"), 24 | 25 | GTEQ(" >= ", "grater than or equal"), 26 | 27 | LIKE(" like ", "like"), 28 | 29 | NOT_LIKE(" not like ", "not like"), 30 | 31 | IN(" in ", "in"), 32 | 33 | NOT_IN(" not in ", "not in"), 34 | 35 | NULL(" is null ", "is null"), 36 | 37 | NOT_NULL(" is not null ", "is not null"),; 38 | 39 | 40 | private String code; 41 | 42 | private String desc; 43 | 44 | } 45 | -------------------------------------------------------------------------------- /lit-support/src/main/java/com/github/lit/support/data/SQL.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.support.data; 2 | 3 | import com.github.lit.support.data.domain.TableMetaDate; 4 | 5 | /** 6 | * @author mybaitis 7 | * @version v1.0 8 | * @see org.apache.ibatis.jdbc.SQL 9 | * date 2018-12-10 14:20 10 | */ 11 | public class SQL extends AbstractSQL { 12 | 13 | public enum Type { 14 | JDBC, 15 | MYBATIS, 16 | ; 17 | } 18 | 19 | 20 | @Override 21 | public SQL getSelf() { 22 | return this; 23 | } 24 | 25 | public static SQL init() { 26 | return new SQL(); 27 | } 28 | 29 | public static SQL baseSelect(Class cls) { 30 | TableMetaDate metaDate = TableMetaDate.forClass(cls); 31 | return SQL.init().SELECT(metaDate.getBaseColumns()).FROM(metaDate.getTableName()); 32 | } 33 | 34 | public static SQL count(Class cls) { 35 | TableMetaDate metaDate = TableMetaDate.forClass(cls); 36 | return SQL.init().SELECT("count(*)").FROM(metaDate.getTableName()); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /lit-support/src/main/java/com/github/lit/support/data/SQLUtils.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.support.data; 2 | 3 | import com.github.lit.support.data.domain.Sort; 4 | import com.github.lit.support.data.domain.TableMetaDate; 5 | import com.github.lit.support.util.bean.BeanUtils; 6 | import org.springframework.util.ReflectionUtils; 7 | import org.springframework.util.StringUtils; 8 | 9 | import java.beans.PropertyDescriptor; 10 | import java.text.MessageFormat; 11 | import java.util.Collection; 12 | import java.util.Map; 13 | import java.util.Objects; 14 | import java.util.Optional; 15 | 16 | /** 17 | * @author liulu 18 | * @version v1.0 19 | * date 2018-12-21 19:57 20 | */ 21 | public abstract class SQLUtils { 22 | 23 | /** 24 | * MySQL 分页,参数1 :第几条开始( offset ); 参数2:查询多少条(pageSize) 25 | */ 26 | private static final String MYSQL_PAGE_SQL = "%s limit %d, %d "; 27 | 28 | /** 29 | * DB2 分页,参数1 :第几条开始( offset ); 参数2:第几条为止(maxResult) 30 | */ 31 | private static final String DB2_PAGE_SQL = "select * from ( select t.*, rownumber() over() rowid from ( %s ) t ) where rowid > %d ) and rowid <= %d "; 32 | 33 | /** 34 | * Oracle 分页,参数1:第几条为止(maxResult); 参数2 :第几条开始( offset ) 35 | */ 36 | private static final String ORACLE_PAGE_SQL = "select * from (select t.*, rownum rowno from ( %s ) t where rownum <= %d ) where rowno > %d "; 37 | 38 | private SQLUtils() { 39 | } 40 | 41 | public static SQL insertSQL(Object entity, SQL.Type sqlType) { 42 | Objects.requireNonNull(entity, "insert with entity can not be null"); 43 | Class eClass = entity.getClass(); 44 | TableMetaDate mataDate = TableMetaDate.forClass(eClass); 45 | Map fieldColumnMap = mataDate.getFieldColumnMap(); 46 | SQL sql = SQL.init().INSERT_INTO(mataDate.getTableName()); 47 | for (Map.Entry entry : fieldColumnMap.entrySet()) { 48 | // 忽略主键 49 | PropertyDescriptor ps = BeanUtils.getPropertyDescriptor(eClass, entry.getKey()); 50 | if (Objects.equals(entry.getKey(), mataDate.getKeyProperty()) 51 | || ps == null || ps.getReadMethod() == null) { 52 | continue; 53 | } 54 | Object value = ReflectionUtils.invokeMethod(ps.getReadMethod(), entity); 55 | if (value != null) { 56 | sql.VALUES(entry.getValue(), getTokenParam(entry.getKey(), sqlType)); 57 | } 58 | } 59 | return sql; 60 | } 61 | 62 | public static SQL updateSQL(Object entity, Boolean ignoreNull, SQL.Type sqlType) { 63 | Objects.requireNonNull(entity, "update with entity can not be null"); 64 | Class entityClass = entity.getClass(); 65 | TableMetaDate mataDate = TableMetaDate.forClass(entityClass); 66 | Map fieldColumnMap = mataDate.getFieldColumnMap(); 67 | 68 | SQL sql = SQL.init().UPDATE(mataDate.getTableName()); 69 | for (Map.Entry entry : fieldColumnMap.entrySet()) { 70 | // 忽略主键 71 | PropertyDescriptor ps = BeanUtils.getPropertyDescriptor(entityClass, entry.getKey()); 72 | if (Objects.equals(entry.getKey(), mataDate.getKeyProperty()) 73 | || ps == null || ps.getReadMethod() == null) { 74 | continue; 75 | } 76 | if (ignoreNull) { 77 | Object value = ReflectionUtils.invokeMethod(ps.getReadMethod(), entity); 78 | if (value != null) { 79 | sql.SET(getEq(entry.getValue(), entry.getKey(), sqlType)); 80 | } 81 | } else { 82 | sql.SET(getEq(entry.getValue(), entry.getKey(), sqlType)); 83 | } 84 | } 85 | sql.WHERE(getEq(mataDate.getKeyColumn(), mataDate.getKeyProperty(), sqlType)); 86 | return sql; 87 | } 88 | 89 | public static SQL deleteSQL(Class eClass, SQL.Type sqlType) { 90 | TableMetaDate mataDate = TableMetaDate.forClass(eClass); 91 | return SQL.init().DELETE_FROM(mataDate.getTableName()) 92 | .WHERE(getEq(mataDate.getKeyColumn(), mataDate.getKeyProperty(), sqlType)); 93 | } 94 | 95 | 96 | public static SQL selectSQL(Class eClass, Object condition, Sort sort, SQL.Type sqlType) { 97 | 98 | TableMetaDate metaDate = TableMetaDate.forClass(eClass); 99 | 100 | SQL sql = SQL.init().SELECT(metaDate.getBaseColumns()).FROM(metaDate.getTableName()); 101 | ReflectionUtils.doWithFields(condition.getClass(), field -> { 102 | Condition logicCondition = field.getAnnotation(Condition.class); 103 | String property = Optional.ofNullable(logicCondition) 104 | .map(Condition::property) 105 | .filter(s -> !s.isEmpty()) 106 | .orElse(field.getName()); 107 | String mappedColumn = metaDate.getColumn(property); 108 | 109 | if (!metaDate.containsColumn(mappedColumn)) { 110 | return; 111 | } 112 | PropertyDescriptor pd = BeanUtils.getPropertyDescriptor(condition.getClass(), field.getName()); 113 | if (pd == null || pd.getReadMethod() == null) { 114 | return; 115 | } 116 | Object value = ReflectionUtils.invokeMethod(pd.getReadMethod(), condition); 117 | String sqlCondition = getCondition(field.getName(), logicCondition, value, sqlType); 118 | if (StringUtils.hasText(sqlCondition)) { 119 | sql.WHERE(mappedColumn + sqlCondition); 120 | } 121 | }); 122 | if (sort != null) { 123 | for (Map.Entry entry : sort.getOrderByMap().entrySet()) { 124 | String column = metaDate.getColumn(entry.getKey()); 125 | sql.ORDER_BY(column + entry.getValue()); 126 | } 127 | } 128 | return sql; 129 | } 130 | 131 | private static String getCondition(String fieldName, Condition logicCondition, Object value, SQL.Type sqlType) { 132 | Logic logic = Optional.ofNullable(logicCondition).map(Condition::logic).orElse(Logic.EQ); 133 | boolean ignoreEmpty = Optional.ofNullable(logicCondition).map(Condition::ignoreEmpty).orElse(true); 134 | if (logic == Logic.NULL || logic == Logic.NOT_NULL) { 135 | return logic.getCode(); 136 | } 137 | if (value == null || ("".equals(value) && ignoreEmpty)) { 138 | return ""; 139 | } 140 | if (value.getClass().isArray()) { 141 | throw new UnsupportedOperationException("unsupported operation for array params:" + fieldName); 142 | } 143 | if (value instanceof Collection && (logic == Logic.IN || logic == Logic.NOT_IN)) { 144 | int size = ((Collection) value).size(); 145 | return logic.getCode() + getIn(fieldName, size, sqlType); 146 | } 147 | return logic.getCode() + getTokenParam(fieldName, sqlType); 148 | } 149 | 150 | 151 | private static String getEq(String column, String param, SQL.Type sqlType) { 152 | return column + Logic.EQ.getCode() + getTokenParam(param, sqlType); 153 | } 154 | 155 | private static String getIn(String property, int size, SQL.Type sqlType) { 156 | if (sqlType == SQL.Type.JDBC) { 157 | return "( :" + property + ")"; 158 | } 159 | if (sqlType == SQL.Type.MYBATIS) { 160 | MessageFormat messageFormat = new MessageFormat("#'{'" + property + "[{0}]}"); 161 | StringBuilder sb = new StringBuilder(" ("); 162 | for (int i = 0; i < size; i++) { 163 | sb.append(messageFormat.format(new Object[]{i})); 164 | if (i != size - 1) { 165 | sb.append(", "); 166 | } 167 | } 168 | return sb.append(")").toString(); 169 | } 170 | throw new UnsupportedOperationException("unsupported operation build in with null SQL.Type"); 171 | } 172 | 173 | 174 | private static String getTokenParam(String param, SQL.Type sqlType) { 175 | switch (sqlType) { 176 | case JDBC: 177 | return ":" + param; 178 | case MYBATIS: 179 | return "#{" + param + "}"; 180 | default: 181 | throw new UnsupportedOperationException("unsupported operation build token param with null SQL.Type"); 182 | } 183 | } 184 | 185 | public static String getPageSql(String dbName, String sql, int pageSize, int pageNum) { 186 | if (StringUtils.isEmpty(dbName)) { 187 | throw new UnsupportedOperationException("unsupported operation build page sql unknow database"); 188 | } 189 | dbName = dbName.toUpperCase(); 190 | switch (dbName) { 191 | case "DB2": 192 | return String.format(DB2_PAGE_SQL, sql, pageSize * (pageNum - 1), pageSize * pageNum); 193 | case "MYSQL": 194 | return String.format(MYSQL_PAGE_SQL, sql, pageSize * (pageNum - 1), pageSize); 195 | case "ORACLE": 196 | return String.format(ORACLE_PAGE_SQL, sql, pageSize * pageNum, pageSize * (pageNum - 1)); 197 | default: 198 | throw new UnsupportedOperationException("unsupported operation build page sql for database: " + dbName); 199 | } 200 | } 201 | } 202 | -------------------------------------------------------------------------------- /lit-support/src/main/java/com/github/lit/support/data/domain/Page.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.support.data.domain; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | 8 | import java.util.Collections; 9 | import java.util.HashMap; 10 | import java.util.List; 11 | import java.util.Map; 12 | 13 | /** 14 | * @author liulu 15 | * @version v1.0 16 | * date 2018-12-15 13:41 17 | */ 18 | @ToString 19 | @NoArgsConstructor 20 | public class Page { 21 | 22 | @Getter 23 | @Setter 24 | private List data; 25 | 26 | @Getter 27 | @Setter 28 | private PageInfo pageInfo; 29 | 30 | private Map additional; 31 | 32 | public Page(List data, PageInfo pageInfo) { 33 | this.data = data; 34 | this.pageInfo = pageInfo; 35 | } 36 | 37 | public static Page emptyPage() { 38 | return new Page<>(Collections.emptyList() , PageInfo.EMPTY); 39 | } 40 | 41 | 42 | public void add(String key, Object value) { 43 | if (additional == null) { 44 | additional = new HashMap<>(); 45 | } 46 | additional.put(key, value); 47 | } 48 | 49 | public void addAll(Map map) { 50 | if (map == null) { 51 | return; 52 | } 53 | if (additional == null) { 54 | additional = new HashMap<>(); 55 | } 56 | additional.putAll(map); 57 | } 58 | 59 | public Map getAdditional() { 60 | if (additional == null) { 61 | return null; 62 | } 63 | return Collections.unmodifiableMap(additional); 64 | } 65 | 66 | 67 | } 68 | -------------------------------------------------------------------------------- /lit-support/src/main/java/com/github/lit/support/data/domain/PageInfo.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.support.data.domain; 2 | 3 | import lombok.Data; 4 | import lombok.NoArgsConstructor; 5 | 6 | import java.io.Serializable; 7 | import java.util.Objects; 8 | 9 | /** 10 | * User : liulu 11 | * Date : 2017/3/20 19:30 12 | * version $Id: PageInfo.java, v 0.1 Exp $ 13 | */ 14 | @Data 15 | @NoArgsConstructor 16 | public class PageInfo implements Serializable { 17 | 18 | private static final long serialVersionUID = -1073813980324211986L; 19 | 20 | private static final int PAGER_LENGTH = 3; 21 | 22 | public static final PageInfo EMPTY = new PageInfo(); 23 | 24 | /** 25 | * 每页记录数 26 | */ 27 | private int pageSize; 28 | 29 | /** 30 | * 当前页 31 | */ 32 | private int pageNum; 33 | 34 | /** 35 | * 总记录数 36 | */ 37 | private int total; 38 | 39 | public PageInfo(int pageSize, int pageNum) { 40 | this.pageSize = pageSize; 41 | this.pageNum = pageNum; 42 | } 43 | 44 | public PageInfo(int pageSize, int pageNum, int total) { 45 | this.pageSize = pageSize; 46 | this.pageNum = pageNum; 47 | this.total = total; 48 | } 49 | 50 | public int getPageNum() { 51 | return Math.min(Math.max(1, pageNum), getTotalPage()); 52 | } 53 | 54 | /** 55 | * @return 总页数 56 | */ 57 | public int getTotalPage() { 58 | return (total - 1) / pageSize + 1; 59 | } 60 | 61 | /** 62 | * @return 分页条起始页码 63 | */ 64 | public int getStart() { 65 | return Math.max(1, Math.min(getPageNum(), getTotalPage() - PAGER_LENGTH) - PAGER_LENGTH); 66 | } 67 | 68 | /** 69 | * @return 分页条结束页码 70 | */ 71 | public int getEnd() { 72 | return Math.min(getTotalPage(), Math.max(getPageNum(), PAGER_LENGTH + 1) + PAGER_LENGTH); 73 | } 74 | 75 | public boolean isFirstPage() { 76 | return getPageNum() == 1; 77 | } 78 | 79 | public boolean isLastPage() { 80 | return Objects.equals(getTotalPage(), getPageNum()); 81 | } 82 | 83 | } 84 | -------------------------------------------------------------------------------- /lit-support/src/main/java/com/github/lit/support/data/domain/PageRequest.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.support.data.domain; 2 | 3 | import lombok.NoArgsConstructor; 4 | import lombok.Setter; 5 | 6 | import java.io.Serializable; 7 | 8 | /** 9 | * User : liulu 10 | * Date : 2016-10-5 11:03 11 | */ 12 | @Setter 13 | @NoArgsConstructor 14 | public class PageRequest implements Pageable, Serializable { 15 | 16 | private static final long serialVersionUID = -2502137541842239335L; 17 | 18 | private static final int MAX_PAGE_SIZE = 200; 19 | 20 | private transient Sort sort; 21 | 22 | /** 23 | * 每页记录数 24 | */ 25 | protected int pageSize = 20; 26 | 27 | /** 28 | * 当前页 29 | */ 30 | protected int pageNum = 1; 31 | 32 | /** 33 | * 是否查询总记录数 34 | */ 35 | protected boolean count = true; 36 | 37 | 38 | public PageRequest(int pageSize, int pageNum) { 39 | this.pageSize = pageSize; 40 | this.pageNum = pageNum; 41 | } 42 | 43 | public PageRequest(int pageSize, int pageNum, boolean count) { 44 | this.pageSize = pageSize; 45 | this.pageNum = pageNum; 46 | this.count = count; 47 | } 48 | 49 | @Override 50 | public int getOffset() { 51 | return getPageSize() * (getPageNum() - 1); 52 | } 53 | 54 | @Override 55 | public int getPageSize() { 56 | return Math.min(MAX_PAGE_SIZE, Math.max(1, pageSize)); 57 | } 58 | 59 | @Override 60 | public int getPageNum() { 61 | return Math.max(1, pageNum); 62 | } 63 | 64 | @Override 65 | public boolean isCount() { 66 | return count; 67 | } 68 | 69 | @Override 70 | public Sort getSort() { 71 | return sort; 72 | } 73 | 74 | 75 | } 76 | -------------------------------------------------------------------------------- /lit-support/src/main/java/com/github/lit/support/data/domain/PageUtils.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.support.data.domain; 2 | 3 | import com.github.lit.support.util.bean.BeanUtils; 4 | 5 | import java.util.List; 6 | import java.util.function.BiConsumer; 7 | 8 | /** 9 | * @author liulu 10 | * @version v1.0 11 | * date 2018-12-22 12:53 12 | */ 13 | public abstract class PageUtils { 14 | 15 | 16 | public static Page convert(Page sPage, Class tClass) { 17 | return convert(sPage, tClass, null); 18 | } 19 | 20 | public static Page convert(Page sPage, Class tClass, BiConsumer consumer) { 21 | Page result = new Page<>(); 22 | result.setPageInfo(sPage.getPageInfo()); 23 | result.addAll(sPage.getAdditional()); 24 | 25 | List tList = BeanUtils.convertList(tClass, sPage.getData(), consumer); 26 | result.setData(tList); 27 | 28 | return result; 29 | } 30 | 31 | 32 | } 33 | -------------------------------------------------------------------------------- /lit-support/src/main/java/com/github/lit/support/data/domain/Pageable.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.support.data.domain; 2 | 3 | /** 4 | * @author liulu 5 | * @version v1.0 6 | * date 2018-12-21 18:58 7 | */ 8 | public interface Pageable { 9 | 10 | 11 | int getPageNum(); 12 | 13 | int getPageSize(); 14 | 15 | int getOffset(); 16 | 17 | Sort getSort(); 18 | 19 | default boolean isCount() { 20 | return true; 21 | } 22 | 23 | 24 | } 25 | -------------------------------------------------------------------------------- /lit-support/src/main/java/com/github/lit/support/data/domain/Sort.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.support.data.domain; 2 | 3 | import com.github.lit.support.util.lamabda.SerializedFunction; 4 | import com.github.lit.support.util.lamabda.SerializedLambdaUtils; 5 | 6 | import java.util.Collections; 7 | import java.util.LinkedHashMap; 8 | import java.util.Map; 9 | import java.util.Objects; 10 | 11 | /** 12 | * not thread safe 13 | * 14 | * @author liulu 15 | * @version v1.0 16 | * date 2019-07-26 17 | */ 18 | public class Sort { 19 | 20 | private static final String ORDER_ASC = " ASC"; 21 | private static final String ORDER_DESC = " DESC"; 22 | 23 | private static final String DEFAULT_MESSAGE = "sort properties must not null!"; 24 | 25 | private Map orderByMap = new LinkedHashMap<>(); 26 | 27 | public static Sort init() { 28 | return new Sort(); 29 | } 30 | 31 | public Sort asc(String... properties) { 32 | Objects.requireNonNull(properties, DEFAULT_MESSAGE); 33 | for (String property : properties) { 34 | orderByMap.put(property, ORDER_ASC); 35 | } 36 | return this; 37 | } 38 | 39 | public Sort desc(String... properties) { 40 | Objects.requireNonNull(properties, DEFAULT_MESSAGE); 41 | for (String property : properties) { 42 | orderByMap.put(property, ORDER_DESC); 43 | } 44 | return this; 45 | } 46 | 47 | @SafeVarargs 48 | public final Sort asc(SerializedFunction... serializedFunctions) { 49 | return addSort(ORDER_ASC, serializedFunctions); 50 | } 51 | 52 | @SafeVarargs 53 | public final Sort desc(SerializedFunction... serializedFunctions) { 54 | return addSort(ORDER_DESC, serializedFunctions); 55 | } 56 | 57 | @SafeVarargs 58 | private final Sort addSort(String direction, SerializedFunction... serializedFunctions) { 59 | Objects.requireNonNull(serializedFunctions, DEFAULT_MESSAGE); 60 | for (SerializedFunction serializedFunction : serializedFunctions) { 61 | String property = SerializedLambdaUtils.getProperty(serializedFunction); 62 | orderByMap.put(property, direction); 63 | } 64 | return this; 65 | } 66 | 67 | public Map getOrderByMap() { 68 | return Collections.unmodifiableMap(orderByMap); 69 | } 70 | 71 | @Override 72 | public String toString() { 73 | StringBuilder sb = new StringBuilder(); 74 | for (Map.Entry entry : orderByMap.entrySet()) { 75 | if (sb.length() > 0) { 76 | sb.append(", "); 77 | } 78 | sb.append(entry.getKey()).append(entry.getValue()); 79 | } 80 | return sb.toString(); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /lit-support/src/main/java/com/github/lit/support/data/domain/TableMetaDate.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.support.data.domain; 2 | 3 | import com.github.lit.support.util.ClassUtils; 4 | import com.github.lit.support.util.NameUtils; 5 | import com.github.lit.support.util.bean.BeanUtils; 6 | import com.github.lit.support.util.lamabda.SerializedFunction; 7 | import com.github.lit.support.util.lamabda.SerializedLambdaUtils; 8 | import lombok.Getter; 9 | 10 | import javax.persistence.Column; 11 | import javax.persistence.Id; 12 | import javax.persistence.Table; 13 | import javax.persistence.Transient; 14 | import java.beans.PropertyDescriptor; 15 | import java.io.Serializable; 16 | import java.lang.reflect.Field; 17 | import java.lang.reflect.Modifier; 18 | import java.util.*; 19 | 20 | /** 21 | * @author liulu 22 | * @version : v1.0 23 | * date : 7/24/18 11:31 24 | */ 25 | @Getter 26 | public class TableMetaDate implements Serializable { 27 | 28 | private static final long serialVersionUID = 7433386817779746930L; 29 | 30 | private static final int DEFAULT_CACHE_LIMIT = 128; 31 | 32 | @SuppressWarnings("serial") 33 | private static final Map, TableMetaDate> TABLE_CACHE = 34 | new LinkedHashMap, TableMetaDate>(DEFAULT_CACHE_LIMIT, 0.75f, true) { 35 | @Override 36 | protected boolean removeEldestEntry(Map.Entry, TableMetaDate> eldest) { 37 | return size() > DEFAULT_CACHE_LIMIT; 38 | } 39 | }; 40 | 41 | private Class entityClass; 42 | 43 | /** 44 | * 表名 45 | */ 46 | private String tableName; 47 | 48 | /** 49 | * 主键属性名 50 | */ 51 | private String keyProperty; 52 | 53 | /** 54 | * 主键对应的列名 55 | */ 56 | private String keyColumn; 57 | 58 | /** 59 | * 属性名和字段名映射关系的 map 60 | */ 61 | private Map fieldColumnMap; 62 | 63 | /** 64 | * 字段类型 65 | */ 66 | private Map> fieldTypeMap; 67 | 68 | private TableMetaDate(Class clazz) { 69 | fieldColumnMap = new HashMap<>(); 70 | fieldTypeMap = new HashMap<>(); 71 | initTableInfo(clazz); 72 | } 73 | 74 | 75 | public static TableMetaDate forClass(Class entityClass) { 76 | synchronized (TABLE_CACHE) { 77 | return TABLE_CACHE.computeIfAbsent(entityClass, TableMetaDate::new); 78 | } 79 | } 80 | 81 | public String getBaseColumns() { 82 | Collection columns = fieldColumnMap.values(); 83 | if (columns.isEmpty()) { 84 | return ""; 85 | } 86 | Iterator iterator = columns.iterator(); 87 | StringBuilder sb = new StringBuilder(); 88 | while (iterator.hasNext()) { 89 | String next = iterator.next(); 90 | sb.append(tableName).append(".").append(next); 91 | if (iterator.hasNext()) { 92 | sb.append(", "); 93 | } 94 | } 95 | return sb.toString(); 96 | } 97 | 98 | /** 99 | * 根据注解初始化表信息, 100 | * 101 | * @param eClass 实体类的 class 102 | */ 103 | private void initTableInfo(Class eClass) { 104 | entityClass = eClass; 105 | Table tableAnnotation = eClass.getAnnotation(Table.class); 106 | tableName = tableAnnotation != null ? tableAnnotation.name() : NameUtils.getUnderLineName(eClass.getSimpleName()); 107 | 108 | Field[] fields = eClass.getDeclaredFields(); 109 | for (Field field : fields) { 110 | 111 | // 过滤静态字段和有 @Transient 注解的字段 112 | if (Modifier.isStatic(field.getModifiers()) || 113 | field.isAnnotationPresent(Transient.class) || 114 | !ClassUtils.isSimpleProperty(field.getType())) { 115 | continue; 116 | } 117 | 118 | String property = field.getName(); 119 | Column column = field.getAnnotation(Column.class); 120 | String columnName = column != null ? column.name() : NameUtils.getUnderLineName(property); 121 | 122 | // 主键信息 : 有 @Id 注解的字段,没有默认是 类名+Id 123 | if (field.isAnnotationPresent(Id.class) || (property.equalsIgnoreCase("id") && keyProperty == null)) { 124 | this.keyProperty = property; 125 | this.keyColumn = columnName; 126 | } 127 | // 将字段对应的列放到 map 中 128 | PropertyDescriptor descriptor = BeanUtils.getPropertyDescriptor(eClass, property); 129 | if (descriptor != null && descriptor.getReadMethod() != null && descriptor.getWriteMethod() != null) { 130 | fieldColumnMap.put(property, columnName); 131 | fieldTypeMap.put(property, field.getType()); 132 | } 133 | } 134 | fieldColumnMap = Collections.unmodifiableMap(fieldColumnMap); 135 | fieldTypeMap = Collections.unmodifiableMap(fieldTypeMap); 136 | } 137 | 138 | 139 | public String getColumn(SerializedFunction function) { 140 | Class lambdaClass = SerializedLambdaUtils.getLambdaClass(function); 141 | // 如果不是实体class的父类 142 | if (!lambdaClass.isAssignableFrom(entityClass)) { 143 | throw new IllegalArgumentException("illegal argument"); 144 | } 145 | String property = SerializedLambdaUtils.getProperty(function); 146 | return fieldColumnMap.get(property); 147 | } 148 | 149 | public String getColumn(String field) { 150 | String column = fieldColumnMap.get(field); 151 | return column == null || column.isEmpty() ? field : column; 152 | } 153 | 154 | public Boolean containsField(String field) { 155 | return fieldColumnMap.containsKey(field); 156 | } 157 | 158 | public Boolean containsColumn(String column) { 159 | return fieldColumnMap.containsValue(column); 160 | } 161 | 162 | 163 | } 164 | -------------------------------------------------------------------------------- /lit-support/src/main/java/com/github/lit/support/data/jdbc/AnnotationRowMapper.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.support.data.jdbc; 2 | 3 | import com.github.lit.support.util.NameUtils; 4 | import org.springframework.beans.BeanUtils; 5 | import org.springframework.core.annotation.AnnotationUtils; 6 | import org.springframework.jdbc.core.BeanPropertyRowMapper; 7 | import org.springframework.util.ReflectionUtils; 8 | 9 | import javax.persistence.Column; 10 | import javax.persistence.Transient; 11 | import java.beans.PropertyDescriptor; 12 | import java.lang.reflect.Field; 13 | import java.lang.reflect.Modifier; 14 | import java.util.Map; 15 | import java.util.Set; 16 | 17 | /** 18 | * @author liulu 19 | * @version v1.0 20 | * date 2018-12-15 21:42 21 | */ 22 | public class AnnotationRowMapper extends BeanPropertyRowMapper { 23 | 24 | public AnnotationRowMapper() { 25 | } 26 | 27 | public AnnotationRowMapper(Class mappedClass) { 28 | initialize(mappedClass); 29 | } 30 | 31 | @SuppressWarnings({"ConstantConditions", "unchecked"}) 32 | @Override 33 | protected void initialize(Class mappedClass) { 34 | super.initialize(mappedClass); 35 | 36 | Field mappedFields = ReflectionUtils.findField(this.getClass(), "mappedFields"); 37 | ReflectionUtils.makeAccessible(mappedFields); 38 | Field mappedProperties = ReflectionUtils.findField(this.getClass(), "mappedProperties"); 39 | ReflectionUtils.makeAccessible(mappedProperties); 40 | 41 | Map mappedFieldsMap = (Map) ReflectionUtils.getField(mappedFields, this); 42 | Set mappedPropertiesSet = (Set) ReflectionUtils.getField(mappedProperties, this); 43 | 44 | ReflectionUtils.doWithFields(mappedClass, field -> { 45 | if (Modifier.isStatic(field.getModifiers()) || 46 | field.isAnnotationPresent(Transient.class) || 47 | !BeanUtils.isSimpleValueType(field.getType())) { 48 | return; 49 | } 50 | PropertyDescriptor pd = BeanUtils.getPropertyDescriptor(mappedClass, field.getName()); 51 | if (pd != null && pd.getWriteMethod() != null) { 52 | Column column = AnnotationUtils.findAnnotation(field, Column.class); 53 | String columnName = column != null ? column.name().toLowerCase() 54 | : NameUtils.getUnderLineName(field.getName()); 55 | mappedFieldsMap.putIfAbsent(columnName, pd); 56 | String lowerPdName = pd.getName().toLowerCase(); 57 | if (!lowerPdName.equals(columnName)) { 58 | mappedFieldsMap.putIfAbsent(lowerPdName, pd); 59 | } 60 | mappedPropertiesSet.add(pd.getName()); 61 | } 62 | }); 63 | } 64 | 65 | 66 | /** 67 | * Static factory method to create a new {@code AnnotationRowMapper} 68 | * (with the mapped class specified only once). 69 | * 70 | * @param mappedClass the class that each row should be mapped to 71 | */ 72 | public static AnnotationRowMapper newInstance(Class mappedClass) { 73 | return new AnnotationRowMapper<>(mappedClass); 74 | } 75 | 76 | 77 | } 78 | -------------------------------------------------------------------------------- /lit-support/src/main/java/com/github/lit/support/data/jdbc/EnableJdbcSupport.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.support.data.jdbc; 2 | 3 | import org.springframework.context.annotation.Import; 4 | 5 | import java.lang.annotation.ElementType; 6 | import java.lang.annotation.Retention; 7 | import java.lang.annotation.RetentionPolicy; 8 | import java.lang.annotation.Target; 9 | 10 | /** 11 | * @author liulu 12 | * @version v1.0 13 | * date 2018-12-22 13:18 14 | */ 15 | @Target({ElementType.TYPE}) 16 | @Retention(RetentionPolicy.RUNTIME) 17 | @Import({JdbcSupportConfigure.class}) 18 | public @interface EnableJdbcSupport { 19 | } 20 | -------------------------------------------------------------------------------- /lit-support/src/main/java/com/github/lit/support/data/jdbc/JdbcRepository.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.support.data.jdbc; 2 | 3 | import com.github.lit.support.data.SQL; 4 | import com.github.lit.support.data.domain.Page; 5 | import com.github.lit.support.data.domain.Pageable; 6 | import com.github.lit.support.data.domain.Sort; 7 | import com.github.lit.support.util.lamabda.SerializedFunction; 8 | import org.springframework.stereotype.Repository; 9 | 10 | import java.util.Collection; 11 | import java.util.List; 12 | 13 | /** 14 | * @author liulu 15 | * @version v1.0 16 | * date 2018-12-09 23:03 17 | */ 18 | @Repository 19 | public interface JdbcRepository { 20 | 21 | int insert(E entity); 22 | 23 | int batchInsert(Collection eList); 24 | 25 | int update(E entity); 26 | 27 | int updateSelective(E entity); 28 | 29 | int delete(E entity); 30 | 31 | int deleteById(Class eClass, Long id); 32 | 33 | int deleteByIds(Class eClass, Collection ids); 34 | 35 | E selectById(Class eClass, Long id); 36 | 37 | List selectByIds(Class eClass, Collection ids); 38 | 39 | List selectAll(Class eClass); 40 | 41 | E selectByProperty(SerializedFunction serializedFunction, Object value); 42 | 43 | List selectListByProperty(SerializedFunction serializedFunction, Object value); 44 | 45 | List selectList(Class eClass, C condition); 46 | 47 | List selectListWithOrder(Class eClass, C condition, Sort sort); 48 | 49 | Page selectPageList(Class eClass, C condition); 50 | 51 | E selectForObject(SQL sql, Object args, Class requiredType); 52 | 53 | List selectForList(SQL sql, Object args, Class requiredType); 54 | 55 | Page selectForPageList(SQL sql, Pageable args, Class requiredType); 56 | 57 | int count(Class eClass); 58 | 59 | int countByProperty(SerializedFunction serializedFunction, Object value); 60 | 61 | 62 | } 63 | -------------------------------------------------------------------------------- /lit-support/src/main/java/com/github/lit/support/data/jdbc/JdbcRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.support.data.jdbc; 2 | 3 | import com.github.lit.support.data.SQL; 4 | import com.github.lit.support.data.SQLUtils; 5 | import com.github.lit.support.data.domain.*; 6 | import com.github.lit.support.util.ClassUtils; 7 | import com.github.lit.support.util.bean.BeanUtils; 8 | import com.github.lit.support.util.lamabda.SerializedFunction; 9 | import com.github.lit.support.util.lamabda.SerializedLambdaUtils; 10 | import lombok.Getter; 11 | import lombok.NoArgsConstructor; 12 | import lombok.Setter; 13 | import lombok.extern.slf4j.Slf4j; 14 | import org.springframework.dao.IncorrectResultSizeDataAccessException; 15 | import org.springframework.jdbc.core.ConnectionCallback; 16 | import org.springframework.jdbc.core.namedparam.EmptySqlParameterSource; 17 | import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; 18 | import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations; 19 | import org.springframework.jdbc.core.namedparam.SqlParameterSource; 20 | import org.springframework.jdbc.support.GeneratedKeyHolder; 21 | import org.springframework.jdbc.support.KeyHolder; 22 | import org.springframework.util.Assert; 23 | import org.springframework.util.CollectionUtils; 24 | import org.springframework.util.ReflectionUtils; 25 | import org.springframework.util.StringUtils; 26 | 27 | import java.beans.PropertyDescriptor; 28 | import java.util.*; 29 | 30 | /** 31 | * @author liulu 32 | * @version v1.0 33 | * date 2018-12-10 14:28 34 | */ 35 | @Slf4j 36 | @NoArgsConstructor 37 | public class JdbcRepositoryImpl implements JdbcRepository { 38 | 39 | private static final String PARAM = "param"; 40 | 41 | private static final String PARAM_EQ = " = :param"; 42 | 43 | private static final String PARAM_IN = " in (:param)"; 44 | 45 | @Setter 46 | private String dbName; 47 | 48 | @Getter 49 | @Setter 50 | private NamedParameterJdbcOperations jdbcOperations; 51 | 52 | 53 | private String getDbName() { 54 | if (StringUtils.isEmpty(dbName)) { 55 | dbName = jdbcOperations.getJdbcOperations() 56 | .execute((ConnectionCallback) con -> con.getMetaData().getDatabaseProductName()); 57 | } 58 | return dbName; 59 | } 60 | 61 | public JdbcRepositoryImpl(NamedParameterJdbcOperations jdbcOperations) { 62 | this.jdbcOperations = jdbcOperations; 63 | } 64 | 65 | @Override 66 | public int insert(E entity) { 67 | Objects.requireNonNull(entity, "insert with entity can not be null"); 68 | Class entityClass = entity.getClass(); 69 | TableMetaDate metaDate = TableMetaDate.forClass(entityClass); 70 | String sql = SQLUtils.insertSQL(entity, SQL.Type.JDBC).toString(); 71 | KeyHolder keyHolder = new GeneratedKeyHolder(); 72 | SqlParameterSource sqlParameterSource = getSqlParameterSource(entity); 73 | logSqlAndParams(sql, sqlParameterSource); 74 | int insert = jdbcOperations.update(sql, sqlParameterSource, keyHolder); 75 | PropertyDescriptor keyPs = BeanUtils.getPropertyDescriptor(entityClass, metaDate.getKeyProperty()); 76 | // set key property 77 | if (keyPs != null) { 78 | ReflectionUtils.invokeMethod(keyPs.getWriteMethod(), entity, 79 | Objects.requireNonNull(keyHolder.getKey()).longValue()); 80 | } 81 | return insert; 82 | } 83 | 84 | @Override 85 | public int batchInsert(Collection eList) { 86 | if (CollectionUtils.isEmpty(eList)) { 87 | return 0; 88 | } 89 | E entity = eList.iterator().next(); 90 | SQL sql = SQLUtils.insertSQL(entity, SQL.Type.JDBC); 91 | 92 | SqlParameterSource[] parameterSources = eList.stream() 93 | .map(this::getSqlParameterSource).toArray(SqlParameterSource[]::new); 94 | int[] updateResult = jdbcOperations.batchUpdate(sql.toString(), parameterSources); 95 | 96 | int row = 0; 97 | for (int res : updateResult) { 98 | row += res; 99 | } 100 | return row; 101 | } 102 | 103 | 104 | @Override 105 | public int update(E entity) { 106 | SQL sql = SQLUtils.updateSQL(entity, false, SQL.Type.JDBC); 107 | return jdbcOperations.update(sql.toString(), getSqlParameterSource(entity)); 108 | } 109 | 110 | @Override 111 | public int updateSelective(E entity) { 112 | String sql = SQLUtils.updateSQL(entity, true, SQL.Type.JDBC).toString(); 113 | SqlParameterSource sqlParameterSource = getSqlParameterSource(entity); 114 | logSqlAndParams(sql, sqlParameterSource); 115 | return jdbcOperations.update(sql, sqlParameterSource); 116 | } 117 | 118 | @Override 119 | public int delete(E entity) { 120 | Assert.notNull(entity, "deleteById with entity can not be null"); 121 | TableMetaDate metaDate = TableMetaDate.forClass(entity.getClass()); 122 | PropertyDescriptor keyPs = BeanUtils.getPropertyDescriptor(entity.getClass(), metaDate.getKeyProperty()); 123 | Assert.notNull(keyPs, "can not find key property from " + entity.getClass().getName()); 124 | Object keyValue = ReflectionUtils.invokeMethod(keyPs.getReadMethod(), entity); 125 | Assert.notNull(keyValue, "key value can not be null"); 126 | 127 | String sql = SQLUtils.deleteSQL(entity.getClass(), SQL.Type.JDBC).toString(); 128 | SqlParameterSource sqlParam = getSqlParameterSource(Collections.singletonMap(metaDate.getKeyProperty(), keyValue)); 129 | logSqlAndParams(sql, sqlParam); 130 | return jdbcOperations.update(sql, sqlParam); 131 | } 132 | 133 | @Override 134 | public int deleteById(Class eClass, Long id) { 135 | Assert.notNull(id, "id can not be null"); 136 | TableMetaDate metaDate = TableMetaDate.forClass(eClass); 137 | String sql = SQLUtils.deleteSQL(eClass, SQL.Type.JDBC).toString(); 138 | SqlParameterSource sqlParam = getSqlParameterSource(Collections.singletonMap(metaDate.getKeyProperty(), id)); 139 | logSqlAndParams(sql, sqlParam); 140 | return jdbcOperations.update(sql, sqlParam); 141 | } 142 | 143 | @Override 144 | public int deleteByIds(Class eClass, Collection ids) { 145 | if (CollectionUtils.isEmpty(ids)) { 146 | return 0; 147 | } 148 | TableMetaDate metaDate = TableMetaDate.forClass(eClass); 149 | String sql = SQL.init().DELETE_FROM(metaDate.getTableName()) 150 | .WHERE(metaDate.getKeyColumn() + PARAM_IN) 151 | .toString(); 152 | SqlParameterSource sqlParam = getSqlParameterSource(Collections.singletonMap(PARAM, ids)); 153 | logSqlAndParams(sql, sqlParam); 154 | return jdbcOperations.update(sql, sqlParam); 155 | } 156 | 157 | @Override 158 | public E selectById(Class eClass, Long id) { 159 | TableMetaDate metaDate = TableMetaDate.forClass(eClass); 160 | 161 | SQL sql = SQL.init().SELECT(metaDate.getBaseColumns()) 162 | .FROM(metaDate.getTableName()) 163 | .WHERE(metaDate.getKeyColumn() + PARAM_EQ); 164 | 165 | return selectForObject(sql, Collections.singletonMap(PARAM, id), eClass); 166 | } 167 | 168 | @Override 169 | public List selectByIds(Class eClass, Collection ids) { 170 | if (CollectionUtils.isEmpty(ids)) { 171 | return Collections.emptyList(); 172 | } 173 | TableMetaDate metaDate = TableMetaDate.forClass(eClass); 174 | 175 | SQL sql = SQL.init().SELECT(metaDate.getBaseColumns()) 176 | .FROM(metaDate.getTableName()) 177 | .WHERE(metaDate.getKeyColumn() + PARAM_IN); 178 | 179 | return selectForList(sql, Collections.singletonMap(PARAM, ids), eClass); 180 | } 181 | 182 | @Override 183 | public List selectAll(Class eClass) { 184 | TableMetaDate metaDate = TableMetaDate.forClass(eClass); 185 | String sql = SQL.init().SELECT(metaDate.getBaseColumns()) 186 | .FROM(metaDate.getTableName()) 187 | .toString(); 188 | logSqlAndParams(sql, null); 189 | return jdbcOperations.query(sql, Collections.emptyMap(), AnnotationRowMapper.newInstance(eClass)); 190 | } 191 | 192 | @Override 193 | public E selectByProperty(SerializedFunction serializedFunction, Object value) { 194 | Class eClass = SerializedLambdaUtils.getLambdaClass(serializedFunction); 195 | SQL sql = getSelectByPropertySql(serializedFunction, eClass); 196 | return selectForObject(sql, Collections.singletonMap(PARAM, value), eClass); 197 | } 198 | 199 | @Override 200 | public List selectListByProperty(SerializedFunction serializedFunction, Object value) { 201 | Class eClass = SerializedLambdaUtils.getLambdaClass(serializedFunction); 202 | String sql = getSelectByPropertySql(serializedFunction, eClass).toString(); 203 | SqlParameterSource sqlParams = getSqlParameterSource(Collections.singletonMap(PARAM, value)); 204 | logSqlAndParams(sql, sqlParams); 205 | return jdbcOperations.query(sql, sqlParams, AnnotationRowMapper.newInstance(eClass)); 206 | } 207 | 208 | private SQL getSelectByPropertySql(SerializedFunction serializedFunction, Class eClass) { 209 | String property = SerializedLambdaUtils.getProperty(serializedFunction); 210 | 211 | TableMetaDate metaDate = TableMetaDate.forClass(eClass); 212 | String column = metaDate.getFieldColumnMap().get(property); 213 | 214 | return SQL.init().SELECT(metaDate.getBaseColumns()) 215 | .FROM(metaDate.getTableName()) 216 | .WHERE(column + PARAM_EQ); 217 | } 218 | 219 | @Override 220 | public List selectList(Class eClass, C condition) { 221 | return selectListWithOrder(eClass, condition, null); 222 | } 223 | 224 | @Override 225 | public List selectListWithOrder(Class eClass, C condition, Sort sort) { 226 | String sql = SQLUtils.selectSQL(eClass, condition, sort, SQL.Type.JDBC).toString(); 227 | SqlParameterSource sqlParams = getSqlParameterSource(condition); 228 | logSqlAndParams(sql, sqlParams); 229 | return jdbcOperations.query(sql, sqlParams, AnnotationRowMapper.newInstance(eClass)); 230 | } 231 | 232 | @Override 233 | public Page selectPageList(Class eClass, C condition) { 234 | 235 | SQL sql = SQLUtils.selectSQL(eClass, condition, condition.getSort(), SQL.Type.JDBC); 236 | return selectForPageList(sql, condition, eClass); 237 | } 238 | 239 | @Override 240 | public E selectForObject(SQL sql, Object args, Class requiredType) { 241 | List rs = selectForList(sql, args, requiredType); 242 | if (CollectionUtils.isEmpty(rs)) { 243 | return null; 244 | } 245 | if (rs.size() > 1) { 246 | throw new IncorrectResultSizeDataAccessException(1, rs.size()); 247 | } 248 | return rs.iterator().next(); 249 | } 250 | 251 | @Override 252 | public List selectForList(SQL sql, Object args, Class requiredType) { 253 | if (args == null) { 254 | args = Collections.emptyMap(); 255 | } 256 | String sqlStr = sql.toString(); 257 | SqlParameterSource parameterSource = getSqlParameterSource(args); 258 | logSqlAndParams(sqlStr, parameterSource); 259 | if (ClassUtils.isSimpleValueType(requiredType)) { 260 | return jdbcOperations.queryForList(sqlStr, parameterSource, requiredType); 261 | } 262 | return jdbcOperations.query(sqlStr, parameterSource, AnnotationRowMapper.newInstance(requiredType)); 263 | } 264 | 265 | @Override 266 | public Page selectForPageList(SQL sql, Pageable args, Class requiredType) { 267 | Integer count = 0; 268 | SqlParameterSource sqlParameterSource = getSqlParameterSource(args); 269 | if (args.isCount()) { 270 | String countSql = sql.countSql(); 271 | logSqlAndParams(countSql, sqlParameterSource); 272 | count = jdbcOperations.queryForObject(countSql, sqlParameterSource, int.class); 273 | if (count == null || count <= 0) { 274 | return Page.emptyPage(); 275 | } 276 | } 277 | String pageSql = SQLUtils.getPageSql(getDbName(), sql.toString(), args.getPageSize(), args.getPageNum()); 278 | logSqlAndParams(pageSql, sqlParameterSource); 279 | List rs = jdbcOperations.query(pageSql, sqlParameterSource, AnnotationRowMapper.newInstance(requiredType)); 280 | 281 | PageInfo pageInfo = new PageInfo(args.getPageSize(), args.getPageNum(), count); 282 | return new Page<>(rs, pageInfo); 283 | } 284 | 285 | @Override 286 | public int count(Class eClass) { 287 | TableMetaDate metaDate = TableMetaDate.forClass(eClass); 288 | SQL sql = SQL.init().SELECT("count(*)") 289 | .FROM(metaDate.getTableName()); 290 | return selectForObject(sql, Collections.emptyMap(), int.class); 291 | } 292 | 293 | @Override 294 | public int countByProperty(SerializedFunction serializedFunction, Object value) { 295 | Class eClass = SerializedLambdaUtils.getLambdaClass(serializedFunction); 296 | String property = SerializedLambdaUtils.getProperty(serializedFunction); 297 | 298 | TableMetaDate metaDate = TableMetaDate.forClass(eClass); 299 | 300 | SQL sql = SQL.init().SELECT("count(*)") 301 | .FROM(metaDate.getTableName()) 302 | .WHERE(metaDate.getColumn(property) + PARAM_EQ); 303 | 304 | return selectForObject(sql, Collections.singletonMap(PARAM, value), int.class); 305 | } 306 | 307 | 308 | private void logSqlAndParams(String sql, SqlParameterSource params) { 309 | if (params == null || params.getParameterNames() == null) { 310 | log.info("\n sql: {} \n params: ", sql); 311 | return; 312 | } 313 | StringBuilder paramLog = new StringBuilder(); 314 | for (String parameterName : params.getParameterNames()) { 315 | Object value = params.getValue(parameterName); 316 | if (!StringUtils.isEmpty(value)) { 317 | paramLog.append(parameterName).append("=").append(value).append(", "); 318 | } 319 | } 320 | log.info("\n sql: {} \n params: {}", sql, paramLog); 321 | } 322 | 323 | private SqlParameterSource getSqlParameterSource(E params) { 324 | if (params == null) { 325 | return new EmptySqlParameterSource(); 326 | } 327 | Map paramMap = params instanceof Map ? (Map) params : BeanUtils.beanToMap(params); 328 | return new MapSqlParameterSource(paramMap); 329 | } 330 | 331 | } 332 | -------------------------------------------------------------------------------- /lit-support/src/main/java/com/github/lit/support/data/jdbc/JdbcSupportConfigure.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.support.data.jdbc; 2 | 3 | import org.springframework.beans.factory.annotation.Value; 4 | import org.springframework.context.ApplicationContext; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.core.annotation.Order; 7 | import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations; 8 | import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; 9 | import org.springframework.util.StringUtils; 10 | 11 | import javax.sql.DataSource; 12 | import java.util.Map; 13 | 14 | /** 15 | * @author liulu 16 | * @version v1.0 17 | * date 2018-12-22 13:02 18 | */ 19 | @Order 20 | public class JdbcSupportConfigure { 21 | 22 | @Value("${lit.support.jdbc.database:}") 23 | private String database; 24 | 25 | @Value("${lit.support.jdbc.dataSource:}") 26 | private String dataSourceName; 27 | 28 | @Value("${lit.support.jdbc.template:}") 29 | private String templateName; 30 | 31 | @Bean 32 | public JdbcRepository jdbcRepository(ApplicationContext context) { 33 | JdbcRepositoryImpl jdbcRepository = new JdbcRepositoryImpl(); 34 | if (StringUtils.hasText(database)) { 35 | jdbcRepository.setDbName(database.toUpperCase()); 36 | } 37 | 38 | Map jdbcOperationsBeans 39 | = context.getBeansOfType(NamedParameterJdbcOperations.class); 40 | if (jdbcOperationsBeans == null || jdbcOperationsBeans.isEmpty()) { 41 | Map dataSourceBeans = context.getBeansOfType(DataSource.class); 42 | if (dataSourceBeans == null || dataSourceBeans.isEmpty()) { 43 | throw new IllegalArgumentException("to enable jdbcRepository, need config DataSource or JdbcOperations bean"); 44 | } 45 | if (StringUtils.isEmpty(dataSourceName)) { 46 | DataSource dataSource = dataSourceBeans.values().iterator().next(); 47 | jdbcRepository.setJdbcOperations(new NamedParameterJdbcTemplate(dataSource)); 48 | return jdbcRepository; 49 | } 50 | DataSource dataSource = dataSourceBeans.get(dataSourceName); 51 | if (dataSource == null) { 52 | throw new IllegalArgumentException("no DataSource bean named: " + dataSourceName); 53 | } 54 | jdbcRepository.setJdbcOperations(new NamedParameterJdbcTemplate(dataSource)); 55 | return jdbcRepository; 56 | } 57 | 58 | if (StringUtils.isEmpty(templateName)) { 59 | jdbcRepository.setJdbcOperations(jdbcOperationsBeans.values().iterator().next()); 60 | return jdbcRepository; 61 | } 62 | NamedParameterJdbcOperations jdbcOperations = jdbcOperationsBeans.get(templateName); 63 | if (jdbcOperations == null) { 64 | throw new IllegalArgumentException("no NamedParameterJdbcOperations bean named: " + templateName); 65 | } 66 | jdbcRepository.setJdbcOperations(jdbcOperations); 67 | 68 | return jdbcRepository; 69 | } 70 | 71 | 72 | 73 | 74 | } 75 | -------------------------------------------------------------------------------- /lit-support/src/main/java/com/github/lit/support/data/mybatis/BaseMapper.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.support.data.mybatis; 2 | 3 | import com.github.lit.support.util.lamabda.SerializedFunction; 4 | import org.apache.ibatis.annotations.DeleteProvider; 5 | import org.apache.ibatis.annotations.InsertProvider; 6 | import org.apache.ibatis.annotations.Options; 7 | import org.apache.ibatis.annotations.Param; 8 | import org.apache.ibatis.annotations.SelectProvider; 9 | import org.apache.ibatis.annotations.UpdateProvider; 10 | 11 | import java.util.List; 12 | 13 | /** 14 | * @author liulu 15 | * @version : v1.0 16 | * date : 7/24/18 09:54 17 | */ 18 | public interface BaseMapper { 19 | 20 | /** 21 | * 新增一条记录 22 | * 23 | * @param entity 实体 24 | * @return 受影响记录 25 | */ 26 | @InsertProvider(type = BaseSqlProvider.class, method = "insert") 27 | @Options(useGeneratedKeys = true, keyColumn = "id") 28 | int insert(E entity); 29 | 30 | /** 31 | * 更新一条记录 32 | * 33 | * @param entity entity 34 | * @return 受影响记录 35 | */ 36 | @UpdateProvider(type = BaseSqlProvider.class, method = "update") 37 | int update(E entity); 38 | 39 | /** 40 | * 删除一条记录 41 | * 42 | * @param id id 43 | * @return 受影响记录 44 | */ 45 | @DeleteProvider(type = BaseSqlProvider.class, method = "deleteById") 46 | int deleteById(Long id); 47 | 48 | /** 49 | * 根据id查询 50 | * 51 | * @param id id 52 | * @return Entity 53 | */ 54 | @SelectProvider(type = BaseSqlProvider.class, method = "selectById") 55 | E selectById(Long id); 56 | 57 | /** 58 | * 根据属性查询一条记录 59 | * 60 | * @param function property 61 | * @param value value 62 | * @param R 63 | * @return Entity 64 | */ 65 | @SelectProvider(type = BaseSqlProvider.class, method = "selectByProperty") 66 | E selectByProperty(@Param("property") SerializedFunction function, @Param("value") Object value); 67 | 68 | /** 69 | * 根据属性查询记录列表 70 | * 71 | * @param function property 72 | * @param value value 73 | * @param R 74 | * @return Entity 75 | */ 76 | @SelectProvider(type = BaseSqlProvider.class, method = "selectByProperty") 77 | List selectListByProperty(@Param("property") SerializedFunction function, @Param("value") Object value); 78 | 79 | /** 80 | * 根据查询条件查询记录 81 | * 82 | * @param condition condition 83 | * @param Condition 84 | * @return List Entity 85 | */ 86 | @SelectProvider(type = BaseSqlProvider.class, method = "selectList") 87 | List selectList(C condition); 88 | 89 | 90 | } 91 | -------------------------------------------------------------------------------- /lit-support/src/main/java/com/github/lit/support/data/mybatis/BaseSqlProvider.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.support.data.mybatis; 2 | 3 | import com.github.lit.support.data.Logic; 4 | import com.github.lit.support.data.SQL; 5 | import com.github.lit.support.data.SQLUtils; 6 | import com.github.lit.support.data.domain.TableMetaDate; 7 | import com.github.lit.support.util.lamabda.SerializedFunction; 8 | import com.github.lit.support.util.lamabda.SerializedLambdaUtils; 9 | import lombok.extern.slf4j.Slf4j; 10 | import org.apache.ibatis.builder.annotation.ProviderContext; 11 | import org.springframework.core.ResolvableType; 12 | import org.springframework.util.Assert; 13 | 14 | import java.lang.reflect.Type; 15 | import java.util.Map; 16 | 17 | /** 18 | * @author liulu 19 | * @version : v1.0 20 | * date : 7/24/18 11:04 21 | */ 22 | @Slf4j 23 | public class BaseSqlProvider { 24 | 25 | public String insert(E entity) { 26 | Assert.notNull(entity, "entity must not null"); 27 | return SQLUtils.insertSQL(entity, SQL.Type.MYBATIS).toString(); 28 | } 29 | 30 | public String update(E entity) { 31 | Assert.notNull(entity, "entity must not null"); 32 | 33 | return SQLUtils.updateSQL(entity, true, SQL.Type.MYBATIS).toString(); 34 | } 35 | 36 | public String delete(ProviderContext context) { 37 | Class entityClass = getEntityClass(context); 38 | return SQLUtils.deleteSQL(entityClass, SQL.Type.MYBATIS).toString(); 39 | } 40 | 41 | public String selectById(ProviderContext context) { 42 | Class entityClass = getEntityClass(context); 43 | TableMetaDate mataDate = TableMetaDate.forClass(entityClass); 44 | 45 | return new SQL().SELECT(mataDate.getBaseColumns()) 46 | .FROM(mataDate.getTableName()) 47 | .WHERE(mataDate.getKeyColumn() + Logic.EQ.getCode() + "#{" + mataDate.getKeyProperty() + "}") 48 | .toString(); 49 | } 50 | 51 | public String selectByProperty(ProviderContext context, Map params) { 52 | SerializedFunction propertyFunction = (SerializedFunction) params.get("property"); 53 | String property = SerializedLambdaUtils.getProperty(propertyFunction); 54 | Class entityClass = getEntityClass(context); 55 | TableMetaDate mataDate = TableMetaDate.forClass(entityClass); 56 | String column = mataDate.getColumn(property); 57 | 58 | return new SQL().SELECT(mataDate.getBaseColumns()) 59 | .FROM(mataDate.getTableName()) 60 | .WHERE(column + Logic.EQ.getCode() + "#{value}") 61 | .toString(); 62 | } 63 | 64 | public String selectByCondition(ProviderContext context, Object condition) { 65 | Class entityClass = getEntityClass(context); 66 | return SQLUtils 67 | .selectSQL(entityClass, condition, null, SQL.Type.MYBATIS) 68 | .toString(); 69 | } 70 | 71 | private Class getEntityClass(ProviderContext context) { 72 | Class mapperType = context.getMapperType(); 73 | for (Type parent : mapperType.getGenericInterfaces()) { 74 | ResolvableType parentType = ResolvableType.forType(parent); 75 | if (parentType.getRawClass() == BaseMapper.class) { 76 | return parentType.getGeneric(0).getRawClass(); 77 | } 78 | } 79 | return null; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /lit-support/src/main/java/com/github/lit/support/data/mybatis/EnambeMybatisSupport.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.support.data.mybatis; 2 | 3 | import org.springframework.context.annotation.Import; 4 | 5 | import java.lang.annotation.ElementType; 6 | import java.lang.annotation.Retention; 7 | import java.lang.annotation.RetentionPolicy; 8 | import java.lang.annotation.Target; 9 | 10 | /** 11 | * @author liulu 12 | * @version v1.0 13 | * date 2018-12-22 13:51 14 | */ 15 | @Target({ElementType.TYPE}) 16 | @Retention(RetentionPolicy.RUNTIME) 17 | @Import({MyBatisSupportConfigure.class}) 18 | public @interface EnambeMybatisSupport { 19 | } 20 | -------------------------------------------------------------------------------- /lit-support/src/main/java/com/github/lit/support/data/mybatis/MyBatisSupportConfigure.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.support.data.mybatis; 2 | 3 | import org.apache.ibatis.session.SqlSessionFactory; 4 | 5 | import javax.annotation.PostConstruct; 6 | import javax.annotation.Resource; 7 | import java.util.List; 8 | 9 | /** 10 | * @author liulu 11 | * @version v1.0 12 | * date 2018-12-11 19:49 13 | */ 14 | public class MyBatisSupportConfigure { 15 | 16 | @Resource 17 | private List sqlSessionFactoryList; 18 | 19 | @PostConstruct 20 | public void addInterceptor() { 21 | // 22 | ResultMapInterceptor resultMapInterceptor = new ResultMapInterceptor(); 23 | for (SqlSessionFactory sqlSessionFactory : sqlSessionFactoryList) { 24 | sqlSessionFactory.getConfiguration().addInterceptor(resultMapInterceptor); 25 | } 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /lit-support/src/main/java/com/github/lit/support/data/mybatis/ResultMapInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.support.data.mybatis; 2 | 3 | import com.github.lit.support.data.domain.TableMetaDate; 4 | import org.apache.ibatis.cache.CacheKey; 5 | import org.apache.ibatis.executor.Executor; 6 | import org.apache.ibatis.mapping.BoundSql; 7 | import org.apache.ibatis.mapping.MappedStatement; 8 | import org.apache.ibatis.mapping.ResultMap; 9 | import org.apache.ibatis.mapping.ResultMapping; 10 | import org.apache.ibatis.plugin.Interceptor; 11 | import org.apache.ibatis.plugin.Intercepts; 12 | import org.apache.ibatis.plugin.Invocation; 13 | import org.apache.ibatis.plugin.Plugin; 14 | import org.apache.ibatis.plugin.Signature; 15 | import org.apache.ibatis.session.ResultHandler; 16 | import org.apache.ibatis.session.RowBounds; 17 | import org.springframework.util.ClassUtils; 18 | import org.springframework.util.CollectionUtils; 19 | import org.springframework.util.ReflectionUtils; 20 | 21 | import java.lang.reflect.Field; 22 | import java.util.ArrayList; 23 | import java.util.Collection; 24 | import java.util.Collections; 25 | import java.util.List; 26 | import java.util.Map; 27 | import java.util.Properties; 28 | 29 | /** 30 | * User : liulu 31 | * Date : 2018/7/11 12:42 32 | * version $Id: ResultMapInterceptor.java, v 0.1 Exp $ 33 | */ 34 | @Intercepts({ 35 | @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}), 36 | @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}), 37 | }) 38 | public class ResultMapInterceptor implements Interceptor { 39 | 40 | @Override 41 | public Object intercept(Invocation invocation) throws Throwable { 42 | if (!(invocation.getTarget() instanceof Executor)) { 43 | return invocation.proceed(); 44 | } 45 | MappedStatement ms = (MappedStatement) invocation.getArgs()[0]; 46 | 47 | // xml sql 不做处理 48 | if (ms.getResource().contains(".xml")) { 49 | return invocation.proceed(); 50 | } 51 | ResultMap resultMap = ms.getResultMaps().iterator().next(); 52 | if (!CollectionUtils.isEmpty(resultMap.getResultMappings())) { 53 | return invocation.proceed(); 54 | } 55 | Class mapType = resultMap.getType(); 56 | if (ClassUtils.isAssignable(mapType, Collection.class)) { 57 | return invocation.proceed(); 58 | } 59 | TableMetaDate mataDate = TableMetaDate.forClass(mapType); 60 | Map> fieldTypeMap = mataDate.getFieldTypeMap(); 61 | // 62 | List resultMappings = new ArrayList<>(fieldTypeMap.size()); 63 | for (Map.Entry entry : mataDate.getFieldColumnMap().entrySet()) { 64 | ResultMapping resultMapping = new ResultMapping.Builder(ms.getConfiguration(), entry.getKey(), entry.getValue(), fieldTypeMap.get(entry.getKey())).build(); 65 | resultMappings.add(resultMapping); 66 | } 67 | ResultMap newRm = new ResultMap.Builder(ms.getConfiguration(), resultMap.getId(), mapType, resultMappings).build(); 68 | 69 | Field field = ReflectionUtils.findField(MappedStatement.class, "resultMaps"); 70 | ReflectionUtils.makeAccessible(field); 71 | ReflectionUtils.setField(field, ms, Collections.singletonList(newRm)); 72 | 73 | return invocation.proceed(); 74 | } 75 | 76 | @Override 77 | public Object plugin(Object target) { 78 | return Plugin.wrap(target, this); 79 | } 80 | 81 | @Override 82 | public void setProperties(Properties properties) { 83 | // 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /lit-support/src/main/java/com/github/lit/support/exception/BizException.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.support.exception; 2 | 3 | /** 4 | * User : liulu 5 | * Date : 2018-03-11 13:28 6 | * version $Id: BizException.java, v 0.1 Exp $ 7 | */ 8 | public class BizException extends LitException { 9 | 10 | private static final long serialVersionUID = 5060380635604270427L; 11 | 12 | public BizException() { 13 | super(); 14 | } 15 | 16 | public BizException(ExceptionDefinition exceptionDefinition) { 17 | super(exceptionDefinition); 18 | } 19 | 20 | public BizException(String message) { 21 | super(message); 22 | } 23 | 24 | public BizException(String code, String message) { 25 | super(code, message); 26 | } 27 | 28 | public BizException(String message, Throwable cause) { 29 | super(message, cause); 30 | } 31 | 32 | public BizException(String code, String message, Throwable cause) { 33 | super(code, message, cause); 34 | } 35 | 36 | public BizException(Throwable cause) { 37 | super(cause); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /lit-support/src/main/java/com/github/lit/support/exception/ExceptionDefinition.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.support.exception; 2 | 3 | /** 4 | * @author liulu 5 | * @version v1.0 6 | * date 2019-02-12 10:49 7 | */ 8 | public interface ExceptionDefinition { 9 | 10 | String getCode(); 11 | 12 | String getMessage(); 13 | 14 | } 15 | -------------------------------------------------------------------------------- /lit-support/src/main/java/com/github/lit/support/exception/LitException.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.support.exception; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | /** 7 | * User : liulu 8 | * Date : 2018-03-11 13:37 9 | * version $Id: LitException.java, v 0.1 Exp $ 10 | */ 11 | class LitException extends RuntimeException { 12 | 13 | private static final long serialVersionUID = -7052223373308595812L; 14 | 15 | @Getter 16 | @Setter 17 | private String code; 18 | 19 | LitException() { 20 | super(); 21 | } 22 | 23 | LitException(ExceptionDefinition exceptionDefinition) { 24 | super(exceptionDefinition.getMessage()); 25 | this.code = exceptionDefinition.getCode(); 26 | } 27 | 28 | LitException(String message) { 29 | super(message); 30 | } 31 | 32 | LitException(String code, String message) { 33 | super(message); 34 | this.code = code; 35 | } 36 | 37 | LitException(String message, Throwable cause) { 38 | super(message, cause); 39 | } 40 | 41 | LitException(String code, String message, Throwable cause) { 42 | super(message, cause); 43 | this.code = code; 44 | } 45 | 46 | LitException(Throwable cause) { 47 | super(cause); 48 | } 49 | 50 | 51 | } 52 | -------------------------------------------------------------------------------- /lit-support/src/main/java/com/github/lit/support/exception/SysException.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.support.exception; 2 | 3 | /** 4 | * User : liulu 5 | * Date : 2018-03-11 13:36 6 | * version $Id: SysException.java, v 0.1 Exp $ 7 | */ 8 | public class SysException extends LitException { 9 | 10 | public SysException() { 11 | super(); 12 | } 13 | 14 | public SysException(ExceptionDefinition exceptionDefinition) { 15 | super(exceptionDefinition); 16 | } 17 | 18 | public SysException(String message) { 19 | super(message); 20 | } 21 | 22 | public SysException(String code, String message) { 23 | super(code, message); 24 | } 25 | 26 | public SysException(String message, Throwable cause) { 27 | super(message, cause); 28 | } 29 | 30 | public SysException(String code, String message, Throwable cause) { 31 | super(code, message, cause); 32 | } 33 | 34 | public SysException(Throwable cause) { 35 | super(cause); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /lit-support/src/main/java/com/github/lit/support/util/DateTimeUtils.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.support.util; 2 | 3 | import java.time.format.DateTimeFormatter; 4 | import java.util.Calendar; 5 | import java.util.Date; 6 | 7 | /** 8 | * User : liulu 9 | * Date : 2018/3/15 16:55 10 | * version $Id: DateTimeUtils.java, v 0.1 Exp $ 11 | */ 12 | public abstract class DateTimeUtils { 13 | 14 | private static final DateTimeFormatter DATE = DateTimeFormatter.ofPattern("yyyy-MM-dd"); 15 | 16 | private static final DateTimeFormatter TIME = DateTimeFormatter.ofPattern("HH:mm:ss"); 17 | 18 | private static final DateTimeFormatter DATE_TIME = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); 19 | 20 | 21 | public static Date firstDayOfMonth(Date origin) { 22 | Calendar calendar = Calendar.getInstance(); 23 | calendar.setTime(origin); 24 | calendar.set(Calendar.DAY_OF_MONTH, 1); 25 | calendar.set(Calendar.HOUR_OF_DAY, 0); 26 | calendar.set(Calendar.MINUTE, 0); 27 | calendar.set(Calendar.SECOND, 0); 28 | return calendar.getTime(); 29 | } 30 | 31 | public static Date lastDayOfMonth(Date origin) { 32 | Calendar calendar = Calendar.getInstance(); 33 | calendar.setTime(origin); 34 | int actualMaximum = calendar.getActualMaximum(Calendar.DAY_OF_MONTH); 35 | calendar.set(Calendar.DAY_OF_MONTH, actualMaximum); 36 | calendar.set(Calendar.HOUR_OF_DAY, 0); 37 | calendar.set(Calendar.MINUTE, 0); 38 | calendar.set(Calendar.SECOND, 0); 39 | return calendar.getTime(); 40 | } 41 | 42 | 43 | } 44 | -------------------------------------------------------------------------------- /lit-support/src/main/java/com/github/lit/support/util/NameUtils.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.support.util; 2 | 3 | /** 4 | * 命名工具类 5 | * User : liulu 6 | * Date : 2016-10-4 16:05 7 | */ 8 | public abstract class NameUtils { 9 | 10 | private NameUtils() {} 11 | 12 | /** 13 | * 下划线分割命名转换为驼峰命名 14 | * 15 | * @param name 下划线命名 16 | * @return 驼峰命名 17 | */ 18 | public static String getCamelName(String name) { 19 | return getCamelName(name, "_"); 20 | } 21 | 22 | /** 23 | * 获取指定字符分隔的驼峰命名 24 | * 25 | * @param name 指定分隔符命名 26 | * @param delimiter 分隔符 27 | * @return 驼峰命名 28 | */ 29 | public static String getCamelName(String name, String delimiter) { 30 | 31 | if (name == null || name.isEmpty()) { 32 | return ""; 33 | } 34 | 35 | char delimiterChar = delimiter.charAt(0); 36 | 37 | StringBuilder sb = new StringBuilder(); 38 | name = name.toLowerCase(); 39 | 40 | for (int i = 0; i < name.length(); i++) { 41 | char c = name.charAt(i); 42 | if (c == delimiterChar) { 43 | i++; 44 | sb.append(Character.toUpperCase(name.charAt(i))); 45 | } else { 46 | sb.append(c); 47 | } 48 | } 49 | 50 | return sb.toString(); 51 | } 52 | 53 | /** 54 | * 将名称首字母大写 55 | * 56 | * @param name 原名称 57 | * @return 首字母大写名称 58 | */ 59 | public static String getFirstUpperName(String name) { 60 | if (name == null || name.isEmpty()) { 61 | return ""; 62 | } 63 | return Character.toUpperCase(name.charAt(0)) + name.substring(1); 64 | } 65 | 66 | /** 67 | * @param name 原名称 68 | * @return 首字母小写名称 69 | */ 70 | public static String getFirstLowerName(String name) { 71 | if (name == null || name.isEmpty()) { 72 | return ""; 73 | } 74 | if (Character.isLowerCase(name.charAt(0))) { 75 | return name; 76 | } 77 | return Character.toLowerCase(name.charAt(0)) + name.substring(1); 78 | } 79 | 80 | /** 81 | * 驼峰命名转换为小写下划线分割命名 82 | * 83 | * @param name 驼峰命名 84 | * @return 下划线命名 85 | */ 86 | public static String getUnderLineName(String name) { 87 | return getLowerDelimiterName(name, "_"); 88 | } 89 | 90 | /** 91 | * 驼峰命名转换为小写指定分隔符命名 92 | * 93 | * @param name 驼峰命名 94 | * @param delimiter 指定分隔符 95 | * @return 小写指定分隔符命名 96 | */ 97 | public static String getLowerDelimiterName(String name, String delimiter) { 98 | return getUpperDelimiterName(name, delimiter).toLowerCase(); 99 | } 100 | 101 | /** 102 | * 驼峰命名转换为大写指定分隔符命名 103 | * 104 | * @param name 驼峰命名 105 | * @param delimiter 指定分隔符 106 | * @return 大写指定分隔符命名 107 | */ 108 | public static String getUpperDelimiterName(String name, String delimiter) { 109 | 110 | if (name == null || name.isEmpty()) { 111 | return ""; 112 | } 113 | StringBuilder sb = new StringBuilder(); 114 | for (int i = 0; i < name.length(); i++) { 115 | char c = name.charAt(i); 116 | if (i > 0 && Character.isUpperCase(c)) { 117 | sb.append(delimiter); 118 | } 119 | sb.append(c); 120 | } 121 | return sb.toString().toUpperCase(); 122 | } 123 | 124 | } 125 | -------------------------------------------------------------------------------- /lit-support/src/main/java/com/github/lit/support/util/PropertyUtils.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.support.util; 2 | 3 | import java.io.*; 4 | import java.util.HashMap; 5 | import java.util.Iterator; 6 | import java.util.Map; 7 | import java.util.Properties; 8 | 9 | /** 10 | * User : liulu 11 | * Date : 2017-1-9 21:24 12 | * version $Id: PropertyUtils.java, v 0.1 Exp $ 13 | */ 14 | public abstract class PropertyUtils { 15 | /** 16 | * 属性文件后缀 17 | */ 18 | private static final String PRO_SUFFIX = ".properties"; 19 | 20 | /** 21 | * 配置文件保存map 22 | */ 23 | private static Map propMap = new HashMap(); 24 | 25 | 26 | /** 27 | * 加载资源文件 28 | * 29 | * @param resourceName 资源名 30 | * @return 资源输入流 31 | */ 32 | public static InputStream loadResource(String resourceName) { 33 | 34 | try { 35 | File configFile = getConfigFile(resourceName); 36 | if (configFile == null) { 37 | InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(resourceName); 38 | return is; 39 | } else { 40 | return new FileInputStream(configFile); 41 | } 42 | } catch (FileNotFoundException e) { 43 | throw new RuntimeException("加载xml文件失败:" + resourceName, e); 44 | } 45 | } 46 | 47 | /** 48 | * 加载properties文件 49 | * 50 | * @param resourceName the resource name 51 | */ 52 | public static void loadProperties(String resourceName) { 53 | 54 | try { 55 | if (!resourceName.endsWith(PRO_SUFFIX)) { 56 | resourceName += PRO_SUFFIX; 57 | } 58 | Properties prop = new Properties(); 59 | prop.load(loadResource(resourceName)); 60 | Iterator> iterator = prop.entrySet().iterator(); 61 | while (iterator.hasNext()) { 62 | Map.Entry entry = iterator.next(); 63 | propMap.put(resourceName + String.valueOf(entry.getKey()), String.valueOf(entry.getValue())); 64 | } 65 | //为配置文件加入一个属性,用以判断该配置文件已加载过 66 | propMap.put(resourceName, "true"); 67 | } catch (IOException e) { 68 | throw new RuntimeException("加载配置文件失败:" + resourceName, e); 69 | } 70 | } 71 | 72 | /** 73 | * 根据key获取properties文件的value值 74 | * 75 | * @param resourceName properties文件名 76 | * @param key properties文件key 77 | * @return properties文件value 78 | */ 79 | public static String getProperty(String resourceName, String key) { 80 | return getProperty(resourceName, key, null); 81 | } 82 | 83 | /** 84 | * 根据key获取properties文件的value值 85 | * 86 | * @param resourceName properties文件名 87 | * @param key the key 88 | * @param defaultValue 不存在时返回的默认值 89 | * @return property 90 | */ 91 | public static String getProperty(String resourceName, String key, String defaultValue) { 92 | if (!resourceName.endsWith(PRO_SUFFIX)) { 93 | resourceName += PRO_SUFFIX; 94 | } 95 | String finalKey = resourceName + key; 96 | if (propMap.get(resourceName) == null) { 97 | loadProperties(resourceName); 98 | } 99 | String value = propMap.get(finalKey); 100 | return value == null ? defaultValue : value; 101 | } 102 | 103 | /** 104 | * 获取web容器的配置目录 105 | * 106 | * @return 文件 107 | */ 108 | private static File getConfigFile(String resourceName) { 109 | 110 | //tomcat 111 | String resourcePath = System.getProperty("catalina.home") + "/conf"; 112 | File file = new File(resourcePath, resourceName); 113 | if (file.exists()) { 114 | return file; 115 | } 116 | //程序目录 117 | resourcePath = System.getProperty("user.dir"); 118 | file = new File(resourcePath, resourceName); 119 | if (file.exists()) { 120 | return file; 121 | } 122 | return null; 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /lit-support/src/main/java/com/github/lit/support/util/RandomUtils.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.support.util; 2 | 3 | import java.util.Random; 4 | 5 | /** 6 | * User : liulu 7 | * Date : 2018/3/15 16:56 8 | * version $Id: RandomUtils.java, v 0.1 Exp $ 9 | */ 10 | public abstract class RandomUtils { 11 | 12 | private RandomUtils() {} 13 | 14 | private static final char[] LOWER_CASE = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'}; 15 | 16 | private static final char[] UPPER_CASE = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'}; 17 | 18 | private static final int[] NUMBER = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; 19 | 20 | private static final Random RANDOM = new Random(); 21 | 22 | 23 | public static String getNumber(int length) { 24 | StringBuilder result = new StringBuilder(length); 25 | for (int i = 0; i < length; i++) { 26 | result.append((RANDOM.nextInt(10))); 27 | } 28 | return result.toString(); 29 | } 30 | 31 | public static String getLowCase(int length) { 32 | StringBuilder result = new StringBuilder(length); 33 | for (int i = 0; i < length; i++) { 34 | int randomIndex = RANDOM.nextInt(LOWER_CASE.length); 35 | result.append(LOWER_CASE[randomIndex]); 36 | } 37 | return result.toString(); 38 | } 39 | 40 | public static String getUpperCase(int length) { 41 | StringBuilder result = new StringBuilder(length); 42 | for (int i = 0; i < length; i++) { 43 | int randomIndex = RANDOM.nextInt(UPPER_CASE.length); 44 | result.append(UPPER_CASE[randomIndex]); 45 | } 46 | return result.toString(); 47 | } 48 | 49 | 50 | } 51 | -------------------------------------------------------------------------------- /lit-support/src/main/java/com/github/lit/support/util/SpelUtils.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.support.util; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.springframework.expression.ExpressionParser; 5 | import org.springframework.expression.spel.standard.SpelExpressionParser; 6 | import org.springframework.expression.spel.support.StandardEvaluationContext; 7 | 8 | import java.util.Map; 9 | 10 | /** 11 | * User : liulu 12 | * Date : 2018/3/25 17:07 13 | * version $Id: SpelUtils.java, v 0.1 Exp $ 14 | */ 15 | @Slf4j 16 | public abstract class SpelUtils { 17 | 18 | private static final ExpressionParser expressionParser = new SpelExpressionParser(); 19 | 20 | 21 | public static String getExpressionValue(String expr, Map content) { 22 | 23 | StandardEvaluationContext evaluationContext = new StandardEvaluationContext(); 24 | evaluationContext.setVariables(content); 25 | 26 | try { 27 | return expressionParser.parseExpression(expr).getValue(evaluationContext, String.class); 28 | } catch (Exception e) { 29 | // 30 | log.warn("parse el expression {} failed, because of {}", expr, e.getMessage()); 31 | } 32 | return expr; 33 | } 34 | 35 | 36 | } 37 | -------------------------------------------------------------------------------- /lit-support/src/main/java/com/github/lit/support/util/SpringContextUtils.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.support.util; 2 | 3 | import org.springframework.beans.BeansException; 4 | import org.springframework.context.ApplicationContext; 5 | import org.springframework.context.ApplicationContextAware; 6 | import org.springframework.core.env.Environment; 7 | 8 | import java.lang.annotation.Annotation; 9 | import java.util.Map; 10 | 11 | /** 12 | * User : liulu 13 | * Date : 2017-2-21 18:22 14 | * version $Id: ApplicationContextUtils.java, v 0.1 Exp $ 15 | */ 16 | public abstract class SpringContextUtils implements ApplicationContextAware { 17 | 18 | private SpringContextUtils(){} 19 | 20 | private static ApplicationContext context; 21 | 22 | private static Environment environment; 23 | 24 | public static T getBean(Class clazz) { 25 | return context.getBean(clazz); 26 | } 27 | 28 | public static T getBean(Class clazz, Object... objects) { 29 | return context.getBean(clazz, objects); 30 | } 31 | 32 | public static Object getBean(String name) { 33 | return context.getBean(name); 34 | } 35 | 36 | public static Object getBean(String name, Object... objects) { 37 | return context.getBean(name, objects); 38 | } 39 | 40 | public static T getBean(String name, Class clazz) { 41 | return context.getBean(name, clazz); 42 | } 43 | 44 | public static Map getBeansOfType(Class clazz) { 45 | return context.getBeansOfType(clazz); 46 | } 47 | 48 | public static Map getBeansWithAnnotation(Class clazz) { 49 | return context.getBeansWithAnnotation(clazz); 50 | } 51 | 52 | public static String getProperty (String key) { 53 | return environment.getProperty(key); 54 | } 55 | 56 | public static String getProperty (String key, String defaultValue) { 57 | return environment.getProperty(key, defaultValue); 58 | } 59 | 60 | public static T getProperty (String key, Class targetType) { 61 | return environment.getProperty(key, targetType); 62 | } 63 | 64 | public static T getProperty (String key, Class targetType, T defaultValue) { 65 | return environment.getProperty(key, targetType, defaultValue); 66 | } 67 | 68 | @Override 69 | public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 70 | context = applicationContext; 71 | environment = applicationContext.getEnvironment(); 72 | } 73 | 74 | public static ApplicationContext getApplicationContext(){ 75 | return context; 76 | } 77 | 78 | public static Environment getEnvironment() { 79 | return environment; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /lit-support/src/main/java/com/github/lit/support/util/TokenUtils.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.support.util; 2 | 3 | import java.util.Map; 4 | 5 | /** 6 | * User : liulu 7 | * Date : 2018/2/7 15:36 8 | * version $Id: ConstantUtils.java, v 0.1 Exp $ 9 | */ 10 | public abstract class TokenUtils { 11 | 12 | private static final String OPEN_TOKEN = "${"; 13 | 14 | private static final String CLOSE_TOKEN = "}"; 15 | 16 | private TokenUtils() {} 17 | 18 | 19 | public static String parseToken(Map context, String text) { 20 | return parseToken(context, text, OPEN_TOKEN, CLOSE_TOKEN); 21 | } 22 | 23 | public static String parseToken(Map context, String text, String openToken, String closeToken) { 24 | if (text == null || text.isEmpty()) { 25 | return text; 26 | } 27 | StringBuilder result = new StringBuilder(text.length() + 100); 28 | 29 | char[] src = text.toCharArray(); 30 | int offset = 0; 31 | int start = text.indexOf(openToken, offset); 32 | 33 | while (start > -1) { 34 | result.append(src, offset, start - offset); 35 | // 查找 closeToken 36 | int end = text.indexOf(closeToken, start); 37 | // closeToken 不存在 38 | if (end < 0) { 39 | offset = start; 40 | break; 41 | } 42 | // openToken 和 closeToken 之间的 key 43 | String key = String.valueOf(src, start + openToken.length(), end - start - openToken.length()); 44 | // key 对应的 value 存在 -> 替换, 不存在 -> 不做处理 45 | String value = context.get(key); 46 | if (value != null && !value.isEmpty()) { 47 | result.append(value); 48 | } else { 49 | result.append(src, start, end - start + closeToken.length()); 50 | } 51 | offset = end + closeToken.length(); 52 | start = text.indexOf(openToken, offset); 53 | } 54 | 55 | if (src.length - offset > 0) { 56 | result.append(src, offset, src.length - offset); 57 | } 58 | return result.toString(); 59 | } 60 | 61 | 62 | } 63 | -------------------------------------------------------------------------------- /lit-support/src/main/java/com/github/lit/support/util/UUIDUtils.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.support.util; 2 | 3 | import java.util.UUID; 4 | 5 | /** 6 | * User : liulu 7 | * Date : 2017-3-6 20:33 8 | * version $Id: UUIDUtils.java, v 0.1 Exp $ 9 | */ 10 | public abstract class UUIDUtils { 11 | 12 | public static String getUUID() { 13 | return UUID.randomUUID().toString().replace("-",""); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /lit-support/src/main/java/com/github/lit/support/util/bean/BeanUtils.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.support.util.bean; 2 | 3 | import com.github.lit.support.util.ClassUtils; 4 | 5 | import java.beans.PropertyDescriptor; 6 | import java.lang.reflect.Method; 7 | import java.lang.reflect.Modifier; 8 | import java.util.ArrayList; 9 | import java.util.Arrays; 10 | import java.util.Collections; 11 | import java.util.LinkedHashMap; 12 | import java.util.List; 13 | import java.util.Map; 14 | import java.util.Objects; 15 | import java.util.function.BiConsumer; 16 | 17 | /** 18 | * @author liulu 19 | * @version v1.0 20 | * @see org.springframework.beans.BeanUtils 21 | * date 2018-12-06 22:18 22 | */ 23 | public abstract class BeanUtils { 24 | 25 | private BeanUtils() {} 26 | 27 | /** 28 | * 判断classpath下是否存在spring-beans依赖 29 | */ 30 | private static final boolean SPRING_PRESENT = ClassUtils.isPresent("org.springframework.beans.BeanUtils"); 31 | 32 | public static Map beanToMap(E bean) { 33 | Objects.requireNonNull(bean, "to map bean can not be null!"); 34 | PropertyDescriptor[] propertyDescriptors = getPropertyDescriptors(bean.getClass()); 35 | 36 | Map result = new LinkedHashMap<>(propertyDescriptors.length); 37 | 38 | for (PropertyDescriptor propertyDescriptor : propertyDescriptors) { 39 | if (propertyDescriptor.getReadMethod() != null) { 40 | Object value = ClassUtils.invokeMethod(propertyDescriptor.getReadMethod(), bean); 41 | result.put(propertyDescriptor.getName(), value); 42 | } 43 | } 44 | return result; 45 | } 46 | 47 | 48 | public static T convert(S source, T target) { 49 | return convert(source, target, ""); 50 | } 51 | 52 | /** 53 | * 参考spring属性拷贝, 拓展: 相同属性source的null值不会拷贝到target 54 | * 55 | * @param source source 56 | * @param target target 57 | * @param ignoreProperties ignoreProperties 58 | * @param S 59 | * @param T 60 | * @return target 61 | * @see org.springframework.beans.BeanUtils#copyProperties(Object, Object, Class, String...) 62 | */ 63 | public static T convert(S source, T target, String... ignoreProperties) { 64 | 65 | if (target == null || source == null) { 66 | return target; 67 | } 68 | PropertyDescriptor[] targetPds = getPropertyDescriptors(target.getClass()); 69 | 70 | List ignoreList = (ignoreProperties != null ? Arrays.asList(ignoreProperties) : null); 71 | 72 | for (PropertyDescriptor targetPd : targetPds) { 73 | Method writeMethod = targetPd.getWriteMethod(); 74 | if (writeMethod != null && (ignoreList == null || !ignoreList.contains(targetPd.getName()))) { 75 | PropertyDescriptor sourcePd = getPropertyDescriptor(source.getClass(), targetPd.getName()); 76 | if (sourcePd != null) { 77 | Method readMethod = sourcePd.getReadMethod(); 78 | if (readMethod != null && 79 | ClassUtils.isAssignable(writeMethod.getParameterTypes()[0], readMethod.getReturnType())) { 80 | try { 81 | if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) { 82 | readMethod.setAccessible(true); 83 | } 84 | Object value = readMethod.invoke(source); 85 | if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) { 86 | writeMethod.setAccessible(true); 87 | } 88 | if (value != null) { 89 | writeMethod.invoke(target, value); 90 | } 91 | } catch (Exception ex) { 92 | throw new IllegalArgumentException( 93 | "Could not copy property '" + targetPd.getName() + "' from source to target", ex); 94 | } 95 | } 96 | } 97 | } 98 | } 99 | return target; 100 | } 101 | 102 | public static List convertList(Class tClass, List sList) { 103 | return convertList(tClass, sList, (BiConsumer) null, ""); 104 | } 105 | 106 | public static List convertList(Class tClass, List sList, String... ignoreProperties) { 107 | return convertList(tClass, sList, null, ignoreProperties); 108 | } 109 | 110 | public static List convertList(Class tClass, List sList, BiConsumer biConsumer) { 111 | return convertList(tClass, sList, biConsumer, ""); 112 | } 113 | 114 | /** 115 | * @param tClass tClass 116 | * @param sList sList 117 | * @param biConsumer biConsumer 118 | * @param ignoreProperties ignoreProperties 119 | * @param S 120 | * @param T 121 | * @return LIST T 122 | */ 123 | public static List convertList(Class tClass, List sList, BiConsumer biConsumer, String... ignoreProperties) { 124 | if (sList == null || sList.isEmpty()) { 125 | return Collections.emptyList(); 126 | } 127 | // 返回的list列表 128 | List resultList = new ArrayList<>(sList.size()); 129 | 130 | // 循环调用转换单个对象 131 | for (S source : sList) { 132 | T target = ClassUtils.newInstance(tClass); 133 | resultList.add(convert(source, target, ignoreProperties)); 134 | if (biConsumer != null) { 135 | biConsumer.accept(source, target); 136 | } 137 | } 138 | return resultList; 139 | } 140 | 141 | 142 | /** 143 | * 返回JavaBean所有属性的PropertyDescriptor 144 | * 145 | * @param beanClass the other class 146 | * @return the property descriptor [] 147 | */ 148 | public static PropertyDescriptor[] getPropertyDescriptors(Class beanClass) { 149 | return SPRING_PRESENT ? org.springframework.beans.BeanUtils.getPropertyDescriptors(beanClass) 150 | : IntrospectionCache.forClass(beanClass).getPropertyDescriptors(); 151 | } 152 | 153 | /** 154 | * 返回JavaBean给定JavaBean给定属性的 PropertyDescriptors 155 | * 156 | * @param beanClass the other class 157 | * @param property the name of the property 158 | * @return the corresponding PropertyDescriptor, or null if none 159 | */ 160 | public static PropertyDescriptor getPropertyDescriptor(Class beanClass, String property) { 161 | return SPRING_PRESENT ? org.springframework.beans.BeanUtils.getPropertyDescriptor(beanClass, property) 162 | : IntrospectionCache.forClass(beanClass).getPropertyDescriptor(property); 163 | } 164 | 165 | 166 | } 167 | -------------------------------------------------------------------------------- /lit-support/src/main/java/com/github/lit/support/util/bean/IntrospectionCache.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.support.util.bean; 2 | 3 | import com.github.lit.support.exception.SysException; 4 | 5 | import java.beans.BeanInfo; 6 | import java.beans.IntrospectionException; 7 | import java.beans.Introspector; 8 | import java.beans.PropertyDescriptor; 9 | import java.lang.ref.Reference; 10 | import java.util.Collections; 11 | import java.util.LinkedHashMap; 12 | import java.util.Map; 13 | import java.util.WeakHashMap; 14 | 15 | /** 16 | * JavaBean信息缓存 17 | * User : liulu 18 | * Date : 2016-10-6 9:51 19 | */ 20 | public class IntrospectionCache { 21 | 22 | /** 23 | * Map keyed by class containing IntrospectionCache. 24 | * Needs to be a WeakHashMap with WeakReferences as values to allow 25 | * for proper garbage collection in case of multiple class loaders. 26 | */ 27 | private static final Map, Object> classCache = Collections.synchronizedMap(new WeakHashMap<>()); 28 | 29 | /** 30 | * 类的属性信息,key为属性名 31 | */ 32 | private final Map propertyDescriptorCache; 33 | 34 | /** 35 | * Instantiates a new Introspection cache. 36 | * 37 | * @param beanClass the other class 38 | */ 39 | private IntrospectionCache(Class beanClass) { 40 | 41 | try { 42 | final BeanInfo beanInfo = Introspector.getBeanInfo(beanClass); 43 | 44 | // 从Introspector缓存立即移除类,在类加载终止时允许适当的垃圾收集 45 | // 我们不管如何总是缓存在这里,这是一个GC友好的方式,对比于IntrospectionCache, 46 | // Introspector没有使用弱引用作为WeakHashMap的值 47 | Class classToFlush = beanClass; 48 | while (classToFlush != null) { 49 | Introspector.flushFromCaches(classToFlush); 50 | classToFlush = classToFlush.getSuperclass(); 51 | } 52 | this.propertyDescriptorCache = new LinkedHashMap<>(); 53 | 54 | // This call is slow so we do it once. 55 | PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors(); 56 | 57 | for (PropertyDescriptor pd : pds) { 58 | if (Class.class.equals(beanClass) && "classLoader".equals(pd.getName()) 59 | || "protectionDomain".equals(pd.getName())) { 60 | // Ignore Class.getClassLoader() and getProtectionDomain() methods - nobody needs to bind to those 61 | continue; 62 | } 63 | this.propertyDescriptorCache.put(pd.getName(), pd); 64 | } 65 | } catch (IntrospectionException ex) { 66 | throw new SysException("初始化缓存bean信息时出现异常", ex); 67 | } 68 | } 69 | 70 | /** 71 | * For class. 72 | * 73 | * @param beanClass the other class 74 | * @return the introspection cache 75 | */ 76 | public static IntrospectionCache forClass(Class beanClass) { 77 | 78 | IntrospectionCache introspectionCache; 79 | Object value = classCache.get(beanClass); 80 | 81 | if (value == null) { 82 | introspectionCache = new IntrospectionCache(beanClass); 83 | classCache.put(beanClass, introspectionCache); 84 | return introspectionCache; 85 | } 86 | 87 | if (value instanceof Reference) { 88 | @SuppressWarnings("rawtypes") 89 | Reference ref = (Reference) value; 90 | return (IntrospectionCache) ref.get(); 91 | } 92 | 93 | return (IntrospectionCache) value; 94 | } 95 | 96 | /** 97 | * Get property descriptors. 98 | * 99 | * @return the property descriptor [ ] 100 | */ 101 | public PropertyDescriptor[] getPropertyDescriptors() { 102 | PropertyDescriptor[] pds = new PropertyDescriptor[this.propertyDescriptorCache.size()]; 103 | int i = 0; 104 | for (PropertyDescriptor pd : this.propertyDescriptorCache.values()) { 105 | pds[i] = pd; 106 | i++; 107 | } 108 | return pds; 109 | } 110 | 111 | /** 112 | * Get property descriptor. 113 | * 114 | * @param name the name 115 | * @return the property descriptor 116 | */ 117 | public PropertyDescriptor getPropertyDescriptor(String name) { 118 | 119 | PropertyDescriptor pd = this.propertyDescriptorCache.get(name); 120 | 121 | if (pd == null && name != null) { 122 | // Same lenient fallback checking as in PropertyTypeDescriptor... 123 | pd = this.propertyDescriptorCache.get(name.substring(0, 1).toLowerCase() + name.substring(1)); 124 | if (pd == null) { 125 | pd = this.propertyDescriptorCache.get(name.substring(0, 1).toUpperCase() + name.substring(1)); 126 | } 127 | } 128 | return pd; 129 | } 130 | 131 | } 132 | -------------------------------------------------------------------------------- /lit-support/src/main/java/com/github/lit/support/util/lamabda/SerializedFunction.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.support.util.lamabda; 2 | 3 | import java.io.Serializable; 4 | import java.util.function.Function; 5 | 6 | /** 7 | * Serialize 8 | * @author liulu 9 | * @version v1.0 10 | * date 2018-12-11 19:42 11 | */ 12 | public interface SerializedFunction extends Function, Serializable { 13 | } 14 | -------------------------------------------------------------------------------- /lit-support/src/main/java/com/github/lit/support/util/lamabda/SerializedLambdaUtils.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.support.util.lamabda; 2 | 3 | import com.github.lit.support.util.ClassUtils; 4 | import com.github.lit.support.util.NameUtils; 5 | 6 | import java.lang.invoke.SerializedLambda; 7 | import java.lang.reflect.Method; 8 | 9 | /** 10 | * @author liulu 11 | * @version : v1.0 12 | * date : 2018/7/15 20:35 13 | */ 14 | public abstract class SerializedLambdaUtils { 15 | 16 | private SerializedLambdaUtils() { 17 | } 18 | 19 | public static String getProperty(SerializedFunction propertyFunction) { 20 | String getMethod = getSerializedLambda(propertyFunction).getImplMethodName(); 21 | 22 | if (getMethod.startsWith("get")) { 23 | return NameUtils.getFirstLowerName(getMethod.substring(3)); 24 | } 25 | if (getMethod.startsWith("is")) { 26 | return NameUtils.getFirstLowerName(getMethod.substring(2)); 27 | } 28 | return NameUtils.getFirstLowerName(getMethod); 29 | } 30 | 31 | @SuppressWarnings("unchecked") 32 | public static Class getLambdaClass(SerializedFunction propertyFunction) { 33 | SerializedLambda serializedLambda = getSerializedLambda(propertyFunction); 34 | String className = ClassUtils.convertResourcePathToClassName(serializedLambda.getImplClass()); 35 | return (Class) ClassUtils.forName(className); 36 | } 37 | 38 | public static SerializedLambda getSerializedLambda(SerializedFunction propertyFunction) { 39 | try { 40 | Method writeReplace = propertyFunction.getClass().getDeclaredMethod("writeReplace"); 41 | writeReplace.setAccessible(Boolean.TRUE); 42 | return (SerializedLambda) writeReplace.invoke(propertyFunction); 43 | } catch (Exception e) { 44 | throw new UnsupportedOperationException(e); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /lit-support/src/main/java/com/github/lit/support/util/secret/EncryptUtils.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.support.util.secret; 2 | 3 | import java.math.BigInteger; 4 | import java.security.MessageDigest; 5 | import java.security.NoSuchAlgorithmException; 6 | import java.security.SecureRandom; 7 | import java.util.regex.Pattern; 8 | 9 | /** 10 | * User : liulu 11 | * Date : 2017/10/22 17:08 12 | * version $Id: EncryptUtils.java, v 0.1 Exp $ 13 | */ 14 | public abstract class EncryptUtils { 15 | 16 | public static final String KEY_SHA = "SHA"; 17 | public static final String KEY_MD5 = "MD5"; 18 | 19 | private static Pattern BCRYPT_PATTERN = Pattern 20 | .compile("\\A\\$2a?\\$\\d\\d\\$[./0-9A-Za-z]{53}"); 21 | 22 | 23 | public static String md5(String data){ 24 | 25 | MessageDigest md5 = null; 26 | try { 27 | md5 = MessageDigest.getInstance(KEY_MD5); 28 | } catch (NoSuchAlgorithmException e) { 29 | throw new RuntimeException("加密失败 !", e); 30 | } 31 | 32 | md5.update(data.getBytes()); 33 | 34 | return new BigInteger(1, md5.digest()).toString(16); 35 | } 36 | 37 | public static String encodeBCrypt(CharSequence rawPassword) { 38 | return encodeBCrypt(rawPassword, -1, null); 39 | } 40 | 41 | public static String encodeBCrypt(CharSequence rawPassword, int strength) { 42 | return encodeBCrypt(rawPassword, strength, null); 43 | } 44 | 45 | 46 | public static String encodeBCrypt(CharSequence rawPassword, int strength, SecureRandom random) { 47 | String salt; 48 | if (strength > 0) { 49 | if (random != null) { 50 | salt = BCrypt.gensalt(strength, random); 51 | } 52 | else { 53 | salt = BCrypt.gensalt(strength); 54 | } 55 | } 56 | else { 57 | salt = BCrypt.gensalt(); 58 | } 59 | return BCrypt.hashpw(rawPassword.toString(), salt); 60 | } 61 | 62 | public static boolean matchesBCrypt(CharSequence rawPassword, String encodedPassword) { 63 | if (encodedPassword == null || encodedPassword.length() == 0) { 64 | return false; 65 | } 66 | 67 | if (!BCRYPT_PATTERN.matcher(encodedPassword).matches()) { 68 | return false; 69 | } 70 | 71 | return BCrypt.checkpw(rawPassword.toString(), encodedPassword); 72 | } 73 | 74 | 75 | } 76 | -------------------------------------------------------------------------------- /lit-support/src/test/java/com/github/lit/support/configure/SpringTestConfigure.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.support.configure; 2 | 3 | import ch.vorburger.exec.ManagedProcessException; 4 | import ch.vorburger.mariadb4j.DB; 5 | import com.github.lit.support.data.jdbc.EnableJdbcSupport; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.context.annotation.Configuration; 8 | import org.springframework.core.Ordered; 9 | import org.springframework.core.annotation.Order; 10 | import org.springframework.jdbc.datasource.DataSourceTransactionManager; 11 | import org.springframework.jdbc.datasource.SingleConnectionDataSource; 12 | import org.springframework.transaction.PlatformTransactionManager; 13 | 14 | import javax.sql.DataSource; 15 | 16 | /** 17 | * @author liulu 18 | * @version v1.0 19 | * date 2018-12-14 21:04 20 | */ 21 | @Configuration 22 | @EnableJdbcSupport 23 | public class SpringTestConfigure { 24 | 25 | 26 | 27 | @Bean 28 | @Order(Ordered.HIGHEST_PRECEDENCE + 1) 29 | public DB initDb() throws ManagedProcessException { 30 | DB db = DB.newEmbeddedDB(3306); 31 | db.start(); 32 | return db; 33 | } 34 | 35 | @Bean 36 | public DataSource dataSource() { 37 | 38 | SingleConnectionDataSource dataSource = new SingleConnectionDataSource(); 39 | dataSource.setDriverClassName("com.mysql.jdbc.Driver"); 40 | dataSource.setUrl("jdbc:mysql://localhost:3306"); 41 | dataSource.setUsername("root"); 42 | dataSource.setPassword(""); 43 | 44 | return dataSource; 45 | } 46 | 47 | @Bean 48 | public PlatformTransactionManager transactionManager(DataSource dataSource) { 49 | return new DataSourceTransactionManager(dataSource); 50 | } 51 | 52 | // @Bean 53 | // public NamedParameterJdbcOperations namedParameterJdbcOperations(DataSource dataSource) { 54 | // return new NamedParameterJdbcTemplate(dataSource); 55 | // } 56 | 57 | // @Bean 58 | // public JdbcRepository jdbcRepository(NamedParameterJdbcOperations jdbcOperations) { 59 | // return new JdbcRepositoryImpl(jdbcOperations); 60 | // } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /lit-support/src/test/java/com/github/lit/support/jdbc/JdbcRepositoryTest.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.support.jdbc; 2 | 3 | import com.github.lit.support.configure.SpringTestConfigure; 4 | import com.github.lit.support.data.SQL; 5 | import com.github.lit.support.data.domain.Page; 6 | import com.github.lit.support.data.domain.PageInfo; 7 | import com.github.lit.support.data.domain.Sort; 8 | import com.github.lit.support.data.domain.TableMetaDate; 9 | import com.github.lit.support.data.jdbc.JdbcRepository; 10 | import com.github.lit.support.model.ProductCondition; 11 | import com.github.lit.support.model.SignProduct; 12 | import org.junit.Assert; 13 | import org.junit.Test; 14 | import org.junit.runner.RunWith; 15 | import org.springframework.dao.DataIntegrityViolationException; 16 | import org.springframework.test.context.ContextConfiguration; 17 | import org.springframework.test.context.jdbc.Sql; 18 | import org.springframework.test.context.junit4.SpringRunner; 19 | import org.springframework.util.StringUtils; 20 | 21 | import javax.annotation.Resource; 22 | import java.util.Arrays; 23 | import java.util.Collections; 24 | import java.util.List; 25 | import java.util.Objects; 26 | import java.util.stream.Collectors; 27 | import java.util.stream.Stream; 28 | 29 | /** 30 | * @author liulu 31 | * @version v1.0 32 | * date 2018-12-11 21:37 33 | */ 34 | @RunWith(SpringRunner.class) 35 | @ContextConfiguration(classes = SpringTestConfigure.class) 36 | @Sql(scripts = "/sql/init_schema.sql") 37 | public class JdbcRepositoryTest { 38 | 39 | @Resource 40 | private JdbcRepository jdbcRepository; 41 | 42 | @Test 43 | public void insert() { 44 | SignProduct signProduct = new SignProduct(); 45 | signProduct.setCode("826478"); 46 | signProduct.setFullName("签约产品一号"); 47 | signProduct.setInventory(826); 48 | jdbcRepository.insert(signProduct); 49 | 50 | Assert.assertTrue(signProduct.getId() >= 1); 51 | } 52 | 53 | @Test 54 | public void batchInsert() { 55 | 56 | List productList = Stream.of("123", "456", "789", "012", "345") 57 | .map(s -> { 58 | SignProduct signProduct = new SignProduct(); 59 | signProduct.setCode(s); 60 | return signProduct; 61 | }).collect(Collectors.toList()); 62 | int insert = jdbcRepository.batchInsert(productList); 63 | 64 | Assert.assertEquals(productList.size(), insert); 65 | } 66 | 67 | @Test(expected = DataIntegrityViolationException.class) 68 | public void update() { 69 | String upCode = "new_code"; 70 | String upName = "new_full_name"; 71 | 72 | SignProduct old = jdbcRepository.selectById(SignProduct.class, 1L); 73 | Assert.assertNotNull(old); 74 | Assert.assertNotEquals(old.getCode(), upCode); 75 | Assert.assertNotEquals(old.getFullName(), upName); 76 | 77 | SignProduct upProduct = new SignProduct(); 78 | upProduct.setId(old.getId()); 79 | upProduct.setCode(upCode); 80 | upProduct.setFullName(upName); 81 | jdbcRepository.update(upProduct); 82 | 83 | } 84 | 85 | @Test 86 | public void updateSelective() { 87 | String upCode = "new_code"; 88 | String upName = "new_full_name"; 89 | 90 | SignProduct old = jdbcRepository.selectById(SignProduct.class, 1L); 91 | Assert.assertNotNull(old); 92 | Assert.assertNotEquals(old.getCode(), upCode); 93 | Assert.assertNotEquals(old.getFullName(), upName); 94 | 95 | SignProduct upProduct = new SignProduct(); 96 | upProduct.setId(old.getId()); 97 | upProduct.setCode(upCode); 98 | upProduct.setFullName(upName); 99 | jdbcRepository.updateSelective(upProduct); 100 | 101 | SignProduct newProduct = jdbcRepository.selectById(SignProduct.class, 1L); 102 | Assert.assertNotNull(newProduct); 103 | Assert.assertEquals(newProduct.getCode(), upCode); 104 | Assert.assertEquals(newProduct.getFullName(), upName); 105 | } 106 | 107 | @Test 108 | public void delete() { 109 | SignProduct deleteProduct = new SignProduct(); 110 | deleteProduct.setId(1L); 111 | int deleted = jdbcRepository.delete(deleteProduct); 112 | Assert.assertTrue(deleted >= 1); 113 | 114 | SignProduct signProduct = jdbcRepository.selectById(SignProduct.class, 1L); 115 | Assert.assertNull(signProduct); 116 | } 117 | 118 | @Test 119 | public void deleteById() { 120 | int deleted = jdbcRepository.deleteById(SignProduct.class, 1L); 121 | Assert.assertEquals(1, deleted); 122 | 123 | SignProduct signProduct = jdbcRepository.selectById(SignProduct.class, 1L); 124 | Assert.assertNull(signProduct); 125 | } 126 | 127 | @Test 128 | public void deleteByIds() { 129 | int deleted = jdbcRepository.deleteByIds(SignProduct.class, Arrays.asList(1L, 2L)); 130 | Assert.assertEquals(2, deleted); 131 | 132 | SignProduct signProduct = jdbcRepository.selectById(SignProduct.class, 1L); 133 | Assert.assertNull(signProduct); 134 | 135 | signProduct = jdbcRepository.selectById(SignProduct.class, 2L); 136 | Assert.assertNull(signProduct); 137 | } 138 | 139 | 140 | @Test 141 | public void selectById() { 142 | SignProduct signProduct = jdbcRepository.selectById(SignProduct.class, 1L); 143 | Assert.assertNotNull(signProduct); 144 | } 145 | 146 | @Test 147 | public void selectByIds() { 148 | List signProducts = jdbcRepository.selectByIds(SignProduct.class, Arrays.asList(1L, 2L)); 149 | Assert.assertEquals(2, signProducts.size()); 150 | } 151 | 152 | 153 | @Test 154 | public void selectAll() { 155 | List signProducts = jdbcRepository.selectAll(SignProduct.class); 156 | TableMetaDate mataDate = TableMetaDate.forClass(SignProduct.class); 157 | SQL sql = SQL.init().SELECT("count(*)").FROM(mataDate.getTableName()); 158 | int count = jdbcRepository.selectForObject(sql, null, int.class); 159 | Assert.assertEquals(count, signProducts.size()); 160 | } 161 | 162 | @Test 163 | public void selectByProperty() { 164 | SignProduct signProduct = jdbcRepository.selectByProperty(SignProduct::getCode, "893341"); 165 | 166 | Assert.assertNotNull(signProduct); 167 | } 168 | 169 | @Test 170 | public void selectListByProperty() { 171 | List signProducts = jdbcRepository.selectListByProperty(SignProduct::getCode, "893341"); 172 | Assert.assertEquals(1, signProducts.size()); 173 | } 174 | 175 | @Test 176 | public void selectForObject() { 177 | TableMetaDate mataDate = TableMetaDate.forClass(SignProduct.class); 178 | SQL sql = SQL.init().SELECT("count(*)") 179 | .FROM(mataDate.getTableName()) 180 | .WHERE("code = :code"); 181 | int count = jdbcRepository.selectForObject(sql, Collections.singletonMap("code", "893341"), int.class); 182 | Assert.assertEquals(1, count); 183 | } 184 | 185 | @Test 186 | public void selectList() { 187 | 188 | ProductCondition condition = new ProductCondition(); 189 | List codes = Arrays.asList("893341", "213324", "123456"); 190 | condition.setCodes(codes); 191 | 192 | List signProducts = jdbcRepository.selectList(SignProduct.class, condition); 193 | signProducts.forEach(signProduct -> Assert.assertTrue(codes.contains(signProduct.getCode()))); 194 | 195 | condition.setFullName("%测试%"); 196 | signProducts = jdbcRepository.selectList(SignProduct.class, condition); 197 | signProducts.forEach(signProduct -> { 198 | Assert.assertTrue(codes.contains(signProduct.getCode())); 199 | Assert.assertTrue(signProduct.getFullName(). contains("测试")); 200 | }); 201 | } 202 | 203 | @Test 204 | public void selectListWithOrder() { 205 | 206 | ProductCondition condition = new ProductCondition(); 207 | Sort orderBy = Sort.init().asc(SignProduct::getCode).desc(SignProduct::getGmtCreate); 208 | List signProducts = jdbcRepository.selectListWithOrder(SignProduct.class, condition, orderBy); 209 | 210 | SignProduct last = null; 211 | for (SignProduct signProduct : signProducts) { 212 | if (last == null) { 213 | last = signProduct; 214 | continue; 215 | } 216 | Assert.assertTrue(last.getCode().compareTo(signProduct.getCode()) < 0); 217 | if (Objects.equals(last.getCode(), signProduct.getCode())) { 218 | Assert.assertTrue(last.getGmtCreate().compareTo(signProduct.getGmtCreate()) >= 0); 219 | } 220 | } 221 | } 222 | 223 | @Test 224 | public void selectForList() { 225 | TableMetaDate mataDate = TableMetaDate.forClass(SignProduct.class); 226 | SQL sql = SQL.init().SELECT(mataDate.getColumn(SignProduct::getCode)) 227 | .FROM(mataDate.getTableName()) 228 | .ORDER_BY(mataDate.getColumn(SignProduct::getCode) + " desc"); 229 | 230 | List codes = jdbcRepository.selectForList(sql, null, String.class); 231 | 232 | String last = ""; 233 | for (String code : codes) { 234 | if (StringUtils.hasText(last)) { 235 | Assert.assertTrue(last.compareTo(code) >= 0); 236 | } 237 | } 238 | } 239 | 240 | @Test 241 | public void selectPageList() { 242 | ProductCondition condition = new ProductCondition(); 243 | condition.setPageSize(2); 244 | Page signProducts = jdbcRepository.selectPageList(SignProduct.class, condition); 245 | PageInfo pageInfo = signProducts.getPageInfo(); 246 | Assert.assertEquals(2, pageInfo.getPageSize()); 247 | Assert.assertEquals(condition.getPageNum(), pageInfo.getPageNum()); 248 | Assert.assertTrue(pageInfo.getTotal() >= 2); 249 | Assert.assertEquals(2, signProducts.getData().size()); 250 | 251 | } 252 | 253 | @Test 254 | public void countByProperty() { 255 | int count = jdbcRepository.countByProperty(SignProduct::getCode, "123123"); 256 | Assert.assertEquals(0, count); 257 | } 258 | 259 | 260 | 261 | } 262 | -------------------------------------------------------------------------------- /lit-support/src/test/java/com/github/lit/support/model/Goods.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.support.model; 2 | 3 | import lombok.Data; 4 | 5 | import javax.persistence.Table; 6 | import java.io.Serializable; 7 | import java.util.Date; 8 | 9 | /** 10 | * User : liulu 11 | * Date : 2018/7/11 19:23 12 | * version $Id: Goods.java, v 0.1 Exp $ 13 | */ 14 | @Data 15 | @Table(name = "sign_product") 16 | public class Goods implements Serializable { 17 | 18 | private static final long serialVersionUID = -6305173237589282633L; 19 | 20 | private Long id; 21 | 22 | private String code; 23 | 24 | private String fullName; 25 | 26 | private Date beginTime; 27 | 28 | private Date endTime; 29 | 30 | private Date createdAt; 31 | 32 | } 33 | -------------------------------------------------------------------------------- /lit-support/src/test/java/com/github/lit/support/model/GoodsCondition.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.support.model; 2 | 3 | import com.github.lit.support.data.Condition; 4 | import com.github.lit.support.data.Logic; 5 | import lombok.Data; 6 | 7 | import java.io.Serializable; 8 | import java.util.List; 9 | 10 | /** 11 | * User : liulu 12 | * Date : 2018/7/11 19:55 13 | * version $Id: GoodsQo.java, v 0.1 Exp $ 14 | */ 15 | @Data 16 | public class GoodsCondition implements Serializable { 17 | 18 | private static final long serialVersionUID = -1113673119261537637L; 19 | 20 | private Long id; 21 | 22 | @Condition(logic = Logic.IN, property = "code") 23 | private List codes; 24 | 25 | private Double price; 26 | 27 | @Condition(logic = Logic.LIKE) 28 | private String fullName; 29 | 30 | private String code; 31 | 32 | } 33 | -------------------------------------------------------------------------------- /lit-support/src/test/java/com/github/lit/support/model/ProductCondition.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.support.model; 2 | 3 | import com.github.lit.support.data.Condition; 4 | import com.github.lit.support.data.Logic; 5 | import com.github.lit.support.data.domain.PageRequest; 6 | import lombok.Data; 7 | import lombok.EqualsAndHashCode; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * @author liulu 13 | * @version v1.0 14 | * date 2018-12-15 11:08 15 | */ 16 | @Data 17 | @EqualsAndHashCode(callSuper = true) 18 | public class ProductCondition extends PageRequest { 19 | 20 | private static final long serialVersionUID = 6026171247313182830L; 21 | 22 | private Long id; 23 | 24 | @Condition(logic = Logic.IN, property = "code") 25 | private List codes; 26 | 27 | private Double price; 28 | 29 | @Condition(logic = Logic.LIKE) 30 | private String fullName; 31 | 32 | private String code; 33 | } 34 | -------------------------------------------------------------------------------- /lit-support/src/test/java/com/github/lit/support/model/SignProduct.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.support.model; 2 | 3 | import lombok.Data; 4 | 5 | import javax.persistence.Table; 6 | import java.io.Serializable; 7 | import java.time.LocalDateTime; 8 | import java.util.Date; 9 | 10 | /** 11 | * @author liulu 12 | * @version v1.0 13 | * date 2018-12-14 21:36 14 | */ 15 | @Data 16 | @Table(name = "sign_product") 17 | public class SignProduct implements Serializable { 18 | 19 | private static final long serialVersionUID = -3445991382244565705L; 20 | 21 | private Long id; 22 | 23 | private String code; 24 | 25 | private String fullName; 26 | 27 | private Integer inventory; 28 | 29 | private LocalDateTime gmtCreate; 30 | 31 | private Date gmtUpdate; 32 | 33 | 34 | } 35 | -------------------------------------------------------------------------------- /lit-support/src/test/java/com/github/lit/support/mybatis/GoodsMapper.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.support.mybatis; 2 | 3 | import com.github.lit.support.data.mybatis.BaseMapper; 4 | import com.github.lit.support.model.Goods; 5 | import org.apache.ibatis.annotations.SelectProvider; 6 | import org.apache.ibatis.builder.annotation.ProviderContext; 7 | 8 | /** 9 | * User : liulu 10 | * Date : 2018/7/11 19:26 11 | * version $Id: GoodsMapper.java, v 0.1 Exp $ 12 | */ 13 | public interface GoodsMapper extends BaseMapper { 14 | 15 | 16 | @SelectProvider(type = GoodsSqlProvider.class, method = "findByCode") 17 | Goods findByCode(String code); 18 | 19 | @org.apache.ibatis.annotations.Select("select * from goods") 20 | Goods findBySql(String s); 21 | 22 | 23 | class GoodsSqlProvider { 24 | 25 | public String findByCode(ProviderContext providerContext) { 26 | // return "select " + baseColumns + " from goods where tenant_id = #{tenantId} and code = #{code}"; 27 | 28 | // Select select = new Select(Goods.class); 29 | // select.where("tenant_id = #{tenantId} and code = #{code}"); 30 | // return select.build(); 31 | return ""; 32 | } 33 | 34 | 35 | } 36 | 37 | 38 | } 39 | -------------------------------------------------------------------------------- /lit-support/src/test/java/com/github/lit/support/mybatis/MapperTest.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.support.mybatis; 2 | 3 | import com.github.lit.support.model.Goods; 4 | import com.github.lit.support.model.GoodsCondition; 5 | import org.apache.ibatis.session.SqlSession; 6 | import org.apache.ibatis.session.SqlSessionFactory; 7 | import org.junit.Before; 8 | import org.junit.Test; 9 | 10 | import java.util.Arrays; 11 | import java.util.Date; 12 | 13 | /** 14 | * User : liulu 15 | * Date : 2018/7/11 19:30 16 | * version $Id: MapperTest.java, v 0.1 Exp $ 17 | */ 18 | public class MapperTest { 19 | 20 | private GoodsMapper goodsMapper; 21 | 22 | @Before 23 | public void before() { 24 | SqlSessionFactory sessionFactory = MybatisConfig.getSessionFactory(); 25 | SqlSession sqlSession = sessionFactory.openSession(); 26 | goodsMapper = sqlSession.getMapper(GoodsMapper.class); 27 | } 28 | 29 | @Test 30 | public void test() throws Exception { 31 | Goods goods = new Goods(); 32 | goods.setId(4L); 33 | goods.setCode("123"); 34 | goods.setFullName("fullName"); 35 | // goods.setPrice(12.34); 36 | goods.setCreatedAt(new Date()); 37 | 38 | goodsMapper.insert(goods); 39 | 40 | } 41 | 42 | @Test 43 | public void test2() { 44 | try { 45 | goodsMapper.deleteById(1L); 46 | } catch (Exception e) { 47 | // e.printStackTrace(); 48 | } 49 | try { 50 | goodsMapper.selectById(1L); 51 | } catch (Exception e) { 52 | // e.printStackTrace(); 53 | } 54 | } 55 | 56 | @Test 57 | public void test3() { 58 | 59 | GoodsCondition condition = new GoodsCondition(); 60 | condition.setId(2L); 61 | condition.setCodes(Arrays.asList("12", "13")); 62 | condition.setFullName("2312312"); 63 | condition.setPrice(12.3); 64 | 65 | goodsMapper.selectList(condition); 66 | 67 | } 68 | 69 | @Test 70 | public void test4() { 71 | Goods goods = goodsMapper.selectByProperty(Goods::getCode, "2332"); 72 | } 73 | 74 | 75 | 76 | } 77 | -------------------------------------------------------------------------------- /lit-support/src/test/java/com/github/lit/support/mybatis/MybatisConfig.java: -------------------------------------------------------------------------------- 1 | package com.github.lit.support.mybatis; 2 | 3 | import com.github.lit.support.data.mybatis.ResultMapInterceptor; 4 | import org.apache.ibatis.datasource.pooled.PooledDataSource; 5 | import org.apache.ibatis.mapping.Environment; 6 | import org.apache.ibatis.session.Configuration; 7 | import org.apache.ibatis.session.SqlSessionFactory; 8 | import org.apache.ibatis.session.SqlSessionFactoryBuilder; 9 | import org.apache.ibatis.transaction.TransactionFactory; 10 | import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory; 11 | 12 | public class MybatisConfig { 13 | 14 | private static SqlSessionFactory sessionFactory; 15 | 16 | public static SqlSessionFactory getSessionFactory() { 17 | if (sessionFactory == null) { 18 | PooledDataSource dataSource = getDataSource(); 19 | TransactionFactory transactionFactory = new JdbcTransactionFactory(); 20 | Environment environment = new Environment("development", transactionFactory, dataSource); 21 | Configuration configuration = new Configuration(environment); 22 | configuration.addInterceptor(new ResultMapInterceptor()); 23 | 24 | configuration.addMapper(GoodsMapper.class); 25 | 26 | sessionFactory = new SqlSessionFactoryBuilder().build(configuration); 27 | } 28 | return sessionFactory; 29 | } 30 | 31 | private static PooledDataSource getDataSource() { 32 | PooledDataSource dataSource = new PooledDataSource(); 33 | dataSource.setDriver("com.mysql.jdbc.Driver"); 34 | dataSource.setUrl("jdbc:mysql://10.10.100.56:3306/qn_dev"); 35 | dataSource.setUsername("root"); 36 | dataSource.setPassword("123456"); 37 | return dataSource; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /lit-support/src/test/resources/sql/init_schema.sql: -------------------------------------------------------------------------------- 1 | CREATE DATABASE IF NOT EXISTS testdb ; 2 | USE testdb; 3 | 4 | DROP TABLE IF EXISTS sign_product; 5 | CREATE TABLE sign_product ( 6 | id BIGINT PRIMARY KEY NOT NULL AUTO_INCREMENT, 7 | code VARCHAR(32) DEFAULT '' NOT NULL, 8 | full_name VARCHAR(128) DEFAULT '' NOT NULL, 9 | inventory INT DEFAULT 0 NOT NULL, 10 | gmt_create TIMESTAMP DEFAULT current_timestamp, 11 | gmt_update TIMESTAMP DEFAULT current_timestamp 12 | ON UPDATE current_timestamp 13 | ) 14 | ENGINE = InnoDB 15 | DEFAULT CHARSET = utf8mb4; 16 | 17 | 18 | INSERT INTO sign_product (code, full_name, inventory) VALUES ('893341', '远见产品3号', 12); 19 | INSERT INTO sign_product (code, full_name, inventory) VALUES ('213324', '这是测试产品', 543); 20 | INSERT INTO sign_product (code, full_name, inventory) VALUES ('123873', '正式环境产品53', 76); 21 | INSERT INTO sign_product (code, full_name, inventory) VALUES ('678567', '招商银行限量', 9765); 22 | 23 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.github.liulus 8 | lit 9 | pom 10 | 2.5.0 11 | 12 | 13 | lit-code 14 | lit-support 15 | lit-starters 16 | 17 | 18 | 19 | 1.7.25 20 | 1.2.3 21 | 1.16.14 22 | 20.0 23 | 2.9.7 24 | 3.4.6 25 | 1.3.2 26 | 2.3.23 27 | 5.0.8.RELEASE 28 | 2.0.4.RELEASE 29 | 5.0.7.RELEASE 30 | 31 | 1.8 32 | 1.8 33 | UTF-8 34 | 35 | 36 | 37 | 38 | org.projectlombok 39 | lombok 40 | ${lombok.version} 41 | provided 42 | 43 | 44 | 45 | junit 46 | junit 47 | 4.13.1 48 | test 49 | 50 | 51 | 52 | 53 | 54 | aliyun 55 | https://maven.aliyun.com/repository/public 56 | 57 | 58 | aliyun_code 59 | http://code.aliyun.com/maven_/repository/raw/public 60 | 61 | 62 | 63 | 64 | aliyun 65 | https://maven.aliyun.com/repository/public 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | org.slf4j 74 | slf4j-api 75 | ${slf4j.version} 76 | 77 | 78 | mysql 79 | mysql-connector-java 80 | 8.0.28 81 | 82 | 83 | com.oracle 84 | ojdbc6 85 | 11.2.0.3 86 | 87 | 88 | c3p0 89 | c3p0 90 | 0.9.1.2 91 | 92 | 93 | com.alibaba 94 | druid 95 | 1.1.2 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | aliyun_code 104 | http://code.aliyun.com/maven_/repository/raw/public 105 | 106 | 107 | aliyun_code 108 | http://localhost:8081/nexus/content/repositories/thirdparty 109 | 110 | 111 | 112 | 113 | 114 | 115 | liu 116 | liu lu 117 | skary0812@yeah.net 118 | 119 | 120 | --------------------------------------------------------------------------------