同样的配置,是让用户通过界面去勾选简单,还是敲一堆代码?
由于项目越来越多,又都是没什么技术含量的。为了写得更快,这次我顺便把controller层,service层也一并生成了。注解,注入一个都没少。
3.3版本对于文件位置做了一些优化。如下所示,base路径是com包的直接父级路径。
运行效果
import wx
from pymysql import connect as pyconnect
from os.path import exists as oexist
from os.path import join
from os import makedirs as omkdirs
class myFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self,None,-1,'逆向工程',size=(400,600))
self.panel = wx.Panel(self)
self.connect_view()
self.Center()
def to_file(self,content, path):# 写入文件
f = open(join(self.basePath,path), 'w', encoding='utf-8')
f.write(content)
f.close()
def get_field_list(self, table_list): # 从数据库中读取表结构信息
reflect_dict = {'tinyint': 'Integer', 'smallint': 'Integer', 'mediumint': 'Integer',
'int': 'Integer', 'bigint': 'Integer', 'float': 'Float', 'double': 'Double',
'decimal': 'Double', 'date': 'Date', 'time': 'Date',
'datetime': 'Date', 'timestamp': 'Date', 'char': 'String',
'varchar': 'String', 'tinytext': 'String', 'text': 'String',
'mediumtext': 'String', 'longtext': 'String'}
cursor = self.db_connection.cursor()
cursor.execute('desc ' + table_list)
field_list = []
for i in cursor.fetchall():
col_name = i[0]
col_type = i[1].split('(')[0]
field_name = self.sql_to_camel(col_name)
field_name = self.first_lower(field_name) # 再过滤一次,防止数据库字段以大写开头
field_type = reflect_dict[col_type]
field_list.append((field_type, field_name))
return field_list
def sql_to_camel(self,string): # 下划线形式命名转驼峰式命名
words = string.split('_')
name = words[0]
if len(words) > 1:
for i in words[1:]:
name += self.first_upper(i)
return name
def first_upper(self,string): # 字符串首字母大写
return string[0].upper() + string[1:]
def first_lower(self,string):
return string[0].lower() + string[1:]
def connect_view(self):# 连接数据库视图
self.label1 = wx.StaticText(self.panel,-1,'用户名:',(50,50))
self.username = wx.TextCtrl(self.panel,-1,'root',(160,50),(200,25))
self.label2 = wx.StaticText(self.panel, -1, '密码:',(50,100))
self.password = wx.TextCtrl(self.panel,-1,'root',(160,100),(200,25))
self.label3 = wx.StaticText(self.panel, -1, '数据库名:',(50,150))
self.db = wx.TextCtrl(self.panel, -1,'kh80',(160, 150),(200,25))
self.label4 = wx.StaticText(self.panel, -1, '实体包:', (50, 200))
self.pojo = wx.TextCtrl(self.panel, -1, 'com.shy.pojo', (160, 200),(200,25))
self.label5 = wx.StaticText(self.panel, -1, 'Mapper接口包:', (50, 250))
self.mapper = wx.TextCtrl(self.panel, -1, 'com.shy.mapper', (160, 250),(200,25))
self.label6 = wx.StaticText(self.panel, -1, 'Service接口包:', (50, 300))
self.service = wx.TextCtrl(self.panel, -1, 'com.shy.service', (160, 300), (200, 25))
self.label7 = wx.StaticText(self.panel,-1,'Service实现类包:',(30,350))
self.serviceImpl = wx.TextCtrl(self.panel,-1,'com.shy.service.impl',(160,350),(200,25))
self.label8 = wx.StaticText(self.panel, -1, 'Controller包:', (50, 400))
self.controller = wx.TextCtrl(self.panel, -1, 'com.shy.controller', (160, 400), (200, 25))
self.label9 = wx.StaticText(self.panel, -1, 'base路径:', (50, 450))
self.proPath = wx.TextCtrl(self.panel, -1,'', (160, 450), (200, 25))
self.next = wx.Button(self.panel, -1, '下一步', (150, 500))
self.next.Bind(wx.EVT_BUTTON, self.next_e)
def table_view(self):# 选取数据表视图
size = self.panel.GetSize()
self.panel.Destroy()
self.scroll = wx.ScrolledWindow(self,-1)
self.scroll.SetSize(size[0], size[1])
self.select_all_btn = wx.ToggleButton(self.scroll,-1,'全选',(50,10))
self.select_all_btn.Bind(wx.EVT_TOGGLEBUTTON,self.select_all_e)
self.next = wx.Button(self.scroll, -1, '创建', (150, 10))
self.next.Bind(wx.EVT_BUTTON,self.generate_e)
self.btn = wx.Button(self.scroll, -1, '清空类名', (250, 10))
self.btn.Bind(wx.EVT_BUTTON, self.clear_tc_e)
self.label2 = wx.StaticText(self.scroll, -1, '勾选数据表名', (50, 50))
self.label3 = wx.StaticText(self.scroll, -1, '输入类名', (250, 50))
cursor = self.db_connection.cursor()
cursor.execute('show tables')
data = cursor.fetchall()
self.tables = []
for i,j in enumerate(data):
class_name = self.first_upper(self.sql_to_camel(j[0]))
self.tables.append((wx.CheckBox(self.scroll , -1 , j[0] , (50,27*i+80)),
wx.TextCtrl(self.scroll, -1, class_name, (200, 27 * i + 75),(150,25))))
self.scroll.SetScrollbars(0, 1, 0, len(data)*27+120)
def clear_tc_e(self,e):
for i in self.tables:
i[1].SetValue('')
def create_dirs(self):# 建立文件夹
path_list = []
for i in self.packages:
path = join(self.basePath,i.replace('.','\\'))
if not oexist(path):
omkdirs(path)
path_list.append(path)
return path_list
def create_pojo(self,fields, class_name): # 创建java实体类
flag = False
for i in fields:
if i[0] == 'Date':
flag = True
break
class_str = 'package ' + self.packages[0] + ';\n\n'
if flag:
class_str += 'import java.util.Date;\n'
class_str += 'import org.springframework.stereotype.Component;\nimport java.io.Serializable;\n\n' \
'@Component\npublic class ' + class_name + ' implements Serializable {\n' # 类名
for i in fields:
class_str += '\tprivate ' + i[0] + ' ' + i[1] + ';\n' # 私有属性
class_str += '\n\tpublic ' + class_name + '('
for i in fields:
class_str += i[0] + ' ' + i[1] + ',' # 构造函数参数
class_str = class_str[:-1] + '){\n'
for i in fields:
class_str += '\t\tthis.' + i[1] + ' = ' + i[1] + ';\n' # 构造函数传参
class_str += '\t}\n\n\tpublic ' + class_name + '(){}\n\n' # 无参构造
for i in fields: # gettr和setter方法
class_str += '\tpublic ' + i[0] + ' get' + self.first_upper(i[1]) + '(){\n\t\treturn ' \
+ i[1] + ';\n\t}\n\n\tpublic void set' + self.first_upper(i[1]) + '(' + i[0] + \
' ' + i[1] + '){\n\t\tthis.' + i[1] + ' = ' + i[1] + ';\n\t}\n\n'
class_str += '\t@Override\n\tpublic String toString(){\n\t\treturn \"' + class_name + \
'{\" +\n'
to_string = ''
for i in fields: # toString方法
if i[0] == 'String':
to_string += '\t\t\t\", ' + str(i[1]) + '=\'\" + ' + str(i[1]) + ' + \'\\\'\' +\n'
else:
to_string += '\t\t\t\",' + str(i[1]) + '=\" + ' + str(i[1]) + ' +\n'
class_str += '\t\t\t\"' + to_string[5:] + '\t\t\t\'}\';\n\t}\n}'
file_name = self.packages[0].replace('.', '\\') + '\\' + class_name + '.java'
self.to_file(class_str, file_name)
def create_mapper_interface(self,class_name):# 创建mapper接口
class_str = 'package ' +self.packages[1] + ';\n\n'\
+'import org.springframework.stereotype.Repository;\n\n' \
+'@Repository\npublic interface ' + class_name + 'Mapper{\n\n}'
file_name = self.packages[1].replace('.', '\\') + '\\' + class_name + 'Mapper.java'
self.to_file(class_str, file_name)
def create_service_interface(self,class_name):
service_str = 'package ' + self.packages[2] + \
';\n\nimport org.springframework.stereotype.Component;\n' \
'\npublic interface ' \
+ class_name + 'Service{\n\n}'
file_name = self.packages[2].replace('.', '\\') + '\\' + class_name + 'Service.java'
self.to_file(service_str, file_name)
def create_service_impl(self,class_name):
service_str = 'package ' + self.packages[3] + ';\n\n'\
+'import ' + self.packages[1] + '.' + class_name + 'Mapper;\n'\
+'import ' + self.packages[2]+'.'+ class_name +'Service;\n'\
+'import org.springframework.beans.factory.annotation.Autowired;\n' \
+'import org.springframework.stereotype.Service;\n\n'\
+'@Service\n'\
+'public class '+ class_name + 'ServiceImpl implements '+class_name+'Service {\n'\
+'\t@Autowired\n'\
+'\tprivate ' + class_name + 'Mapper mapper;\n}'
file_name = self.packages[3].replace('.', '\\') + '\\' + class_name + 'ServiceImpl.java'
self.to_file(service_str, file_name)
def create_controller(self,controller_str):
file_name = self.packages[4].replace('.', '\\') + '\\' + 'CenterController.java'
self.to_file(controller_str, file_name)
def generate_e(self,e):# 生成相应文件事件
self.create_dirs() # 建立文件夹
class_names = []
controller_str = 'package '+self.packages[4] + ';\n\n'\
+'import org.springframework.web.bind.annotation.RestController;\n'
service_fields = ''
service_imports = ''
for i in self.tables:
if i[0].GetValue() == True:
class_name = i[1].GetValue() # 类名
field_list = self.get_field_list(i[0].GetLabel()) # 所有的属性值和类型
self.create_pojo(field_list,class_name)# 创建实体类
self.create_mapper_interface(class_name)# 创建接口
self.create_service_interface(class_name)# 创建service接口
self.create_service_impl(class_name)# 创建service实现类
service_imports += 'import '+self.packages[3]+'.'+class_name+'ServiceImpl;\n'
service_fields += '\t@\n\tprivate '+class_name+'ServiceImpl '+self.first_lower(class_name)+'Service;\n'
controller_str += service_imports+'\n@RestController\npublic class CenterController{\n'+service_fields+'\n}'
self.create_controller(controller_str)
self.db_connection.close() # 关闭数据库连接
wx.MessageBox('成功!')# 弹出提示信息
self.Destroy()
def select_all_e(self,e):# 全选和全不选功能切换事件
value = self.select_all_btn.GetValue()
if(value):
self.select_all_btn.SetLabel('全不选')
for i in self.tables:
i[0].SetValue(True)
else:
self.select_all_btn.SetLabel('全选')
for i in self.tables:
i[0].SetValue(False)
def next_e(self,e):# 读取表名并获取连接事件
self.db_connection = pyconnect('localhost',
self.username.GetValue(),
self.password.GetValue(),
self.db.GetValue())# 获取数据库连接对象
# 包名表
self.packages = [self.pojo.GetValue(), self.mapper.GetValue(), self.service.GetValue(),self.serviceImpl.GetValue(),self.controller.GetValue()]
# 工程所在的路径
self.basePath = self.proPath.GetValue()
# 销毁界面不需要用到的一些组件
self.label1.Destroy()
self.label2.Destroy()
self.label3.Destroy()
self.label4.Destroy()
self.label5.Destroy()
self.label6.Destroy()
self.label7.Destroy()
self.label8.Destroy()
self.label9.Destroy()
self.username.Destroy()
self.password.Destroy()
self.db.Destroy()
self.pojo.Destroy()
self.mapper.Destroy()
self.service.Destroy()
self.serviceImpl.Destroy()
self.controller.Destroy()
self.proPath.Destroy()
self.next.Destroy()
self.table_view()
if __name__=='__main__':
app = wx.App()
frame = myFrame()
frame.Show()
app.MainLoop()