1. 程式人生 > 程式設計 >SpringMVC postgreSQL二進位制檔案儲存

SpringMVC postgreSQL二進位制檔案儲存

引言

我這裡有一張表的列型別是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結果