最近用SpringBoot重构一个PHP项目,用JPA操作MySQL数据库,由于要维持原来的表结构,应用中就要把许多表转化为Java类。
一般的ORM框架可以很方便地把Java类映射为关系数据库表,但这里显然是它的逆过程,这个好像没有现成的工具和框架,难道要对着表一个字段一个字段地写?
要知道,数据库有几十张表,每张表都有很多字段,一个个写还真得花不少精力,而且手写还很容易出错。
最好的办法当然是用程序实现自动转换了,这里我们用SQL来实现这种转换。
SQL实现表转Java
基本思路就是根据表名查询出列名,用concat函数拼接修饰符得到Java对象属性列表:
select
concat(
'public ',
case
when data_type in ('varchar', 'char', 'text') then
'String'
when data_type in ('int', 'tinyint') then
'Integer'
when data_type in ('bigint') then
'Long'
when data_type in ('datetime') then
'Date'
when data_type in ('bit', 'boolean') then
'Boolean'
else
'类型不确定'
end,
' ',
column_name,
';'
) as java
from
information_schema. columns
where
table_name = "person";
运行结果就是转换好的Java对象属性了,直接复制到类中即可。
封装成 MySQL 存储过程
把上面SQL语句封装成存储过程,使用的时候更方便:
-- 以表名为输入参数,输出对应的java对象属性
create procedure sql2java (in t_name char(30))
begin
select
concat(
'public ',
case
when data_type in ('varchar', 'char', 'text') then
'String'
when data_type in ('int', 'tinyint') then
'Integer'
when data_type in ('bigint') then
'Long'
when data_type in ('datetime') then
'Date'
when data_type in ('bit', 'boolean') then
'Boolean'
else
'类型不确定'
end,
' ',
column_name,
';'
) as java
from
information_schema. columns
where
table_name = t_name;
end;
调用 MySQL 存储过程,直接传入表名即可:
call sql2java('person');
循环遍历所有表
数据库中有很多张表,如果我们不想一次次输入表名,通过循环遍历可以一次性得到所有结果。
具体做法是先查出数据库所有表名:
SELECT
table_name
FROM
information_schema. TABLES
WHERE
table_schema = 'db_name';
然后把结果集通过游标和while循环遍历所有表:
-- 打开游标
open cur;
while done do
-- 获取数据
fetch cur into t_name;
-- 直接调用之前的存储过程
call sql2java (t_name);
end
while;
-- 关闭游标
close cur;
最后把上面SQL语句封装成 sql2java_all 存储过程。
调用存储过程,可一次性输出所有表的Java类:
call sql2java_all;
此方法除了可以得到Java类,稍作修改也可以支持多语言,比如Python、PHP的类,C++、Golang 的结构体以及Protobuf 的DSL代码。