我正在尝试使用MyBatis将新记录插入到一个简单的数据库表中,但我得到一个奇怪的异常。 Mybe与我没有使用POJO有关。
MyBatis版本:3.4.5
我的表:
@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);
MyBatis mapper:
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)
...
我得到的例外:
[B
我不想为这个"内容"创建带有getter / setter方法的POJO类。 param但我认为这个问题与缺少POJO有关。
解决方案是什么?
修改
答案 0 :(得分: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})")
否则参数会移一。
答案 1 :(得分: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
返回long。
[...]而不是建议生成的密钥。然后,您似乎最终想要获取键值,这意味着返回到带有@SelectKey
的方块,并且需要POJO和生成值的目标属性。它甚至适用于带有生成密钥的批量插入。
我最近发现,如果按照settings section of the documentation中的说明操作,可以使用实际参数名称(那么您的代码将按原样运行):
useActualParamName
允许引用语句参数 方法签名中声明的实际名称。要使用此功能, 您的项目必须使用-parameters选项在Java 8中编译。 (自:3.4.1)有效值:true
|false
默认值:true