news 2026/3/8 3:52:09

Forest项目数据库从Derby迁移至MySQL指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Forest项目数据库从Derby迁移至MySQL指南

Forest项目数据库从Derby迁移至MySQL实战指南

在开发Java EE应用时,我们常会用Apache Derby作为初期的嵌入式数据库。它启动快、无需独立部署,特别适合教学项目和本地调试。像经典的Forest示例项目,默认就使用Derby来简化环境搭建。但一旦进入多实例部署或准备上线,问题就来了:Derby不支持远程连接,无法应对高并发,连基本的主从复制都没有——这些都成了生产环境中的致命短板。

我最近带团队做一次系统重构,就把一个运行多年的Forest项目从Derby迁移到了MySQL。整个过程看似简单,但实际操作中踩了不少坑:驱动加载失败、字符集乱码、外键约束冲突……最终总结出一套可复用的迁移方案,今天分享出来,希望能帮你少走弯路。


首先得把MySQL环境准备好。推荐直接上5.7以上版本,避免遇到老版本的兼容性问题。Linux或macOS下可以通过systemctlbrew快速启动服务:

sudo systemctl start mysql

接着登录MySQL,创建专用数据库和用户。这里强调一点:千万别让应用直接用root账号连接,这是很多安全审计不过关的根源。正确的做法是创建最小权限账户:

CREATE DATABASE forest CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE USER 'forest_user'@'localhost' IDENTIFIED BY 'secure_password'; GRANT ALL PRIVILEGES ON forest.* TO 'forest_user'@'localhost'; FLUSH PRIVILEGES;

注意指定了utf8mb4字符集,这是为了后续支持中文和emoji。如果跳过这步,后期插入中文数据时大概率会报“Incorrect string value”错误。

接下来是关键一步——修改数据源配置。Forest通常跑在GlassFish这类Java EE服务器上,数据源定义在web.xml里。原来的Derby配置长这样:

<data-source> <name>java:global/ForestDataSource</name> <class-name>org.apache.derby.jdbc.EmbeddedDataSource</class-name> ... </data-source>

需要替换成MySQL对应的配置:

<data-source> <name>java:global/ForestDataSource</name> <class-name>com.mysql.cj.jdbc.MysqlDataSource</class-name> <server-name>localhost</server-name> <port-number>3306</port-number> <user>forest_user</user> <password>secure_password</password> <database-name>forest</database-name> <property> <name>useSSL</name> <value>false</value> </property> <property> <name>allowPublicKeyRetrieval</name> <value>true</value> </property> <property> <name>serverTimezone</name> <value>UTC</value> </property> </data-source>

这几个连接参数很关键:
-useSSL=false:测试环境可以关闭,生产建议开启并配置证书;
-allowPublicKeyRetrieval=true:解决某些MySQL 8.x版本下的公钥获取问题;
-serverTimezone=UTC:避免时区差异导致时间字段错乱。

别忘了删掉原配置里的createDatabaseIfNotExist这类Derby特有属性,MySQL不认这个。

光改配置还不行,还得让应用服务器认识MySQL驱动。最稳妥的方式是把JDBC驱动放进服务器的lib目录:

  1. 去官网下载最新版 MySQL Connector/J,比如mysql-connector-java-8.0.33.jar
  2. 放到应用服务器的类路径下,例如:
    domains/domain1/lib/mysql-connector-java-8.0.33.jar
  3. 重启服务器生效。

如果漏了这步,启动时准会看到熟悉的红字报错:

java.lang.ClassNotFoundException: com.mysql.cj.jdbc.MysqlDataSource

这时候别慌,检查JAR包是否放对位置,再确认文件名有没有拼错。

接下来是重头戏——SQL脚本适配。Derby和MySQL语法差异不小,直接拿原脚本执行基本必挂。我们需要调整三类文件:drop.sqlcreate.sqldata.sql

先看drop.sql。由于存在外键依赖,删表必须按顺序来,否则会提示“Cannot delete or update a parent row”。更稳妥的做法是临时关闭外键检查:

SET FOREIGN_KEY_CHECKS = 0; DROP TABLE IF EXISTS ORDER_DETAIL; DROP TABLE IF EXISTS CUSTOMER_ORDER; DROP TABLE IF EXISTS PRODUCT; DROP TABLE IF EXISTS CATEGORY; DROP TABLE IF EXISTS PERSON_GROUPS; DROP TABLE IF EXISTS PERSON; DROP TABLE IF EXISTS GROUPS; DROP TABLE IF EXISTS ORDER_STATUS; SET FOREIGN_KEY_CHECKS = 1;

IF EXISTS能避免因表不存在而中断脚本执行,这对自动化部署尤其重要。

再来看建表语句create.sql。核心改动点有几个:

  • 主键自增从GENERATED ALWAYS AS IDENTITY改成AUTO_INCREMENT
  • Blob类型升级为LONGBLOB,以防图片数据超限;
  • 所有文本字段统一用utf8mb4编码;
  • 外键约束显式命名,便于后期排查问题。

以下是适配后的部分建表示例:

CREATE TABLE PERSON ( ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY, FIRSTNAME VARCHAR(50) NOT NULL, LASTNAME VARCHAR(100) NOT NULL, EMAIL VARCHAR(45) NOT NULL UNIQUE, ADDRESS VARCHAR(45) NOT NULL, CITY VARCHAR(45) NOT NULL, PASSWORD VARCHAR(100), DTYPE VARCHAR(31) ); CREATE INDEX SQL_PERSON_EMAIL_INDEX ON PERSON(EMAIL);

