You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flyway迁移SQL文件无法读取资源目录SVG文件的问题

解决Flyway迁移中PostgreSQL pg_read_file()无法读取项目资源文件的问题

问题根源

pg_read_file()是PostgreSQL服务器端函数,它读取的是数据库服务器本地文件系统中的文件,而非应用程序所在机器的文件,更不是项目classpath下的资源文件。你之前用绝对路径能成功,是因为该路径是数据库服务器可访问的本地路径(比如本地开发时数据库和应用在同一台机器),而你写的相对路径是相对于PostgreSQL的工作目录(通常是其data目录),而非你的Java项目目录,所以找不到文件。

解决方案

方案一:将文件放到PostgreSQL允许读取的目录

  1. 在psql中执行SHOW data_directory;查询PostgreSQL的数据目录
  2. 将image.svg复制到该目录下
  3. 修改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文件后插入数据库:

  1. 在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);
        }
    }
}
  1. 删除或重命名原来的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 19:02:11