Java 插入具有自动生成id的新记录
我试图用MyBatis将一条新记录插入到一个简单的数据库表中,但遇到了一个奇怪的异常。Mybe这与我没有使用POJO有关 MyBatis版本:3.4.5 我的桌子:Java 插入具有自动生成id的新记录,java,mybatis,ibatis,Java,Mybatis,Ibatis,我试图用MyBatis将一条新记录插入到一个简单的数据库表中,但遇到了一个奇怪的异常。Mybe这与我没有使用POJO有关 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}, #{
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方法为这个“content”参数创建POJO类,但我认为这个问题与缺少POJO有关
解决办法是什么
编辑
我正在尝试调试mybatis代码,我在参数类型中找到了“[B
”:
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);
}
我认为您需要从insert注释中删除{id}
(因为这个值是自动生成的)
否则,参数将移位一。@SelectKey
在您希望在代码中进一步重用生成的值时很有用,但您似乎不会
那么为什么不将所有内容都保存在SQL中呢:
INSERT INTO image (id, content) VALUES ((SELECT NEXTVAL('image_seq')), #{content})
关于参数的例外情况,参数必须用@Param
注释命名
int insertImage(@Param("content") byte[] content);
或
请注意,INSERT以及UPDATE和DELETE语句返回的int类型是插入/更新/删除的行数[…]
<强>编辑:除非你认为在引擎盖下,java 8返回长。
[…]而不是像建议的那样生成的键。然后,您似乎最终想要获得键值,这意味着返回到与
@SelectKey
的平方一,并且需要一个POJO和一个生成值的目标属性。它甚至可以与生成键的批量插入一起工作
我最近发现,如果在中遵循以下说明,则可以使用实际参数名称(然后代码将按原样工作):
useActualParamName
允许按语句参数引用语句参数
方法签名中声明的实际名称。若要使用此功能,
您的项目必须使用带有-parameters选项的Java8编译。
(自:3.4.1)有效值:true
|false
默认值:true
根据您的建议,我从sql中删除了id,但没有任何帮助。我遇到了一个奇怪的异常:org.apache.ibatis.binding.BindingException:找不到参数“content”。可用参数是[array,id],我删除了@SelectKey,并向方法签名添加了一个长输入参数,如下所示:long insertImage(long id,byte[]content)。但现在这是我得到的异常:org.apache.ibatis.binding.BindingException:未找到参数“id”。可用参数有[arg1、arg0、param1、param2]我知道日志中这4个参数的来源。谢谢你的回复。最后,我创建了一个带有id、注释、文件名和长度属性的POJO。将这些元数据与文件内容一起存储是有意义的。当然,POJO解决了我的问题。谢谢。
int insertImage(@Param("content") byte[] content);
int insertImage(@Param("id) Long id, @Param("content") byte[] content)