You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Spring Boot整合MyBatis插入MySQL Blob类型报错及自定义TypeHandler注册问题

Spring Boot整合MyBatis插入MySQL Blob类型报错及自定义TypeHandler注册问题

Hi there, let's break down your problem and solve it step by step. The error you're seeing happens because MyBatis can't find a default TypeHandler that maps java.sql.Blob (your model's type) to MySQL's BLOB JDBC type in your version of mybatis-spring-boot-starter (1.3.2 is a bit older, which might be part of the issue).

Let's fix this with two key steps: creating a custom TypeHandler, then registering it in your Spring Boot project without any XML configuration.


Step 1: Create a Custom Blob TypeHandler

First, create a class that extends MyBatis's BaseTypeHandler to handle the java.sql.Blob type explicitly. This will tell MyBatis exactly how to convert between your model's Blob type and the database's BLOB type.

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;

import java.sql.Blob;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

// Annotations to map this handler to your Java type and target JDBC type
@MappedTypes(Blob.class)
@MappedJdbcTypes(JdbcType.BLOB)
public class CustomBlobTypeHandler extends BaseTypeHandler<Blob> {

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, Blob parameter, JdbcType jdbcType) throws SQLException {
        // Pass the Blob object directly to the prepared statement
        ps.setBlob(i, parameter);
    }

    @Override
    public Blob getNullableResult(ResultSet rs, String columnName) throws SQLException {
        // Retrieve Blob from ResultSet using column name
        return rs.getBlob(columnName);
    }

    @Override
    public Blob getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        // Retrieve Blob from ResultSet using column index
        return rs.getBlob(columnIndex);
    }

    @Override
    public Blob getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        // Retrieve Blob from CallableStatement
        return cs.getBlob(columnIndex);
    }
}

This handler removes ambiguity for MyBatis by defining explicit conversion logic for java.sql.Blob.


Step 2: Register the TypeHandler in Spring Boot

Since you're using the mybatis-spring-boot-starter (no XML config required), you have two straightforward ways to register your custom TypeHandler:

Option 1: Application Properties (Simplest)

Add a property to your application.properties or application.yml to tell MyBatis which package to scan for custom TypeHandlers. For example, if your CustomBlobTypeHandler lives in com.yourproject.handlers:

application.properties:

# Tell MyBatis to scan this package for all custom TypeHandlers
mybatis.type-handlers-package=com.yourproject.handlers

application.yml (if you prefer YAML):

mybatis:
  type-handlers-package: com.yourproject.handlers

MyBatis will automatically detect and register any TypeHandlers in this package that are annotated with @MappedTypes/@MappedJdbcTypes or extend BaseTypeHandler.

Option 2: Java Configuration (Manual Control)

If you want more control over the registration process, create a @Configuration class to explicitly define the SqlSessionFactoryBean and register your TypeHandler:

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;

@Configuration
@MapperScan(basePackages = "com.yourproject.mappers") // Replace with your mapper package
public class MyBatisConfig {

    @Bean
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSource);
        
        // Register your custom TypeHandler directly
        sessionFactory.setTypeHandlers(new CustomBlobTypeHandler());
        
        // Alternatively, scan a package for all TypeHandlers:
        // sessionFactory.setTypeHandlersPackage("com.yourproject.handlers");
        
        return sessionFactory.getObject();
    }
}

This approach is useful if you don't want to rely on package scanning, or if you need to register individual TypeHandlers selectively.


Optional: Explicitly Specify TypeHandler in Mapper

While not required if you registered the handler correctly, you can explicitly reference it in your mapper's insert statement to make the mapping absolutely clear:

@Mapper
public interface Mapper {
    String InsertStatement = "insert into table1 (id, contentblob) values (#{id}, #{contentblob, jdbcType=BLOB, typeHandler=com.yourproject.handlers.CustomBlobTypeHandler})";
    
    @Insert(InsertStatement)
    void insertContent(Model param);
}

Quick Additional Notes

  • Your mybatis-spring-boot-starter version (1.3.2) is quite old (released in 2018). Upgrading to a newer stable version (e.g., 2.2.2 for the 2.x branch) would give you better default TypeHandler support and bug fixes, though the custom handler solution works for your current version too.
  • You mentioned avoiding byte[] for large blobs: using java.sql.Blob is fully valid for MySQL (it supports LONGBLOB for large data payloads), so this solution is perfectly suited to your use case.

Give these steps a try, and your insert statement should execute without the TypeHandler null error.

内容来源于stack exchange

火山引擎 最新活动