您好,登录后才能下订单哦!
密码登录
登录注册
点击 登录注册 即表示同意《亿速云用户服务条款》
# MyBatis TypeHandler注入Spring依赖的方法
## 前言
在Java企业级应用开发中,MyBatis作为一款优秀的持久层框架,与Spring框架的整合已成为行业标配。TypeHandler作为MyBatis类型转换的核心组件,其与Spring依赖注入机制的整合对于构建灵活、可维护的数据访问层至关重要。本文将深入探讨TypeHandler的实现原理、Spring依赖注入机制,并提供多种实用的整合方案。
## 第一章:TypeHandler基础概念
### 1.1 什么是TypeHandler
TypeHandler是MyBatis中用于处理Java类型与JDBC类型之间转换的核心接口,主要职责包括:
- 参数设置(PreparedStatement)
- 结果集获取(ResultSet)
- 存储过程参数处理(CallableStatement)
```java
public interface TypeHandler<T> {
void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException;
T getResult(ResultSet rs, String columnName) throws SQLException;
// 其他方法...
}
MyBatis已为常见Java类型提供了默认实现:
Java类型 | 对应TypeHandler |
---|---|
String | StringTypeHandler |
Integer | IntegerTypeHandler |
Date | DateTypeHandler |
Enum | EnumTypeHandler |
需要自定义TypeHandler的典型场景包括: - 复杂JSON对象与数据库VARCHAR的转换 - 加密/解密字段处理 - 特殊日期格式处理 - 状态枚举的定制化存储
Spring通过BeanFactory和ApplicationContext实现控制反转:
graph TD
A[配置文件/注解] --> B[BeanDefinition]
B --> C[BeanFactory]
C --> D[依赖注入]
@Service
public class UserService {
private final UserRepository repository;
@Autowired
public UserService(UserRepository repository) {
this.repository = repository;
}
}
@Service
public class OrderService {
private PaymentService paymentService;
@Autowired
public void setPaymentService(PaymentService paymentService) {
this.paymentService = paymentService;
}
}
@Service
public class ProductService {
@Autowired
private InventoryService inventoryService;
}
作用域 | 描述 |
---|---|
singleton | 默认作用域,单个IoC容器共享实例 |
prototype | 每次请求创建新实例 |
request | 单个HTTP请求生命周期 |
session | 用户会话生命周期 |
public class JsonTypeHandler extends BaseTypeHandler<MyData>
implements InitializingBean {
@Autowired
private ObjectMapper objectMapper;
@Override
public void afterPropertiesSet() {
SpringBeanAutowiringSupport
.processInjectionBasedOnCurrentContext(this);
}
// 实现TypeHandler方法...
}
优缺点分析: - 优点:实现简单 - 缺点:强依赖Spring上下文
public class SecureTypeHandler extends BaseTypeHandler<String>
implements ApplicationContextAware {
private ApplicationContext context;
private Encryptor encryptor;
@Override
public void setApplicationContext(
ApplicationContext applicationContext) {
this.context = applicationContext;
this.encryptor = context.getBean(Encryptor.class);
}
// 实现加解密逻辑...
}
在MyBatis配置类中注册:
@Configuration
public class MyBatisConfig {
@Bean
public EncryptTypeHandler encryptTypeHandler(EncryptService service) {
return new EncryptTypeHandler(service);
}
@Bean
public SqlSessionFactory sqlSessionFactory(
DataSource dataSource,
EncryptTypeHandler encryptTypeHandler) {
SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
factory.setDataSource(dataSource);
// 注册TypeHandler
factory.setTypeHandlers(new TypeHandler[]{
encryptTypeHandler
});
return factory.getObject();
}
}
public class SpringAwareTypeHandlerProxy<T> implements TypeHandler<T> {
private final TypeHandler<T> delegate;
public SpringAwareTypeHandlerProxy(TypeHandler<T> delegate) {
this.delegate = delegate;
AutowireCapableBeanFactory factory = ...;
factory.autowireBean(delegate);
}
// 委托方法实现...
}
public class StatusEnumTypeHandler extends BaseTypeHandler<Status> {
@Autowired
private StatusMappingRepository repository;
@Override
public void setNonNullParameter(PreparedStatement ps, int i,
Status parameter, JdbcType jdbcType) {
ps.setInt(i, repository.getCode(parameter));
}
@Override
public Status getNullableResult(ResultSet rs, String columnName) {
return repository.getStatus(rs.getInt(columnName));
}
}
public class TenantAwareTypeHandler extends BaseTypeHandler<String> {
@Autowired
private TenantContext tenantContext;
@Override
public void setNonNullParameter(PreparedStatement ps, int i,
String parameter, JdbcType jdbcType) {
String processed = tenantContext.process(parameter);
ps.setString(i, processed);
}
}
创建META-INF/spring.factories
:
org.mybatis.spring.boot.autoconfigure.TypeHandlerAutoConfiguration=\
com.example.handlers.CustomHandlerAutoConfiguration
配置类示例:
@Configuration
@AutoConfigureAfter(MybatisAutoConfiguration.class)
public class CustomHandlerAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public GeoTypeHandler geoTypeHandler() {
return new GeoTypeHandler();
}
}
@Component
@Scope("prototype")
public class ContextAwareHandler extends BaseTypeHandler<Object> {
// 每个请求独立实例
}
public class CachingTypeHandler extends BaseTypeHandler<BigDecimal> {
private final LoadingCache<String, BigDecimal> cache;
public CachingTypeHandler(CurrencyService service) {
this.cache = Caffeine.newBuilder()
.maximumSize(1000)
.build(service::convertCurrency);
}
}
public class SafeJsonTypeHandler extends BaseTypeHandler<Map> {
@Override
public Map getNullableResult(ResultSet rs, String columnName) {
try {
return parseJson(rs.getString(columnName));
} catch (IOException e) {
log.error("JSON解析失败", e);
return Collections.emptyMap();
}
}
}
上下文未正确设置
ContextLoaderListener
web.xml
配置作用域不匹配
@Component
@Scope("prototype")
public class PrototypeHandler { ... }
循环依赖问题
@Lazy
注解解决
<result column="json_data" property="data"
typeHandler="com.example.JsonTypeHandler"/>
public class TransactionAwareHandler extends BaseTypeHandler<String> {
@Autowired
private PlatformTransactionManager txManager;
@Override
public void setParameter(...) {
TransactionTemplate template = new TransactionTemplate(txManager);
template.execute(status -> {
// 在事务中执行操作
return null;
});
}
}
@TableName(autoResultMap = true)
public class User {
@TableField(typeHandler = JsonTypeHandler.class)
private Map<String, Object> attributes;
}
public class ReactiveTypeHandler extends BaseTypeHandler<Mono<String>> {
@Autowired
private ReactiveRedisTemplate<String, String> redisTemplate;
@Override
public Mono<String> getNullableResult(ResultSet rs, String columnName) {
return redisTemplate.opsForValue().get(rs.getString(columnName));
}
}
@RefreshScope
@Component
public class CloudConfigTypeHandler extends BaseTypeHandler<String> {
@Value("${encryption.key}")
private String encryptionKey;
// 配置热更新时会自动刷新
}
通过本文的系统性讲解,我们深入探讨了MyBatis TypeHandler与Spring依赖注入的多种整合方案。从基础实现到高级应用,从性能优化到异常处理,希望这些内容能为开发者构建健壮的数据访问层提供有效参考。随着技术生态的不断发展,TypeHandler的应用模式也将持续演进,建议读者持续关注MyBatis和Spring框架的最新动态。
src/
├── main/
│ ├── java/
│ │ └── com/
│ │ └── example/
│ │ ├── config/
│ │ ├── handler/
│ │ └── model/
│ └── resources/
│ ├── mapper/
│ └── application.yml
”`
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。