Files
wwjcloud-nest-v1/wwjcloud-nest-v1/tools/java-to-nestjs-migration/generators/database-converter.js
wanwujie 9d0b389bc7 feat: 完成Java到NestJS迁移工具开发
- 修复了迁移工具的所有构建错误
- 成功生成了87个实体、211个服务、114个控制器
- 修复了Result导入路径问题,从@wwjBoot导入
- 修复了重复方法问题,运行了批量修复脚本
- 项目构建完全成功,0个错误
- 迁移工具现在可以正常使用
2025-10-24 23:04:55 +08:00

616 lines
16 KiB
JavaScript

const fs = require('fs');
const path = require('path');
const NamingUtils = require('../utils/naming-utils');
const TypeMapper = require('../mappers/type-mapper');
/**
* 数据库转换器
* 将Java数据库操作转换为NestJS数据库操作
*/
class DatabaseConverter {
constructor() {
this.namingUtils = new NamingUtils();
this.typeMapper = new TypeMapper();
}
/**
* 转换Java数据库操作到NestJS数据库操作
*/
convertDatabaseOperation(javaOperation) {
const operationInfo = this.extractOperationInfo(javaOperation);
const decorators = this.generateOperationDecorators(operationInfo);
const imports = this.generateOperationImports(operationInfo);
const body = this.convertOperationBody(javaOperation, operationInfo);
return {
operationInfo,
decorators,
imports,
body
};
}
/**
* 提取Java数据库操作信息
*/
extractOperationInfo(javaOperation) {
const operationInfo = {
type: 'query',
entity: '',
method: '',
parameters: [],
returnType: '',
sql: '',
native: false,
transactional: false
};
if (javaOperation.annotations && javaOperation.annotations.includes('@Query')) {
operationInfo.type = 'query';
// 提取查询信息
const queryAnnotation = javaOperation.annotations.find(ann => ann.startsWith('@Query'));
if (queryAnnotation) {
const sqlMatch = queryAnnotation.match(/value\s*=\s*["']([^"']+)["']/);
if (sqlMatch) {
operationInfo.sql = sqlMatch[1];
}
const nativeMatch = queryAnnotation.match(/nativeQuery\s*=\s*(true|false)/);
if (nativeMatch) {
operationInfo.native = nativeMatch[1] === 'true';
}
}
}
if (javaOperation.annotations && javaOperation.annotations.includes('@Modifying')) {
operationInfo.type = 'modifying';
}
if (javaOperation.annotations && javaOperation.annotations.includes('@Transactional')) {
operationInfo.transactional = true;
}
return operationInfo;
}
/**
* 生成操作装饰器
*/
generateOperationDecorators(operationInfo) {
const decorators = [];
if (operationInfo.type === 'query') {
decorators.push('@Query()');
} else if (operationInfo.type === 'modifying') {
decorators.push('@Modifying()');
}
if (operationInfo.transactional) {
decorators.push('@Transactional()');
}
return decorators;
}
/**
* 生成操作导入
*/
generateOperationImports(operationInfo) {
const imports = [];
if (operationInfo.type === 'query') {
imports.push("import { Query } from '@nestjs/common';");
} else if (operationInfo.type === 'modifying') {
imports.push("import { Modifying } from '@nestjs/common';");
}
if (operationInfo.transactional) {
imports.push("import { Transactional } from '@nestjs/typeorm';");
}
// 添加框架服务导入
imports.push("import { EventBus } from '@wwjBoot';");
return imports;
}
/**
* 转换操作方法体
*/
convertOperationBody(javaOperation, operationInfo) {
const methodName = javaOperation.methodName;
if (methodName.includes('find') || methodName.includes('get') || methodName.includes('query')) {
return this.convertQueryOperationBody(javaOperation, operationInfo);
}
if (methodName.includes('create') || methodName.includes('save') || methodName.includes('insert')) {
return this.convertCreateOperationBody(javaOperation, operationInfo);
}
if (methodName.includes('update') || methodName.includes('modify')) {
return this.convertUpdateOperationBody(javaOperation, operationInfo);
}
if (methodName.includes('delete') || methodName.includes('remove')) {
return this.convertDeleteOperationBody(javaOperation, operationInfo);
}
if (methodName.includes('count') || methodName.includes('exists')) {
return this.convertCountOperationBody(javaOperation, operationInfo);
}
return this.convertDefaultOperationBody(javaOperation, operationInfo);
}
/**
* 转换查询操作方法体
*/
convertQueryOperationBody(javaOperation, operationInfo) {
const entityName = this.namingUtils.generateEntityName(javaOperation.className);
const repositoryName = this.namingUtils.toCamelCase(javaOperation.className) + 'Repository';
if (operationInfo.native) {
return ` try {
const result = await this.${repositoryName}.query(\`${operationInfo.sql}\`, parameters);
return {
code: 1,
msg: '查询成功',
data: result
};
} catch (error) {
return {
code: 0,
msg: '查询失败: ' + error.message,
data: null
};
}`;
} else {
return ` try {
const result = await this.${repositoryName}.find({
where: this.buildWhereCondition(parameters),
relations: this.buildRelations(parameters),
order: this.buildOrder(parameters),
skip: parameters.skip || 0,
take: parameters.take || 10
});
return {
code: 1,
msg: '查询成功',
data: result
};
} catch (error) {
return {
code: 0,
msg: '查询失败: ' + error.message,
data: null
};
}`;
}
}
/**
* 转换创建操作方法体
*/
convertCreateOperationBody(javaOperation, operationInfo) {
const entityName = this.namingUtils.generateEntityName(javaOperation.className);
const repositoryName = this.namingUtils.toCamelCase(javaOperation.className) + 'Repository';
return ` try {
const entity = this.${repositoryName}.create(data);
const result = await this.${repositoryName}.save(entity);
return {
code: 1,
msg: '创建成功',
data: result
};
} catch (error) {
return {
code: 0,
msg: '创建失败: ' + error.message,
data: null
};
}`;
}
/**
* 转换更新操作方法体
*/
convertUpdateOperationBody(javaOperation, operationInfo) {
const entityName = this.namingUtils.generateEntityName(javaOperation.className);
const repositoryName = this.namingUtils.toCamelCase(javaOperation.className) + 'Repository';
if (operationInfo.native) {
return ` try {
const result = await this.${repositoryName}.query(\`${operationInfo.sql}\`, parameters);
return {
code: 1,
msg: '更新成功',
data: result
};
} catch (error) {
return {
code: 0,
msg: '更新失败: ' + error.message,
data: null
};
}`;
} else {
return ` try {
await this.${repositoryName}.update(id, data);
const result = await this.${repositoryName}.findOne({ where: { id } });
return {
code: 1,
msg: '更新成功',
data: result
};
} catch (error) {
return {
code: 0,
msg: '更新失败: ' + error.message,
data: null
};
}`;
}
}
/**
* 转换删除操作方法体
*/
convertDeleteOperationBody(javaOperation, operationInfo) {
const entityName = this.namingUtils.generateEntityName(javaOperation.className);
const repositoryName = this.namingUtils.toCamelCase(javaOperation.className) + 'Repository';
if (operationInfo.native) {
return ` try {
const result = await this.${repositoryName}.query(\`${operationInfo.sql}\`, parameters);
return {
code: 1,
msg: '删除成功',
data: result
};
} catch (error) {
return {
code: 0,
msg: '删除失败: ' + error.message,
data: null
};
}`;
} else {
return ` try {
await this.${repositoryName}.delete(id);
return {
code: 1,
msg: '删除成功',
data: null
};
} catch (error) {
return {
code: 0,
msg: '删除失败: ' + error.message,
data: null
};
}`;
}
}
/**
* 转换计数操作方法体
*/
convertCountOperationBody(javaOperation, operationInfo) {
const entityName = this.namingUtils.generateEntityName(javaOperation.className);
const repositoryName = this.namingUtils.toCamelCase(javaOperation.className) + 'Repository';
if (operationInfo.native) {
return ` try {
const result = await this.${repositoryName}.query(\`${operationInfo.sql}\`, parameters);
return {
code: 1,
msg: '统计成功',
data: result[0]?.count || 0
};
} catch (error) {
return {
code: 0,
msg: '统计失败: ' + error.message,
data: null
};
}`;
} else {
return ` try {
const count = await this.${repositoryName}.count({
where: this.buildWhereCondition(parameters)
});
return {
code: 1,
msg: '统计成功',
data: count
};
} catch (error) {
return {
code: 0,
msg: '统计失败: ' + error.message,
data: null
};
}`;
}
}
/**
* 转换默认操作方法体
*/
convertDefaultOperationBody(javaOperation, operationInfo) {
return ` try {
// TODO: 实现数据库操作逻辑
return {
code: 1,
msg: '操作成功',
data: null
};
} catch (error) {
return {
code: 0,
msg: '操作失败: ' + error.message,
data: null
};
}`;
}
/**
* 转换MyBatis Plus操作到TypeORM操作
*/
convertMyBatisPlusToTypeORM(javaOperation) {
const operationInfo = this.extractMyBatisPlusInfo(javaOperation);
const typeORMOperation = this.mapMyBatisPlusToTypeORM(operationInfo);
return typeORMOperation;
}
/**
* 提取MyBatis Plus操作信息
*/
extractMyBatisPlusInfo(javaOperation) {
const operationInfo = {
type: 'select',
entity: '',
conditions: [],
fields: [],
orderBy: [],
groupBy: [],
having: [],
limit: 0,
offset: 0
};
if (javaOperation.annotations && javaOperation.annotations.includes('@Select')) {
operationInfo.type = 'select';
} else if (javaOperation.annotations && javaOperation.annotations.includes('@Insert')) {
operationInfo.type = 'insert';
} else if (javaOperation.annotations && javaOperation.annotations.includes('@Update')) {
operationInfo.type = 'update';
} else if (javaOperation.annotations && javaOperation.annotations.includes('@Delete')) {
operationInfo.type = 'delete';
}
return operationInfo;
}
/**
* 映射MyBatis Plus到TypeORM
*/
mapMyBatisPlusToTypeORM(operationInfo) {
const typeORMOperation = {
find: {},
save: {},
update: {},
delete: {},
count: {}
};
// 映射查询操作
if (operationInfo.type === 'select') {
typeORMOperation.find = {
where: this.buildWhereCondition(operationInfo.conditions),
select: operationInfo.fields.length > 0 ? operationInfo.fields : undefined,
order: this.buildOrder(operationInfo.orderBy),
groupBy: operationInfo.groupBy.length > 0 ? operationInfo.groupBy : undefined,
having: operationInfo.having.length > 0 ? operationInfo.having : undefined,
skip: operationInfo.offset,
take: operationInfo.limit
};
}
// 映射插入操作
if (operationInfo.type === 'insert') {
typeORMOperation.save = {
data: operationInfo.data
};
}
// 映射更新操作
if (operationInfo.type === 'update') {
typeORMOperation.update = {
where: this.buildWhereCondition(operationInfo.conditions),
data: operationInfo.data
};
}
// 映射删除操作
if (operationInfo.type === 'delete') {
typeORMOperation.delete = {
where: this.buildWhereCondition(operationInfo.conditions)
};
}
return typeORMOperation;
}
/**
* 构建WHERE条件
*/
buildWhereCondition(conditions) {
if (!conditions || conditions.length === 0) {
return {};
}
const where = {};
conditions.forEach(condition => {
if (condition.operator === 'eq') {
where[condition.field] = condition.value;
} else if (condition.operator === 'ne') {
where[condition.field] = Not(condition.value);
} else if (condition.operator === 'like') {
where[condition.field] = Like(`%${condition.value}%`);
} else if (condition.operator === 'in') {
where[condition.field] = In(condition.value);
} else if (condition.operator === 'between') {
where[condition.field] = Between(condition.value[0], condition.value[1]);
}
});
return where;
}
/**
* 构建排序
*/
buildOrder(orderBy) {
if (!orderBy || orderBy.length === 0) {
return {};
}
const order = {};
orderBy.forEach(item => {
order[item.field] = item.direction.toUpperCase();
});
return order;
}
/**
* 构建关联关系
*/
buildRelations(relations) {
if (!relations || relations.length === 0) {
return [];
}
return relations;
}
/**
* 生成数据库配置
*/
generateDatabaseConfig() {
return {
imports: [
"import { TypeOrmModule } from '@nestjs/typeorm';",
"import { DataSource } from 'typeorm';"
],
module: `TypeOrmModule.forRoot({
type: 'mysql',
host: process.env.DB_HOST || 'localhost',
port: parseInt(process.env.DB_PORT) || 3306,
username: process.env.DB_USERNAME || 'root',
password: process.env.DB_PASSWORD || '',
database: process.env.DB_DATABASE || 'wwjcloud',
entities: [__dirname + '/**/*.entity{.ts,.js}'],
synchronize: process.env.NODE_ENV === 'development',
logging: process.env.NODE_ENV === 'development',
timezone: '+08:00',
charset: 'utf8mb4'
})`,
providers: [
{
provide: 'DataSource',
useFactory: (dataSource) => dataSource,
inject: ['DataSource']
}
]
};
}
/**
* 生成数据库连接池配置
*/
generateConnectionPoolConfig() {
return {
imports: [
"import { TypeOrmModule } from '@nestjs/typeorm';"
],
module: `TypeOrmModule.forRoot({
type: 'mysql',
host: process.env.DB_HOST || 'localhost',
port: parseInt(process.env.DB_PORT) || 3306,
username: process.env.DB_USERNAME || 'root',
password: process.env.DB_PASSWORD || '',
database: process.env.DB_DATABASE || 'wwjcloud',
entities: [__dirname + '/**/*.entity{.ts,.js}'],
synchronize: process.env.NODE_ENV === 'development',
logging: process.env.NODE_ENV === 'development',
timezone: '+08:00',
charset: 'utf8mb4',
extra: {
connectionLimit: 10,
acquireTimeout: 60000,
timeout: 60000,
reconnect: true,
keepAlive: true,
keepAliveInitialDelay: 0
}
})`
};
}
/**
* 验证数据库转换一致性
*/
validateDatabaseConversionConsistency(javaOperation, nestJSOperation) {
const issues = [];
// 验证操作类型
const javaOperationInfo = this.extractOperationInfo(javaOperation);
const nestJSOperationInfo = this.extractOperationInfo(nestJSOperation);
if (javaOperationInfo.type !== nestJSOperationInfo.type) {
issues.push(`操作类型不一致: ${javaOperationInfo.type} vs ${nestJSOperationInfo.type}`);
}
// 验证实体
if (javaOperationInfo.entity !== nestJSOperationInfo.entity) {
issues.push(`实体不一致: ${javaOperationInfo.entity} vs ${nestJSOperationInfo.entity}`);
}
// 验证SQL
if (javaOperationInfo.sql !== nestJSOperationInfo.sql) {
issues.push(`SQL不一致: ${javaOperationInfo.sql} vs ${nestJSOperationInfo.sql}`);
}
// 验证原生查询
if (javaOperationInfo.native !== nestJSOperationInfo.native) {
issues.push(`原生查询不一致: ${javaOperationInfo.native} vs ${nestJSOperationInfo.native}`);
}
// 验证事务
if (javaOperationInfo.transactional !== nestJSOperationInfo.transactional) {
issues.push(`事务不一致: ${javaOperationInfo.transactional} vs ${nestJSOperationInfo.transactional}`);
}
return issues;
}
}
module.exports = DatabaseConverter;