[英]Insert a new record with autogenerated id
I am trying to insert a new record into a simple database table with MyBatis but I get a strange exception. 我正在尝试使用MyBatis将新记录插入到简单的数据库表中,但出现一个奇怪的异常。 Mybe it is related to that I am not using POJO. 可能与我没有使用POJO有关。
MyBatis version: 3.4.5 MyBatis版本:3.4.5
My table: 我的桌子:
CREATE TABLE IF NOT EXISTS image
(
id BIGINT PRIMARY KEY,
content BYTEA
) WITHOUT OIDS;
MyBatis mapper: 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);
The way I am trying to use it: 我尝试使用它的方式:
byte[] fileContent = IOUtils.toByteArray(inputStream);
long id = imageDao.insertImage(fileContent);
The exception what I get: 我得到的例外:
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)
...
I do not want to create POJO class with getter/setter method for this one "content" param but I think this issue is related to missing POJO. 我不想为此一种“内容”参数使用getter / setter方法创建POJO类,但我认为此问题与缺少POJO有关。
What is the solution? 解决办法是什么?
EDIT 编辑
I am trying to debug mybatis code and I have found " [B
" in the parameterTypes
: 我正在尝试调试mybatis代码,并且在parameterTypes
发现了“ [B
”:
java.lang.Long cannot be cast to [B java.lang.Long不能强制转换为[B
This is saying that you are trying to convert long
to byte[]
这就是说您正在尝试将long
转换为byte[]
Looking at source of org.apache.ibatis.type.ByteArrayTypeHandler
: 查看org.apache.ibatis.type.ByteArrayTypeHandler
源代码:
public void setNonNullParameter(PreparedStatement ps, int i, byte[] parameter, JdbcType jdbcType) throws SQLException {
ps.setBytes(i, parameter);
}
I think you need to remove {id}
from insert annotation (as this value is autogenerated). 我认为您需要从插入注释中删除{id}
(因为此值是自动生成的)。
@Insert("INSERT INTO image (content) VALUES (#{content})")
Otherwise parameters are shifted by one. 否则,参数将移位一。
@SelectKey
is useful when you want to reuse generated value farther in the code, but it seems yo will not. 当您想在代码中进一步重用生成的值时, @SelectKey
很有用,但似乎不会。
Then why not keep everything in the SQL: 那么为什么不将所有内容保留在SQL中:
INSERT INTO image (id, content) VALUES ((SELECT NEXTVAL('image_seq')), #{content})
For exception regarding parameters, parameters must be named with @Param
annotation 对于有关参数的异常,必须使用@Param
批注来命名参数
int insertImage(@Param("content") byte[] content);
or 要么
int insertImage(@Param("id) Long id, @Param("content") byte[] content)
Note that INSERT as well as UPDATE and DELETE statements returns type int being the number of inserted/updated/deleted rows, [...] 请注意,INSERT以及UPDATE和DELETE语句返回的类型为int,即插入/更新/删除的行数,[...]
EDIT: unless you consider that under the hood, the java 8 PreparedStatement.executeLargeUpdate
returning long is executed. 编辑:除非您认为在幕后,否则将执行返回long的Java 8 PreparedStatement.executeLargeUpdate
。
[...] and not the generated key as it is suggested. [...]而不是建议的生成密钥。 Then it seems you eventually want to get the key value, that means back to square one with @SelectKey
and need for a POJO and a target property for the generated value. 那么看来您最终想要获得键值,这意味着要使用@SelectKey
返回平方,并需要一个POJO和一个用于生成值的目标属性。 It even works with bulk insert with generated keys. 它甚至可以与带有生成密钥的批量插入一起使用。
I have discovered lately that actual parameters name can be used (then your code will work as is) if following instructions in settings section of the documentation : 我最近发现,如果按照文档的“设置”部分中的说明进行操作,则可以使用实际的参数名称(然后您的代码将按原样工作):
useActualParamName
Allow referencing statement parameters by their actual names declared in the method signature.useActualParamName
允许通过方法签名中声明的实际名称引用语句参数。 To use this feature, your project must be compiled in Java 8 with -parameters option . 要使用此功能,您的项目必须使用-parameters选项在Java 8中进行编译 。 (Since: 3.4.1) valid values:true
| (自3.4.1开始)有效值:true
|false
default:true
false
默认值:true
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.