Flyway迁移SQL文件无法读取资源目录SVG文件的问题
解决Flyway迁移中PostgreSQL pg_read_file()无法读取项目资源文件的问题
问题根源
pg_read_file()是PostgreSQL服务器端函数,它读取的是数据库服务器本地文件系统中的文件,而非应用程序所在机器的文件,更不是项目classpath下的资源文件。你之前用绝对路径能成功,是因为该路径是数据库服务器可访问的本地路径(比如本地开发时数据库和应用在同一台机器),而你写的相对路径是相对于PostgreSQL的工作目录(通常是其data目录),而非你的Java项目目录,所以找不到文件。
解决方案
方案一:将文件放到PostgreSQL允许读取的目录
- 在psql中执行
SHOW data_directory;查询PostgreSQL的数据目录 - 将
image.svg复制到该目录下 - 修改SQL迁移文件中的路径:
INSERT INTO public.image(image_id, file) VALUES ('656cc4e8-9e50-1111-1111-303cdc05a058', pg_read_file('image.svg')::bytea);
或者直接使用数据库服务器上的绝对路径:
INSERT INTO public.image(image_id, file) VALUES ('656cc4e8-9e50-1111-1111-303cdc05a058', pg_read_file('/var/lib/postgresql/14/main/image.svg')::bytea);
注意:若要读取data目录外的文件,需修改PostgreSQL配置文件
postgresql.conf的相关参数,同时确保PostgreSQL进程拥有该文件的读取权限。
方案二:使用Flyway Java迁移读取classpath资源
这种方式更贴合Java项目的资源管理逻辑,利用Spring的资源加载能力读取classpath文件后插入数据库:
- 在
src/main/java/db/migration/目录下创建Java迁移类:
package db.migration; import org.flywaydb.core.api.migration.BaseJavaMigration; import org.flywaydb.core.api.migration.Context; import org.springframework.core.io.ClassPathResource; import java.io.IOException; import java.sql.PreparedStatement; import java.util.UUID; public class V1__PopulateImageTable extends BaseJavaMigration { @Override public void migrate(Context context) throws IOException { // 读取classpath中的SVG文件 ClassPathResource svgResource = new ClassPathResource("local-images/image.svg"); byte[] svgBytes = svgResource.getContentAsByteArray(); // 执行插入操作 String insertSql = "INSERT INTO public.image(image_id, file) VALUES (?, ?)"; try (PreparedStatement stmt = context.getConnection().prepareStatement(insertSql)) { stmt.setObject(1, UUID.fromString("656cc4e8-9e50-1111-1111-303cdc05a058")); stmt.setBytes(2, svgBytes); stmt.executeUpdate(); } catch (Exception e) { throw new RuntimeException("插入图片数据失败", e); } } }
- 删除或重命名原来的SQL迁移文件,避免Flyway重复执行迁移
方案三:直接将SVG内容嵌入SQL文件
如果SVG文件内容较小,可以直接将其文本内容转换为bytea类型插入:
INSERT INTO public.image(image_id, file) VALUES ('656cc4e8-9e50-1111-1111-303cdc05a058', E'<svg xmlns="http://www.w3.org/2000/svg" ...></svg>'::bytea);
注意:SVG内容中的特殊字符需要正确转义,比如单引号要替换为两个单引号。
内容的提问来源于stack exchange,提问作者Gaurav Jeswani
相关产品推荐
相关产品推荐