索引也重新规划了一下,比如给EMAIL加唯一索引,提升登录查询效率。这种细节能在高并发场景下带来明显性能改善。

至于data.sql,内容基本不用动,但要确保字段类型匹配。比如原来Derby里可能允许空字符串插入非空字段,MySQL默认是不允许的,得提前清理脏数据。

到这里,持久层配置其实已经差不多了。多数情况下,persistence.xml不需要修改:

<persistence-unit name="forestPU" transaction-type="JTA"> <jta-data-source>java:global/ForestDataSource</jta-data-source> <properties> <property name="javax.persistence.schema-generation.database.action" value="none"/> </properties> </persistence-unit>

只要JNDI名称一致,并且明确关闭了自动建表(schema-generation设为none),JPA就能顺利接管。如果你用的是Hibernate,可以额外指定方言优化性能:

<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL8Dialect"/>

最后一步,执行迁移。首次迁移建议手动操作,流程清晰可控:

  1. 登录MySQL命令行;
  2. 依次执行drop.sqlcreate.sqldata.sql
  3. 启动应用服务器;
  4. 浏览首页,验证数据是否正常加载。

等流程跑通后,就可以写成自动化脚本集成进CI/CD流水线:

#!/bin/bash DB_USER="forest_user" DB_PASS="secure_password" DB_NAME="forest" mysql -u$DB_USER -p$DB_PASS $DB_NAME < sql/drop.sql mysql -u$DB_USER -p$DB_PASS $DB_NAME < sql/create.sql mysql -u$DB_USER -p$DB_PASS $DB_NAME < sql/data.sql echo "✅ Database migration completed!"

配上GitLab CI或者Jenkins,每次发布都能一键完成数据库初始化。

当然,过程中难免遇到问题。我把常见故障列了个表,方便快速定位:

问题原因分析解决方案
ClassNotFoundException: MysqlDataSource缺少MySQL驱动检查JAR是否放入正确的lib目录
Access denied for user用户名密码错误或权限不足重新授权或检查连接字符串
Unknown database 'forest'数据库未创建手动执行CREATE DATABASE或启用自动创建
Incorrect string value字符集不匹配统一使用UTF8MB4编码
应用启动报错外键冲突表删除顺序不当先关闭外键检查再执行DROP

特别提醒:如果出现“Data truncation”错误,大概率是某个VARCHAR字段长度不够,记得根据日志定位具体表和字段。

这次迁移完成后,系统的稳定性明显提升。更重要的是,为后续扩展打开了空间——现在可以轻松引入连接池监控、读写分离,甚至考虑分库分表。相比之下,困在Derby里几乎寸步难行。

最后提个小建议:把最终版的SQL脚本纳入Git管理,并写清楚执行顺序说明。新人接手项目时,再也不用问“数据库怎么初始化”这种问题了。

技术演进的本质,就是不断把“能跑”变成“跑得好”。从Derby到MySQL,不只是换了个数据库,更是工程思维的一次升级。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/4 15:59:47

【AI编程效率提升300%】:Python集成Open-AutoGLM接口的终极方法论

第一章&#xff1a;Python集成Open-AutoGLM接口的核心价值将Python与Open-AutoGLM接口深度集成&#xff0c;为开发者提供了高效构建智能化应用的能力。该集成不仅简化了自然语言处理任务的实现流程&#xff0c;还显著提升了模型调用的灵活性和可扩展性&#xff0c;适用于自动化…

作者头像 李华
网站建设 2026/3/3 23:06:50

Vue自定义精美商品分类组件,助力电商开发

Vue自定义精美商品分类组件&#xff0c;助力电商开发 在移动电商应用的日常开发中&#xff0c;分类页几乎是每个项目都绕不开的核心模块。无论是综合类平台还是垂直领域商城&#xff0c;用户往往通过分类导航快速定位商品&#xff0c;这使得该页面不仅承载着巨大的流量入口功能…

作者头像 李华
网站建设 2026/3/6 18:13:49

Open-AutoGLM怎么装在手机上?3种方法曝光,第2种最简单

第一章&#xff1a;Open-AutoGLM操作手机怎么安装 Open-AutoGLM 是一款基于 AutoGLM 框架开发的移动端自动化工具&#xff0c;支持通过自然语言指令驱动手机完成各类操作。在手机上安装 Open-AutoGLM 需要确保设备满足基础运行环境&#xff0c;并按照标准流程进行部署。 准备工…

作者头像 李华
网站建设 2026/3/8 4:19:15

拆解2004年松下DV摄像机:数字时代的缩影

拆解2004年松下DV摄像机&#xff1a;数字时代的缩影 在智能手机随手一拍就能生成4K视频的今天&#xff0c;你是否还记得那种小心翼翼按下“录制”键、屏住呼吸对准孩子的第一次走路、毕业典礼或家庭旅行的画面&#xff1f;那时我们用的不是手机&#xff0c;而是一台沉甸甸却充满…

作者头像 李华
网站建设 2026/3/6 0:42:34

Open-AutoGLM接口调用难题,90%开发者忽略的2个关键参数配置

第一章&#xff1a;Open-AutoGLM接口调用难题&#xff0c;90%开发者忽略的2个关键参数配置在集成 Open-AutoGLM 接口时&#xff0c;许多开发者频繁遭遇响应超时或鉴权失败问题&#xff0c;根源往往在于两个被广泛忽视的关键参数&#xff1a;timeout_ms 与 signature_version。正…

作者头像 李华