在JPA項目啟動時如何新增MySQL字段
前言
本來用了JPA,直接實(shí)體類加參數(shù)就可以新增字段了,但是架不住垃圾項目在啟動項目時會加載數(shù)據(jù)庫SQL文件去插入數(shù)據(jù),那沒辦法了,只能再加一些弱智操作去修復(fù)一些弱智操作。
起因
項目啟動的時候會先執(zhí)行schema.sql,再執(zhí)行data.sql,然后再執(zhí)行JPA建表新增字段等操作。然而在新版本中在配置表中加了某個字段,假設(shè)為status,并且在data.sql中對status進(jìn)行了賦值操作。此時舊版本升級新版本,啟動時執(zhí)行了data.sql文件,就會報錯,報錯信息,配置如下:
java.sql.SQLSyntaxErrorException: Unknown column 'status' in 'field list'
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:120)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97)
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)
at com.mysql.cj.jdbc.StatementImpl.executeInternal(StatementImpl.java:764)
at com.mysql.cj.jdbc.StatementImpl.execute(StatementImpl.java:648)
at com.alibaba.druid.filter.FilterChainImpl.statement_execute(FilterChainImpl.java:2958)
at com.alibaba.druid.filter.FilterAdapter.statement_execute(FilterAdapter.java:2473)
at com.alibaba.druid.filter.FilterEventAdapter.statement_execute(FilterEventAdapter.java:188)
at com.alibaba.druid.filter.FilterChainImpl.statement_execute(FilterChainImpl.java:2956)
at com.alibaba.druid.wall.WallFilter.statement_execute(WallFilter.java:415)
at com.alibaba.druid.filter.FilterChainImpl.statement_execute(FilterChainImpl.java:2956)
at com.alibaba.druid.filter.FilterAdapter.statement_execute(FilterAdapter.java:2473)
at com.alibaba.druid.filter.FilterEventAdapter.statement_execute(FilterEventAdapter.java:188)
at com.alibaba.druid.filter.FilterChainImpl.statement_execute(FilterChainImpl.java:2956)
at com.alibaba.druid.proxy.jdbc.StatementProxyImpl.execute(StatementProxyImpl.java:147)
配置:
spring: datasource: # 工程啟動加載數(shù)據(jù)庫結(jié)構(gòu)sql腳本 schema: - classpath:/mysql/schema.sql # 工程啟動加載數(shù)據(jù)庫默認(rèn)數(shù)據(jù)sql腳本 data: - classpath:/mysql/data.sql
解決方案
如果要解決這個問題,那么就需要在 schema.sql 中新增字段,下面是幾種解決方案:
方案1
方案說明
在 schema.sql 刪除這個表,然后重新建表的時候帶上要新增的字段
SET FOREIGN_KEY_CHECKS=0; DROP TABLE IF EXISTS `your_table_name`; CREATE TABLE `hxj_report_template_index` ( `ID` bigint(20) NOT NULL AUTO_INCREMENT, `your_column_name` varchar(255) DEFAULT NULL, PRIMARY KEY (`ID`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; SET FOREIGN_KEY_CHECKS=1;
應(yīng)用場景
該方案簡單粗暴,僅限于這個表存的數(shù)據(jù)一直不變,不會被更新。
可能出現(xiàn)的問題
如果該表被修改了,刪除再新增初始化會回到初始狀態(tài)。
方案2
方案說明
在 schema.sql 判斷該字段是否存在,不存在則新增:
-- 替換 table_name 和 column_name 為實(shí)際的表名和列名 SET @table_name = 'your_table'; SET @column_name = 'new_column'; SET @column_definition = 'VARCHAR(255)'; -- 替換為你需要的列定義 -- 查詢列是否存在 SELECT COUNT(*) INTO @column_exists FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = @table_name AND column_name = @column_name; -- 根據(jù)查詢結(jié)果決定是否新增列 SET @sql = IF(@column_exists = 0, CONCAT('ALTER TABLE ', @table_name, ' ADD COLUMN ', @column_name, ' ', @column_definition), 'SELECT "Column already exists"'); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
應(yīng)用場景
沒遇到不適用的,評論區(qū)補(bǔ)充吧
可能出現(xiàn)的問題
如果配置了阿里 Durid,那么Druid 連接池的 SQL 防火墻機(jī)制會阻止動態(tài) SQL 語句 PREPARE stmt FROM @sql 的執(zhí)行。Druid 的 SQL 防火墻嚴(yán)格限制某些類型的 SQL 語句,以防止 SQL 注入攻擊。錯誤如下(本來是一行的,我加下?lián)Q行方便查看):
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaConfiguration':
Unsatisfied dependency expressed through constructor parameter 0;
nested exception is org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'druidDataSource' defined in class path resource [com/xxx/config/DruidConfig.class]: Initialization of bean failed;
nested exception is org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'org.springframework.boot.autoconfigure.jdbc.DataSourceInitializerInvoker':
Invocation of init method failed; nested exception is org.springframework.jdbc.datasource.init.ScriptStatementFailedException:
Failed to execute SQL script statement #26 of class path resource [mysql/schema.sql]: PREPARE stmt FROM @sql;
nested exception is java.sql.SQLException: sql injection violation, class com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlPrepareStatement not allow : PREPARE stmt FROM @sql
主要看最后一行,如果確實(shí)需要使用 PREPARE 語句,可以考慮在 Druid 配置中放寬對該語句的限制。但這可能會帶來安全風(fēng)險,因此需要謹(jǐn)慎處理。
spring: datasource: druid: wall: config: update-allow: true delete-allow: true insert-allow: true select-allow: true truncate-allow: true replace-allow: true drop-allow: true create-table-allow: true alter-table-allow: true prepared-stmt-allow: true
方案3
方案說明
搜索引擎結(jié)果表示在 MySQL8 有直接的語句可以判斷字段是否存在并新增
ALTER TABLE `your_table_name` ADD COLUMN IF NOT EXISTS `your_column_name` varchar(50);
應(yīng)用場景
適用于 MySQL8.0 以上版本(我在5.7.26和8.0.34版本都試過,直接報錯不知道什么原因)
可能出現(xiàn)的問題
可能的問題就是我試過我不行,沒時間去看為啥不行了,大佬可直接評論區(qū)說一下,謝謝
總結(jié)
我用的方案1,如果你也是這種項目,那么我也推薦你用方案1,簡單粗暴又方便;方案2是問了chatgpt得出來的答案,感覺不錯,但是報錯了又不想改;但是你需要知道為何會出現(xiàn)這種問題,以及如何避免出現(xiàn)這種問題,以下是我的理解:
- 不建議使用 schema.sql 和 data.sql 對數(shù)據(jù)庫結(jié)構(gòu)及數(shù)據(jù)進(jìn)行初始化,因?yàn)樵诿恳淮雾椖繂樱@兩個文件都必須執(zhí)行一次,大大減慢了項目的啟動速度,替代方案可以是使用 flyway 進(jìn)行數(shù)據(jù)庫版本控制。
- JPA 真的不是初學(xué)者快捷構(gòu)建項目的首選,如果沒有對 JPA 有正確的理解,在遇到復(fù)雜場景時會手足無措,這邊還是建議使用 Mybatis 捏,初學(xué)者多寫寫 SQL 語句有助于進(jìn)步捏,高手另說哈。 感謝您的閱讀
到此這篇關(guān)于在JPA項目啟動時新增MySQL字段的文章就介紹到這了,更多相關(guān)JPA啟動新增MySQL字段內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- JPA之映射mysql text類型的問題
- Springboot2.0配置JPA多數(shù)據(jù)源連接兩個mysql數(shù)據(jù)庫方式
- Spring boot基于JPA訪問MySQL數(shù)據(jù)庫的實(shí)現(xiàn)
- 解決springboot的JPA在Mysql8新增記錄失敗的問題
- Spring Data Jpa Mysql使用utf8mb4編碼的示例代碼
- springboot使用spring-data-jpa操作MySQL數(shù)據(jù)庫
- Spring-Data-JPA整合MySQL和配置的方法
- SpringBoot連接MYSQL數(shù)據(jù)庫并使用JPA進(jìn)行操作
- Spring Boot 添加MySQL數(shù)據(jù)庫及JPA實(shí)例
相關(guān)文章
Mysql經(jīng)典高逼格/命令行操作(速成)(推薦)
這篇文章主要介紹了Mysql命令行操作,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04MySQL 重裝MySQL后, mysql服務(wù)無法啟動
把mysql程序卸載后, 重裝, 結(jié)果mysql服務(wù)啟動不了,碰到這個問題的朋友可以參考下。2011-08-08詳解MySQL的主從復(fù)制、讀寫分離、備份恢復(fù)
本篇文章主要對MySQL的主從復(fù)制、讀寫分離、備份恢復(fù)進(jìn)行詳細(xì)全面的講解,具有很好的參考價值,需要的朋友一起來看下吧2016-12-12詳解騰訊云CentOS7.0使用yum安裝mysql及使用遇到的問題
本篇文章主要介紹了騰訊云CentOS7.0使用yum安裝mysql,詳細(xì)的介紹了使用yum安裝mysql及使用遇到的問題,有興趣的可以了解一下。2017-01-01