Java通过REST API从MySQL读取图片报Blob容器构建器不存在错误
问题原因
你的报错是JDBI 2.x版本未内置java.sql.Blob类型的容器构造器导致的,当你定义DAO方法直接返回Blob类型时,JDBI无法将数据库返回的大字段结果封装为Blob实例。
另外还有一个隐藏问题:java.sql.Blob是和数据库连接生命周期绑定的,一旦数据库连接关闭,即使你拿到Blob实例也无法读取其中的内容,后续调用handleBlob方法同样会报错。
解决方案
推荐优先采用第一种方案,实现成本最低且稳定性更高:
方案1:修改DAO方法返回值为byte[]
JDBI默认支持将MySQL的BLOB类型列直接映射为字节数组,你只需要调整retrieveImage对应的DAO方法、Factory方法的返回值类型从Blob改为byte[]即可,不需要修改SQL逻辑,也不需要额外配置映射器。
调整后你的业务代码可以简化为:
// 不需要再调用handleBlob处理Blob,直接拿到图片字节数组 byte[] image = BooksFactory.retrieveImage(b.getBookId());
方案2:自定义注册Blob容器工厂(不推荐)
如果业务必须使用Blob类型,你可以手动为JDBI注册Blob类型的容器构造器,示例代码如下:
// 初始化JDBI的时候注册 jdbi.registerContainerFactory(new ContainerFactory<Blob>() { @Override public boolean accepts(Class<?> type) { return Blob.class.isAssignableFrom(type); } @Override public ContainerBuilder<Blob> newContainerBuilderFor(Class<?> type) { return new ContainerBuilder<Blob>() { private Blob blob; @Override public ContainerBuilder<Blob> add(Object it) { this.blob = (Blob) it; return this; } @Override public Blob build() { return blob; } }; } });
注意该方案需要额外处理数据库连接生命周期,确保读取Blob内容时连接未关闭,维护成本更高。
额外优化建议
- 你当前的逻辑是先查全量书籍列表,再循环调用接口查每本书的图片和库存,属于典型的N+1查询问题,数据量大的时候性能会非常差,建议修改
listAllBooks的SQL语句,关联查询库存和图片字段,一次查询返回所有需要的内容。 - 你当前将图片存储在本地E盘并返回本地路径给前端,前端无法直接访问该路径,建议将图片存储在静态资源服务目录,返回对应的HTTP访问路径,或者将图片转为Base64字符串放在返回结果中。
内容的提问来源于stack exchange,提问作者Pallavi Prasad
相关产品推荐
相关产品推荐

