javaspring-bootmybatisspring-mybatis

How do I insert a blob type using Mybatis?


In my Spring Boot application using MyBatis for SQL queries I am having trouble inserting a blob type to MySQL:

Model.java

public class Model {

private Integer id;

private Blob contentblob;

public Integer getId() {
    return id;
}
public void setId(Integer id) {
    this.id = id;
}
public Blob getContentblob() {
    return contentblob;
}
public void setContentblob(Blob contentblob) {
    this.contentblob = contentblob;
}

Mapper.java

@Mapper public interface Mapper {

String InsertStatement = "insert into table1 (id, contentblob) values (#{id}, #{contentblob, jdbcType=BLOB})";

@Insert(InsertStatement)
void insertContent(Model param);}

I get:

Could not find value method on SQL annotation. Cause: java.lang.IllegalStateException: Type handler was null on parameter mapping for property 'contentblob'. It was either not specified and/or could not be found for the javaType (java.sql.Blob) : jdbcType (BLOB) combination.

The error originates from MyBatis where it can't handle java.sql.Blob and the solution provided is to create a file that will override BaseTypeHandler. However where is the second part ("Then register it with the SqlSessionFactoryBean using the typeHandlersPackage property:") inserted? I don't have that XML in my project. I just imported MyBatis from my pom.xml.

<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>1.3.2</version>
</dependency>

The type cannot be byte[] as some blobs are big so I don't think this can be applied (and it is for Oracle though I may be wrong). My code runs without the insert statement and errors when I include it.


Solution

  • You can use InputStream

    @Mapper 
    public interface Mapper {
       String INSERT_SQL = 
          "insert into table1 (id, contentblob) " + 
          "values (#{id}, #{contentblob, jdbcType=BLOB, javaType=java.io.InputStream})";
    
       @Insert(INSERT_SQL)
       void insertContent(@Param("id") Integer id, @Param("contentblob") InputStream contentblob);
    }
    

    Usage

    try (InputStream contentblob = new FileInputStream(new File("path/to/file"))) {
        sqlSession.getMapper(Mapper.class).insertContent(1, contentblob);
    }
    

    Under the hood mybatis will lookup a TypeHandler for javaType=InputStream, jdbcType=BLOB and will delegate to the BlobInputStreamTypeHandler