在JPA項(xiàng)目啟動(dòng)時(shí)如何新增MySQL字段
前言
本來用了JPA,直接實(shí)體類加參數(shù)就可以新增字段了,但是架不住垃圾項(xiàng)目在啟動(dòng)項(xiàng)目時(shí)會(huì)加載數(shù)據(jù)庫SQL文件去插入數(shù)據(jù),那沒辦法了,只能再加一些弱智操作去修復(fù)一些弱智操作。
起因
項(xiàng)目啟動(dòng)的時(shí)候會(huì)先執(zhí)行schema.sql,再執(zhí)行data.sql,然后再執(zhí)行JPA建表新增字段等操作。然而在新版本中在配置表中加了某個(gè)字段,假設(shè)為status,并且在data.sql中對(duì)status進(jìn)行了賦值操作。此時(shí)舊版本升級(jí)新版本,啟動(dòng)時(shí)執(zhí)行了data.sql文件,就會(huì)報(bào)錯(cuò),報(bào)錯(cuò)信息,配置如下:
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:
# 工程啟動(dòng)加載數(shù)據(jù)庫結(jié)構(gòu)sql腳本
schema:
- classpath:/mysql/schema.sql
# 工程啟動(dòng)加載數(shù)據(jù)庫默認(rèn)數(shù)據(jù)sql腳本
data:
- classpath:/mysql/data.sql解決方案
如果要解決這個(gè)問題,那么就需要在 schema.sql 中新增字段,下面是幾種解決方案:
方案1
方案說明
在 schema.sql 刪除這個(gè)表,然后重新建表的時(shí)候帶上要新增的字段
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)用場景
該方案簡單粗暴,僅限于這個(gè)表存的數(shù)據(jù)一直不變,不會(huì)被更新。
可能出現(xiàn)的問題
如果該表被修改了,刪除再新增初始化會(huì)回到初始狀態(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)用場景
沒遇到不適用的,評(píng)論區(qū)補(bǔ)充吧
可能出現(xiàn)的問題
如果配置了阿里 Durid,那么Druid 連接池的 SQL 防火墻機(jī)制會(huì)阻止動(dòng)態(tài) SQL 語句 PREPARE stmt FROM @sql 的執(zhí)行。Druid 的 SQL 防火墻嚴(yán)格限制某些類型的 SQL 語句,以防止 SQL 注入攻擊。錯(cuò)誤如下(本來是一行的,我加下?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 配置中放寬對(duì)該語句的限制。但這可能會(huì)帶來安全風(fēng)險(xiǎn),因此需要謹(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版本都試過,直接報(bào)錯(cuò)不知道什么原因)
可能出現(xiàn)的問題
可能的問題就是我試過我不行,沒時(shí)間去看為啥不行了,大佬可直接評(píng)論區(qū)說一下,謝謝
總結(jié)
我用的方案1,如果你也是這種項(xiàng)目,那么我也推薦你用方案1,簡單粗暴又方便;方案2是問了chatgpt得出來的答案,感覺不錯(cuò),但是報(bào)錯(cuò)了又不想改;但是你需要知道為何會(huì)出現(xiàn)這種問題,以及如何避免出現(xiàn)這種問題,以下是我的理解:
- 不建議使用 schema.sql 和 data.sql 對(duì)數(shù)據(jù)庫結(jié)構(gòu)及數(shù)據(jù)進(jìn)行初始化,因?yàn)樵诿恳淮雾?xiàng)目啟動(dòng),這兩個(gè)文件都必須執(zhí)行一次,大大減慢了項(xiàng)目的啟動(dòng)速度,替代方案可以是使用 flyway 進(jìn)行數(shù)據(jù)庫版本控制。
- JPA 真的不是初學(xué)者快捷構(gòu)建項(xiàng)目的首選,如果沒有對(duì) JPA 有正確的理解,在遇到復(fù)雜場景時(shí)會(huì)手足無措,這邊還是建議使用 Mybatis 捏,初學(xué)者多寫寫 SQL 語句有助于進(jìn)步捏,高手另說哈。 感謝您的閱讀
到此這篇關(guān)于在JPA項(xiàng)目啟動(dòng)時(shí)新增MySQL字段的文章就介紹到這了,更多相關(guān)JPA啟動(dòng)新增MySQL字段內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- JPA之映射mysql text類型的問題
- Springboot2.0配置JPA多數(shù)據(jù)源連接兩個(gè)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中分頁查詢的數(shù)據(jù)重復(fù)問題
本文分析了MySQL分頁查詢中常見的數(shù)據(jù)重復(fù)問題,主要發(fā)生在排序字段值相同時(shí),MySQL不穩(wěn)定排序?qū)е掠涗涰樞虿灰恢?下面我們就來深入探討一下吧2026-05-05
MYSQL 左連接右連接和內(nèi)連接的詳解及區(qū)別
這篇文章主要介紹了MYSQL 左連接右連接和內(nèi)連接的詳解及區(qū)別的相關(guān)資料,需要的朋友可以參考下2016-11-11
mysql通過my.cnf修改默認(rèn)字符集為utf-8的方法和注意事項(xiàng)
本文主要給大家介紹mysql通過my.cnf修改默認(rèn)字符集為utf-8的方法,當(dāng)然你也可以設(shè)置成別的,國際點(diǎn)還是utf-8好,以及在修改過程中要注意的一些事項(xiàng),有需要的朋友們可以參考借鑒。2016-09-09
mysql InnoDB建表時(shí)設(shè)定初始大小的方法
這篇文章主要介紹了mysql InnoDB建表時(shí)設(shè)定初始大小的方法,需要大家到MYSQL后臺(tái)實(shí)際操作方可以看到效果2013-11-11
MySQL中字段類型為longtext的值導(dǎo)出后顯示二進(jìn)制串方式
這篇文章主要介紹了MySQL中字段類型為longtext的值導(dǎo)出后顯示二進(jìn)制串方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07
MySQL中處理大數(shù)據(jù)表的3種方案的實(shí)現(xiàn)與對(duì)比
這篇文章主要為大家詳細(xì)介紹了MySQL中處理大數(shù)據(jù)表的3種方案的實(shí)現(xiàn)與對(duì)比,文中的示例代碼講解詳細(xì),有需要的小伙伴可以根據(jù)需要進(jìn)行選擇2025-10-10

