mysql生成Java实体类
根据mysql建表语句,生成Java实体类,可选带swagger注解,自用的,可能只符合我目前项目的规范,各位使用要前核对看一下,代码我放下面了,自取哦。
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>MySQL转Java实体类工具</title> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> <style> * { box-sizing: border-box; margin: 0; padding: 0; } body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; line-height: 1.6; color: #333; background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%); min-height: 100vh; padding: 20px; } .container { max-width: 1200px; margin: 0 auto; } header { text-align: center; margin-bottom: 30px; padding: 20px; background: rgba(255, 255, 255, 0.9); border-radius: 10px; box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1); } header h1 { color: #2c3e50; margin-bottom: 10px; font-size: 2.5rem; } header p { color: #7f8c8d; font-size: 1.1rem; } .controls { display: flex; flex-wrap: wrap; gap: 20px; margin-bottom: 25px; background: rgba(255, 255, 255, 0.9); padding: 20px; border-radius: 10px; box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1); } .control-group { flex: 1; min-width: 250px; } .control-group label { display: block; margin-bottom: 8px; font-weight: 600; color: #2c3e50; } .control-group input[type="text"] { width: 100%; padding: 12px 15px; border: 2px solid #ddd; border-radius: 6px; font-size: 16px; transition: border-color 0.3s; } .control-group input[type="text"]:focus { border-color: #3498db; outline: none; } .checkbox-group { display: flex; align-items: center; margin-top: 15px; } .checkbox-group input { margin-right: 10px; width: 18px; height: 18px; } button { background: #3498db; color: white; border: none; padding: 12px 25px; border-radius: 6px; cursor: pointer; font-size: 16px; font-weight: 600; transition: background 0.3s; margin-top: 10px; } button:hover { background: #2980b9; } .card-container { display: grid; grid-template-columns: 1fr 1fr; gap: 25px; margin-bottom: 30px; } @media (max-width: 900px) { .card-container { grid-template-columns: 1fr; } } .card { background: rgba(255, 255, 255, 0.95); border-radius: 10px; overflow: hidden; box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1); } .card-header { background: #2c3e50; color: white; padding: 15px 20px; } .card-header h2 { font-size: 1.4rem; } .card-body { padding: 20px; height: 400px; display: flex; flex-direction: column; } textarea { width: 100%; height: 100%; padding: 15px; border: 2px solid #ddd; border-radius: 6px; font-family: 'Courier New', Courier, monospace; font-size: 14px; resize: none; } pre { flex: 1; padding: 15px; border: 2px solid #ddd; border-radius: 6px; background: #f8f9fa; overflow: auto; font-family: 'Courier New', Courier, monospace; font-size: 14px; white-space: pre-wrap; } .copy { margin-top: 15px; align-self: flex-end; background: #27ae60; } .copy:hover { background: #219653; } .field-info { background: rgba(255, 255, 255, 0.9); border-radius: 10px; padding: 25px; margin-bottom: 30px; box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1); } .field-info h3 { margin-bottom: 20px; color: #2c3e50; font-size: 1.5rem; } .info-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 20px; } .info-item { background: #f8f9fa; padding: 15px; border-radius: 8px; border-left: 4px solid #3498db; } .info-item h4 { margin-bottom: 10px; color: #2c3e50; } footer { text-align: center; padding: 20px; color: #7f8c8d; background: rgba(255, 255, 255, 0.9); border-radius: 10px; box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1); } .fa-database, .fa-file-code, .fa-table, .fa-copy, .fa-bolt, .fa-folder, .fa-cube { margin-right: 8px; } .highlight { color: #e74c3c; font-weight: bold; } </style> </head> <body> <div class="container"> <header> <h1><i class="fas fa-database"></i> MySQL转Java实体类工具</h1> <p>将MySQL建表语句自动转换为Java实体类代码,支持Lombok、Swagger注解</p> </header> <div class="controls"> <div class="control-group"> <label for="packageName"><i class="fas fa-folder"></i> 包名 (Package Name)</label> <input type="text" id="packageName" value="cn.yiyuan.iot.model" placeholder="例如:com.example.model"> </div> <div class="control-group"> <label for="className"><i class="fas fa-cube"></i> 类名 (Class Name)</label> <input type="text" id="className" placeholder="自动从表名生成"> </div> <div class="control-group"> <div class="checkbox-group"> <input type="checkbox" id="addApiModelProperty" checked> <label for="addApiModelProperty">添加 @ApiModelProperty 注解</label> </div> <button id="generateBtn"><i class="fas fa-bolt"></i> 生成实体类</button> </div> </div> <div class="card-container"> <div class="card"> <div class="card-header"> <h2><i class="fas fa-table"></i> MySQL 建表语句</h2> </div> <div class="card-body"> <textarea id="sqlInput" placeholder="在此粘贴您的MySQL建表语句...">CREATE TABLE `course_category` ( `id` bigint NOT NULL, `user_name` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '创建用户名称', `user_id` bigint DEFAULT NULL COMMENT '创建用户id', `status` tinyint(1) DEFAULT '0' COMMENT '是否可用,0:可用,1:不可用', `create_time` datetime DEFAULT NULL COMMENT '创建时间', `update_time` datetime DEFAULT NULL COMMENT '修改时间', `name` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '分类名称', `sort` int DEFAULT '0' COMMENT '排序', `parent_id` bigint DEFAULT NULL COMMENT '上级分类id', PRIMARY KEY (`id`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='课程分类表';</textarea> </div> </div> <div class="card"> <div class="card-header"> <h2><i class="fas fa-file-code"></i> Java 实体类</h2> </div> <div class="card-body"> <pre id="javaOutput">// 输入建表语句后点击生成按钮</pre> <button class="copy" id="copyBtn"><i class="fas fa-copy"></i> 复制到剪贴板</button> </div> </div> </div> <div class="field-info"> <h3><i class="fas fa-lightbulb"></i> 使用说明</h3> <div class="info-grid"> <div class="info-item"> <h4>命名转换</h4> <p>表名/字段名自动转换为驼峰命名法(例如:user_name → userName)</p> </div> <div class="info-item"> <h4>类型映射</h4> <p>MySQL类型 → Java类型:<br>bigint → Long<br>varchar → String<br>datetime → Date</p> </div> <div class="info-item"> <h4>自动注解</h4> <p>主键自动添加 @Id 注解<br>所有字段添加 @ApiModelProperty</p> </div> <div class="info-item"> <h4>支持特性</h4> <p>表注释 → 类注释<br>字段注释 → 属性注释<br>支持Lombok @Data注解</p> </div> </div> </div> <footer> <p>© 2023 MySQL转Java实体类工具 | 开发者工具</p> </footer> </div> <script> document.addEventListener('DOMContentLoaded', function() { const sqlInput = document.getElementById('sqlInput'); const javaOutput = document.getElementById('javaOutput'); const generateBtn = document.getElementById('generateBtn'); const copyBtn = document.getElementById('copyBtn'); const packageNameInput = document.getElementById('packageName'); const classNameInput = document.getElementById('className'); const addApiModelPropertyCheckbox = document.getElementById('addApiModelProperty'); // 类型映射关系 const typeMap = { 'bigint': 'Long', 'int': 'Integer', 'tinyint': 'Integer', 'smallint': 'Integer', 'mediumint': 'Integer', 'integer': 'Integer', 'float': 'Float', 'double': 'Double', 'decimal': 'BigDecimal', 'numeric': 'BigDecimal', 'char': 'String', 'varchar': 'String', 'text': 'String', 'mediumtext': 'String', 'longtext': 'String', 'date': 'Date', 'datetime': 'Date', 'timestamp': 'Date', 'time': 'Date', 'boolean': 'Boolean', 'bit': 'Boolean', 'blob': 'byte[]' }; // 生成实体类 generateBtn.addEventListener('click', generateEntityClass); // 复制功能 copyBtn.addEventListener('click', copyToClipboard); // 自动提取表名 sqlInput.addEventListener('input', extractTableName); function generateEntityClass() { const sql = sqlInput.value.trim(); if (!sql) { javaOutput.textContent = '// 请输入MySQL建表语句'; return; } const packageName = packageNameInput.value.trim() || 'com.example.model'; let className = classNameInput.value.trim(); const addApiModelProperty = addApiModelPropertyCheckbox.checked; // 解析建表语句 const tableMatch = sql.match(/CREATE\s+TABLE\s+(?:IF\s+NOT\s+EXISTS\s+)?`?(\w+)`?/i); if (!tableMatch) { javaOutput.textContent = '// 无法识别建表语句,请检查格式'; return; } const tableName = tableMatch[1]; if (!className) { className = toCamelCase(tableName, true, true); } // 解析表注释 let tableComment = ''; const commentMatch = sql.match(/COMMENT\s*=\s*'([^']+)'/i); if (commentMatch) { tableComment = commentMatch[1]; } // 解析字段 const fieldRegex = /`(\w+)`\s+(\w+)(?:\((\d+|\d+,\d+|\d+\s+\w+)\))?\s*(?:unsigned\s+)?(?:CHARACTER\s+SET\s+\w+)?\s*(?:COLLATE\s+\w+)?\s*(NOT\s+NULL|NULL)?\s*(?:DEFAULT\s+([^\s,]+))?\s*(?:AUTO_INCREMENT)?\s*(?:ON\s+UPDATE\s+CURRENT_TIMESTAMP)?\s*(?:COMMENT\s+'(.*?)')?/gi; const lines = sql.split('\n'); let fieldMatch; const fields = []; const primaryKeys = []; // 查找主键 const pkMatch = sql.match(/PRIMARY\s+KEY\s*\(([^)]+)\)/i); if (pkMatch) { const pkFields = pkMatch[1].replace(/`/g, '').split(',').map(f => f.trim()); primaryKeys.push(...pkFields); } // 逐行解析字段(避免匹配到约束) for (const line of lines) { const trimmedLine = line.trim(); if (/^(CONSTRAINT|KEY|INDEX|UNIQUE|FOREIGN)/i.test(trimmedLine)) continue; fieldRegex.lastIndex = 0; // 每次重置 const match = fieldRegex.exec(trimmedLine); if (match) { const fieldName = match[1]; const sqlType = match[2].toLowerCase(); const defaultValue = match[5]; // 这里是默认值 let fieldComment = match[6] || ''; // 这里才是注释 if (fieldComment) { fieldComment = fieldComment.replace(/\\'/g, "'"); } const isRequired = /NOT NULL/i.test(trimmedLine); const javaType = typeMap[sqlType] || 'Object'; const javaFieldName = toCamelCase(fieldName, false, false); fields.push({ sqlName: fieldName, javaName: javaFieldName, sqlType, javaType, comment: fieldComment, isPrimary: primaryKeys.includes(fieldName), isRequired }); } } if (fields.length === 0) { javaOutput.textContent = '// 未找到有效字段定义\n// 原始SQL:\n' + sql; return; } // 生成实体类代码 let code = `package ${packageName};\n\n`; // 动态导入需要的类型 const imports = new Set(); imports.add('import javax.persistence.Id;'); imports.add('import javax.persistence.Table;'); imports.add('import lombok.Data;'); imports.add('import java.io.Serializable;'); // 检查是否需要导入Swagger if (addApiModelProperty) { imports.add('import io.swagger.annotations.ApiModel;'); imports.add('import io.swagger.annotations.ApiModelProperty;'); } // 检查需要导入的类型 fields.forEach(field => { if (field.javaType === 'Date') { imports.add('import java.util.Date;'); } else if (field.javaType === 'BigDecimal') { imports.add('import java.math.BigDecimal;'); } }); // 添加import语句 Array.from(imports).sort().forEach(imp => { code += imp + '\n'; }); code += '\n'; if (tableComment) { code += `/**\n * ${tableComment}\n */\n`; } // 添加类注解 code += `@Data\n`; code += `@Table(name = "${tableName}")\n`; if (addApiModelProperty) { code += `@ApiModel(value = "${className}", description = "${tableComment || className}")\n`; } code += `public class ${className} implements Serializable {\n\n`; // 添加字段 fields.forEach(field => { if (field.comment) { code += ` /**\n * ${field.comment}\n */\n`; } if (field.isPrimary) { code += ` @Id\n`; } if (addApiModelProperty) { const apiValue = field.comment ? field.comment : field.javaName; code += ` @ApiModelProperty(value = "${apiValue}", name = "${field.javaName}", example = "${getExampleValue(field.javaType)}", required = ${field.isRequired})\n`; } code += ` private ${field.javaType} ${field.javaName};\n\n`; }); code += `}`; javaOutput.textContent = code; } // 获取示例值 function getExampleValue(javaType) { switch(javaType) { case 'Long': return "1"; case 'Integer': return "1"; case 'String': return "example"; case 'Date': return "2023-01-01 12:00:00"; case 'BigDecimal': return "100.00"; case 'Boolean': return "true"; default: return ""; } } function toCamelCase(str, capitalizeFirst, isClassName) { let cleanedStr = str; if (isClassName) { cleanedStr = cleanedStr .replace(/^t_?b?_?/, '') .replace(/^table_?/, ''); } return cleanedStr.split('_') .map((word, index) => { if (index === 0 && !capitalizeFirst) { return word; } return word.charAt(0).toUpperCase() + word.slice(1); }) .join(''); } function extractTableName() { const sql = sqlInput.value.trim(); if (!classNameInput.value) { const tableMatch = sql.match(/CREATE\s+TABLE\s+(?:IF\s+NOT\s+EXISTS\s+)?`?(\w+)`?/i); if (tableMatch) { const tableName = tableMatch[1]; classNameInput.value = toCamelCase(tableName, true, true); } } } function copyToClipboard() { const text = javaOutput.innerText; navigator.clipboard.writeText(text) .then(() => { const originalText = copyBtn.innerHTML; copyBtn.innerHTML = '<i class="fas fa-check"></i> 已复制!'; setTimeout(() => { copyBtn.innerHTML = originalText; }, 2000); }) .catch(err => { console.error('复制失败:', err); alert('复制失败,请手动复制代码'); }); } // 页面加载时自动生成一次 setTimeout(generateEntityClass, 500); }); </script> </body> </html>