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: usingjava.sql.Blobis 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




