hibernate h2变mysql_懒要懒到底,能自动的就不要手动,Hibernate正向工程完成Oracle数据库到MySql数据库转换(含字段转换、注释)...
需求描述需求是這樣的:因為我們目前的一個老項目是Oracle數據庫的,這個庫呢,數據庫是沒有注釋的,而且字段名和表名都是大寫風格,比如在代碼層面的po呢,以前也是沒有任何注釋的,但是經過這些年,大家慢慢踩坑多了,也給po加上了一些注釋了,比如:現狀就是這樣,再說說目標是:希望把這個庫能轉成mysql,表名和字段名最好都用下劃線分隔每個單詞,字段呢,最好能有注釋。也就是差不多下面這樣:方案分析最早我嘗試的就是hibernate正向工程,建一個空的mysql庫,然后配置hibernate的選項為:這樣的話呢,就會自動在我們指定的mysql數據庫生成表了,不過,有兩個瑕疵是:生成的表,字段和表名都是和PO里一樣的駝峰格式;沒有注釋。第一個問題,我這邊是通過覆蓋hibernate源碼的方式解決,將駝峰轉換為了下劃線;第二個問題,麻煩一些,因為要做到字段帶注釋的話,那就得看看哪里能拿到注釋。hibernate執行過程中,從PO類里?不可能,編譯好的class里,怎么會有注釋呢?那就只能從源文件著手了,PO類的源碼里,field上是有注釋的,那就必須要去解析PO類的java文件,從里面提取出每個PO類中:字段--》注釋的對應關系來。大方向已定,我們開搞!最后我這里解決這兩個問題,是覆蓋了三個hibernate的類的源碼,大概如下:在繼續之前,先說明一下,這個肯定是要修改hibernate源碼的,這里只講講怎么覆蓋某個jar包里的類:我這里是spring mvc的老項目,最后是部署在tomcat運行,tomcat的WebAppClassloader,負責加載以下兩個路徑的class:覆蓋的原理,就是依賴其查找class的先后順序來做,比如lib下的某個jar包有:org.hibernate.mapping.Table這個類,正常情況下,都會加載到這個類;但如果我們在classes下放一個同包名同類名的類,那么就會優先加載我們的這個class了。但是假設這個類引用了hibernate的其他類B,不影響,畢竟我們沒覆蓋類B,所以還是會到lib下查找,最后還是會使用hibernate jar包中的B。最終源碼已經放在了:https://github.com/cctvckl/work_util/tree/master/Hibernate_PositiveEngineer問題1解決步驟:駝峰格式的建表語句轉下劃線知道怎么覆蓋了,再說說怎么去找要覆蓋哪兒,這個需要一點經驗。我這里先還原成沒修改時的樣子,跑一下項目,發現日志有以下輸出:2019-10-23 13:47:11.819 [main] DEBUG [] org.hibernate.SQL - drop table if exists KPIRECORD2019-10-23 13:47:11.823 [main] DEBUG [] org.hibernate.SQL - create table KPIRECORD ( kpiRecordId varchar(255) not null, endTime varchar(255), evaluatorId varchar(255), kpiComment varchar(255), kpiDate datetime, kpiValue double precision, roleCode integer, startTime varchar(255), superiors varchar(255), userId varchar(255), primary key (kpiRecordId) )2019-10-23 13:47:11.988 [main] INFO [] org.hibernate.tool.hbm2ddl.SchemaExport - HHH000230: Schema export complete其他不重要,我們看最后一行,里面包含了Schema export complete,這個肯定是代碼里的日志,我們拿這個東西,在代碼里搜一波(這一步,要求maven是下載了jar包的源碼):接下來,我們點進去,因為maven下載了源碼的關系,所以再利用idea的findUsage功能,剩下的,就是在覺得比較靠譜的地方打上斷點,運行一下,debug一下,大概就知道流程了。找啊找,找到了下面的地方,(org.hibernate.mapping.Table#sqlCreateString)怎么覆蓋,不用多說了吧,如果是spring mvc(或者spring boot)架構,都要在最上層的module里的src下操作,加上這么一個全路徑一致的類,然后將里面的sqlCreateString改寫。我這里附上改寫后的:到這里,基本搞定了第一個問題。問題2解決步驟:給建表語句增加注釋其實這個步驟分成了2個小步驟,第一步是拿到下面這樣的數據:第二步,就是像上面第一步那樣,在生成create table語句時,根據table名稱,取到上面這樣的數據,然后再根據列名,取到注釋,拼成一條下面這樣的(重點是下面加粗部分):start_time varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '考評開始時間',問題2解決步驟之第一步:獲取表字段注釋這部分純粹考驗字符串解析功力了,我說下思路,也可以直接看源碼。主要是逐行讀取java文件,然后看該行是否為注釋(區分單行注釋和多行注釋):單行: /** 被考評人*/ private String userId;多行: /** * 主鍵,考評記錄ID */ private String kpiRecordId;單行注釋的話,直接用正則匹配;多行的話,會引入一個狀態變量,最后還是會轉換為一個單行注釋。匹配上后,提取出注釋,存到一個全局變量;如果下一行正則匹配了一個field,則將之前的注釋和這個field湊一對,存到map里。大致流程就是這樣的,代碼如下:問題2解決步驟之第二步:覆蓋hibernate源碼,建表過程中構造注釋這次覆蓋了org.hibernate.cfg.Configuration#generateSchemaCreationScript方法:然后里面的內容也不用我細說了,再次根據列名查找注釋,構造建表sql就行了。這里加個成果展示:總結希望對大家有所幫助,有疑問可以直接加我。源碼在:https://github.com/cctvckl/work_util/tree/master/Hibernate_PositiveEngineer
10-23 23:37
總結
以上是生活随笔為你收集整理的hibernate h2变mysql_懒要懒到底,能自动的就不要手动,Hibernate正向工程完成Oracle数据库到MySql数据库转换(含字段转换、注释)...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java监听某端口和ip_Java 通过
- 下一篇: java jpa注解哪个包好,Sprin