简体   繁体   中英

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. Mybe it is related to that I am not using POJO.

MyBatis version: 3.4.5

My table:

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

MyBatis mapper:

@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.

What is the solution?

EDIT

I am trying to debug mybatis code and I have found " [B " in the parameterTypes : 在此处输入图片说明

java.lang.Long cannot be cast to [B

This is saying that you are trying to convert long to byte[]

Looking at source of 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).

@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.

Then why not keep everything in the SQL:

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

For exception regarding parameters, parameters must be named with @Param annotation

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, [...]

EDIT: unless you consider that under the hood, the java 8 PreparedStatement.executeLargeUpdate returning long is executed.

[...] 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. 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. To use this feature, your project must be compiled in Java 8 with -parameters option . (Since: 3.4.1) valid values: true | false default: true

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM