SpringMVC postgreSQL二進位制檔案儲存
阿新 • • 發佈:2020-06-24
引言
我這裡有一張表的列型別是bytea型,也就是檔案的二進位制資料,它屬於大物件(Large Objects)。
(什麼是大物件)
把二進位制資料插入表中需要以下幾個步驟。
0. 沒有使用Spring以及Mybatis時,處理PostgreSQL二進位制資料
postgreSQL官方檔案中,儲存二進位制是用Java的PreparedStatement#setBinaryStream方法。
File file = new File("myimage.gif");
FileInputStream fis = new FileInputStream(file);
PreparedStatement ps = conn.prepareStatement("INSERT INTO images VALUES (?,?)" );
ps.setString(1,file.getName());
ps.setBinaryStream(2,fis,file.length());
ps.executeUpdate();
ps.close();
fis.close();
複製程式碼
讀取二進位制則用ResultSet.getBytes()
PreparedStatement ps = con.prepareStatement("SELECT img FROM images WHERE imgname = ?");
ps.setString(1,"myimage.gif");
ResultSet rs = ps.executeQuery();
if (rs != null) {
while (rs.next()) {
byte[] imgBytes = rs.getBytes(1);
// 業務
}
rs.close();
}
ps.close();
複製程式碼
那Spring+mybatis+postgreSQL中怎麼使用呢。也不復雜。
1. 定義實體類
實體類的編碼相當的簡單。我們只需要把相關的二進位制欄位宣告為byte陣列型別,Mybatis就會自動處理。這是因為在MyBatis 3.4中提供了TypeHandler處理BLOB/CLOB資料。
// 實體類欄位
public class Entity {
......
private byte[] phototemplate;
.....
}
複製程式碼
2. 手動提交事務
像往常一樣我把資料insert到表中時,出現了以下PSQLException。
大物件不能用於自動提交模式(Large Objects may not be used in auto-commit mode)
複製程式碼
於是改成了手動提交事務,終於成功插入了資料。
有時候我們需要手動提交事務,比如說很大的資料分次提交,避免記憶體溢位。又或者插入二進資料到表中。
這裡的關鍵是自己把DataSourceTransactionManager注入,並使用它進行事務處理。
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
@Service
public class IndicationmessagesServiceImpl {
@Autowired
MyMapper mapper;
@Autowired
private DataSourceTransactionManager transactionManager;
public void insert() throws Exception {
// 業務邏輯
// TODO
DefaultTransactionDefinition transDefinition = new DefaultTransactionDefinition();
// 開始新事物
transDefinition.setPropagationBehavior(DefaultTransactionDefinition.PROPAGATION_REQUIRES_NEW);
TransactionStatus transStatus = transactionManager.getTransaction(transDefinition);
try {
mapper.insert(entity);
// 提交事務
transactionManager.commit(transStatus);
} catch (Exception e) {
// 回滾事務
transactionManager.rollback(transStatus);
throw new Exception(e);
}
}
}
複製程式碼
3.業務邏輯
我這裡是讀取圖片檔案的二進位制資料,然後賦值給上面的phototemplate欄位。
private byte[] readAll(InputStream inputStream) throws IOException {
byte[] buffer = new byte[1024];
try (ByteArrayOutputStream bout = new ByteArrayOutputStream();) {
int len;
while (-1 != (len = inputStream.read(buffer))) {
bout.write(buffer,len);
}
return bout.toByteArray();
}
}
複製程式碼
最後執行上述service的insert方法,插入到資料庫。
select phototemplate結果