2017-10-12 141 views
2

我想用MyBatis將一條新記錄插入到一​​個簡單的數據庫表中,但我得到一個奇怪的異常。 Mybe它與我沒有使用POJO有關。用自動生成的ID插入一條新記錄

MyBatis的版本:3.4.5

我的表:

CREATE TABLE IF NOT EXISTS image 
(
    id BIGINT PRIMARY KEY, 
    content BYTEA 
) WITHOUT OIDS; 

MyBatis的映射器:

@Insert("INSERT INTO image (id, content) VALUES (#{id}, #{content})") 
@SelectKey(statement = "SELECT NEXTVAL('image_seq')", keyProperty = "id", before = true, resultType = long.class) 
long insertImage(byte[] content); 

的方式我試圖使用它:

byte[] fileContent = IOUtils.toByteArray(inputStream); 
long id = imageDao.insertImage(fileContent); 

我得到的例外:

java.lang.ClassCastException: java.lang.Long cannot be cast to [B 
    at org.apache.ibatis.type.ByteArrayTypeHandler.setNonNullParameter(ByteArrayTypeHandler.java:26) 
    at org.apache.ibatis.type.BaseTypeHandler.setParameter(BaseTypeHandler.java:53) 
    at org.apache.ibatis.scripting.defaults.DefaultParameterHandler.setParameters(DefaultParameterHandler.java:87) 
    at org.apache.ibatis.executor.statement.PreparedStatementHandler.parameterize(PreparedStatementHandler.java:93) 
    at org.apache.ibatis.executor.statement.RoutingStatementHandler.parameterize(RoutingStatementHandler.java:64) 
    at org.apache.ibatis.executor.SimpleExecutor.prepareStatement(SimpleExecutor.java:86) 
    at org.apache.ibatis.executor.SimpleExecutor.doUpdate(SimpleExecutor.java:49) 
    at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:117) 
    at org.apache.ibatis.executor.CachingExecutor.update(CachingExecutor.java:76) 
    at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:198) 
    at org.apache.ibatis.session.defaults.DefaultSqlSession.insert(DefaultSqlSession.java:185) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
... 

我不想創建這一個「內容」參數的getter/setter方法POJO類,但我認爲這個問題與缺失POJO。

解決方案是什麼?

編輯

我試圖調試MyBatis的代碼,我已經在parameterTypes發現 「[B」: enter image description here

回答

0

@SelectKey當你想在代碼中重複使用生成的值時很有用,但它看起來喲不會。

那麼,爲什麼不把一切都在SQL:

INSERT INTO image (id, content) VALUES ((SELECT NEXTVAL('image_seq')), #{content}) 

異常有關的參數,參數必須與@Param註釋

int insertImage(@Param("content") byte[] content); 

int insertImage(@Param("id) Long id, @Param("content") byte[] content) 

注意,被命名爲INSERT以及UPDATE和DELETE語句返回int類型插入/更新/刪除行的數量,[...]

編輯:除非你認爲在引擎蓋下,java 8 PreparedStatement.executeLargeUpdate返回長執行。

[...]而不是建議的生成密鑰。那麼看起來你最終想獲得關鍵值,這意味着回到原來的@SelectKey,需要一個POJO和一個目標屬性來生成值。它甚至適用於帶有生成密鑰的批量插入。

我近來可用於實際參數名稱發現(那麼你的代碼將工作是)如果settings section of the documentation以下說明:

useActualParamName允許通過在方法中聲明其 實際名稱引用語句的參數簽名。要使用此功能, 您的項目必須使用-parameters選項在Java 8中進行編譯。 (從:3.4.1)有效值:true | false默認:true

+0

感謝您的回覆。 Finnally我創建了一個ID,註釋,文件名和長度屬性的POJO。將這些元數據與文件內容一起存儲是有意義的。 POJO解決了我的問題。謝謝。 – zappee

0

java.lang.Long中不能轉換爲[B

這就是說你試圖將long轉換成byte[]

綜觀org.apache.ibatis.type.ByteArrayTypeHandler來源:

public void setNonNullParameter(PreparedStatement ps, int i, byte[] parameter, JdbcType jdbcType) throws SQLException { 
    ps.setBytes(i, parameter); 
} 

我認爲你需要從插入註釋去掉{id}(因爲這個值是自動生成的)。

@Insert("INSERT INTO image (content) VALUES (#{content})") 

否則參數偏移一個。

+0

按照你的建議,我刪除ID從SQL,但它並沒有幫助。我得到了這個奇怪的異常:org.apache.ibatis.binding.BindingException:找不到參數'content'。可用參數是[array,id] – zappee

+0

我刪除了@SelectKey,並向方法簽名添加了一個長輸入參數,如下所示:long insertImage(long id,byte [] content)。但是現在這是我得到的異常:org.apache.ibatis.binding.BindingException:找不到參數'id'。可用的參數是[arg1,arg0,param1,param2]在日誌中的這4個參數來自哪裏的時候,我有一點點的自信。 – zappee