2017-10-12 145 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