SpringMVC postgreSQL二進制文件存儲

引言

我這裏有一張表的列類型是bytea型,也就是文件的二進制數據,它屬於大對象(Large Objects)。
(什麼是大對象) 把二進制數據插入表中須要如下幾個步驟。html

0. 沒有使用Spring以及Mybatis時,處理PostgreSQL二進制數據

postgreSQL官方文檔中,存儲二進制是用Java的PreparedStatement#setBinaryStream方法。spring

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到表中時,出現瞭如下PSQLExceptionbash

大對象不能用於自動提交模式(Large Objects may not be used in auto-commit mode)
複製代碼

因而改爲了手動提交事務,終於成功插入了數據。 有時候咱們須要手動提交事務,好比說很大的數據分次提交,避免內存溢出。又或者插入二進數據到表中。
這裏的關鍵是本身把DataSourceTransactionManager注入,並使用它進行事務處理。mybatis

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字段。app

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, 0, len);
		}
		return bout.toByteArray();
	}
	
}
複製代碼

最後執行上述service的insert方法,插入到數據庫。
select phototemplate結果 post

相關文章
相關標籤/搜索