FlywayJava迁移:在Postgresql中插入BLOB



所有数据库迁移都使用Flyway。现在是迁移时处理二进制数据(图像(的时候了。我使用的是Postgresql和Spring Data JPA。

首先,我使用Postgresql在数据库列photo oid中得到了这个字段

@Entity
public class Person {
// omitted 
@Lob
private byte[] photo;
}

我的迁移脚本看起来像这个

V1__CREATE_DB.sql
V2__INSERT_PERSON.sql
V3__INSERT_PHOTO.java

起初,我没能成功地使用JdbcTemplate迁移(更新(一个有照片的人。后来我发现,通过这样做,我可以将类型oid更改为bytea

@Lob
@Type(type = "org.hibernate.type.BinaryType")
private byte[] photo;

然后我让迁移代码看起来像这个

public void migrate(Context context) throws IOException {
JdbcTemplate template = ...
List<String> locations = ... // photo physical locations/paths
for(String location: locations) {
InputStream image = ... // from location
Long id = ... // get id from image name
template.update("UPDATE person SET photo = ? where id = " + id,
new Object[] { new SqlLobValue(image.readAllBytes(), new DefaultLobHandler()) },
new int[] { Types.BLOB }
);
}
}

此V3__迁移按预期运行,但

  • 是否有更好的方法来实现此迁移?我是否也应该为oid执行此操作?在这种情况下,如何执行?

  • 除了明显的存储容量差异外,是否有理由不选择bytea而不是oid

在几乎打破谷歌之后,我终于找到了一个如何使用JdbcTemplate更新列photo oid的解决方案。

DefaultLobHandler lobHandler = new DefaultLobHandler();
lobHandler.setWrapAsLob(true);
jdbcTemplate.execute("UPDATE person SET photo = ? where id = ?", new AbstractLobCreatingPreparedStatementCallback(lobHandler) {                                                       
protected void setValues(PreparedStatement ps, LobCreator lobCreator) throws SQLException {     
lobCreator.setBlobAsBinaryStream(ps, 1, image, image.available());                                        
ps.setLong(2, id);
}
}

最新更新