mybatis中实现枚举自动转换方法详解

前言

最近在工作中遇到一个问题,在设计数据库的时候,我们有时候会把表里的某个字段的值设置为数字或者为英文来表示他的一些特殊含义。就拿设置成数字来说,假如1对应是学生,2对应是教师,在Java里面定义成这样的枚举,但是一般使用mybatis查出来的话,我们想要让它自动装换成我们想要的枚举,不需要再手动根据数值去判断设置成我们想要的枚举。要是实现这样的效果,那么我们就要用到mybatis的BaseTypeHandler了。

BaseTypeHandler介绍

让我们来看看要继承BaseTypeHandler这个抽象类,需要覆写哪些方法:

public abstract void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException; 

public abstract T getNullableResult(ResultSet rs, String columnName) throws SQLException; 

public abstract T getNullableResult(ResultSet rs, int columnIndex) throws SQLException; 

public abstract T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException; 

实现了这些抽象类,当得到结果集的时候,程序就会回调这些方法,例如根据名称获取当前行的某一列的值,那么就会直接回调getNullableResult(ResultSet rs, String columnName)这个方法,根据名称得到当行的当前列的值,然后我们在这里去调用枚举,匹配枚举中的每一个值,相等的话直接返回该枚举,达到自动转换成我们想要的枚举的效果。其他的重载方法类似,只不过是有些根据列索引,有些根据列名称做枚举自动转换而已。

好了,介绍就到这里,让我们来看看具体实现。。

自动转换实现例子

创建数据库表

创建枚举

package net.itaem.less; 

import java.util.HashMap;
import java.util.Map; 

/**
 * @author: Fighter168
 */
public enum PersonType{
 STUDENT("1","学生"),
 TEACHER("2","教师"); 

 private String value;
 private String displayName; 

 static Map<String,PersonType> enumMap=new HashMap<String, PersonType>();
 static{
 for(PersonType type:PersonType.values()){
  enumMap.put(type.getValue(), type);
 }
 } 

 private PersonType(String value,String displayName) {
  this.value=value;
  this.displayName=displayName;
 } 

 public String getValue() {
 return value;
 }
 public void setValue(String value) {
 this.value = value;
 }
 public String getDisplayName() {
 return displayName;
 }
 public void setDisplayName(String displayName) {
 this.displayName = displayName;
 } 

 public static PersonType getEnum(String value) {
 return enumMap.get(value);
 }
} 

创建Po实体类

/**
 * @author: Fighter168
 */
public class Person {
 private String id;
 private String name;
 //枚举
 private PersonType personType;
 //set get 方法。。
} 

创建Dao接口

创建一个简单的测试dao,这里简单的提供一个测试的查询方法。

/**
 * @author: Fighter168
 */
public interface PersonDao { 

 public List<Person> query(); 

} 

创建枚举转换处理器

package net.itaem.handler; 

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

import net.itaem.less.PersonType; 

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

/**
 * @author: Fighter168
 */
public class PersonTypeHandler extends BaseTypeHandler<PersonType>{ 

 private Class<PersonType> type; 

 private PersonType[] enums; 

 /**
 * 设置配置文件设置的转换类以及枚举类内容,供其他方法更便捷高效的实现
 * @param type 配置文件中设置的转换类
 */
 public PersonTypeHandler(Class<PersonType> type) {
 if (type == null)
  throw new IllegalArgumentException("Type argument cannot be null");
 this.type = type;
 this.enums = type.getEnumConstants();
 if (this.enums == null)
  throw new IllegalArgumentException(type.getSimpleName()
   + " does not represent an enum type.");
 } 

 @Override
 public PersonType getNullableResult(ResultSet rs, String columnName) throws SQLException {
 // 根据数据库存储类型决定获取类型,本例子中数据库中存放String类型
 String i = rs.getString(columnName);
 if (rs.wasNull()) {
  return null;
 } else {
  // 根据数据库中的value值,定位PersonType子类
  return PersonType.getEnum(i);
 }
 } 

 @Override
 public PersonType getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
 // 根据数据库存储类型决定获取类型,本例子中数据库中存放String类型
  String i = rs.getString(columnIndex);
 if (rs.wasNull()) {
  return null;
 } else {
  // 根据数据库中的value值,定位PersonType子类
  return PersonType.getEnum(i);
 }
 } 

 @Override
 public PersonType getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
  // 根据数据库存储类型决定获取类型,本例子中数据库中存放String类型
 String i = cs.getString(columnIndex);
 if (cs.wasNull()) {
  return null;
 } else {
  // 根据数据库中的value值,定位PersonType子类
  return PersonType.getEnum(i);
 }
 } 

 @Override
 public void setNonNullParameter(PreparedStatement ps, int i, PersonType parameter, JdbcType jdbcType)
  throws SQLException {
 // baseTypeHandler已经帮我们做了parameter的null判断
 ps.setString(i, parameter.getValue()); 

 } 

} 

创建Mapper映射文件

PersonDao对应的PersonMapper映射文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://www.mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="net.itaem.dao.PersonDao" > 

 <resultMap id="resultMap" type="net.itaem.po.Person" >
 <result column="id" property="id" jdbcType="CHAR" />
 <result column="name" property="name" jdbcType="CHAR" />
 <result column="type" property="personType" jdbcType="CHAR" />
 </resultMap> 

 <select id="query" resultMap="resultMap">
 select * from person
 </select> 

</mapper> 

其实handler还可以写在PersonMapper.xml这里,写成下面这样:

<result column="type" property="personType" typeHandler="net.itaem.handler.PersonTypeHandler"/> 

创建Spring的配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
 <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
  <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
  <property name="url" value="jdbc:mysql://localhost:3306/test"/>
  <property name="username" value="root"/>
  <property name="password" value="123abc"/>
  <!-- 连接池启动时候的初始连接数 -->
  <property name="initialSize" value="10"/>
  <!-- 最小空闲值 -->
  <property name="minIdle" value="5"/>
  <!-- 最大空闲值 -->
  <property name="maxIdle" value="20"/>
  <property name="maxWait" value="2000"/>
  <!-- 连接池最大值 -->
  <property name="maxActive" value="50"/>
  <property name="logAbandoned" value="true"/>
  <property name="removeAbandoned" value="true"/>
  <property name="removeAbandonedTimeout" value="180"/>
 </bean> 

 <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
 <property name="configLocation" value="classpath:/resource/cfg.xml"/>
 <property name="dataSource" ref="dataSource"/>
 </bean> 

 <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
  <property name="basePackage" value="net.itaem.dao"/>
 </bean>
</beans> 

创建mybatis的配置文件

下面是为mybatis创建配置文件cfg.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
 PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
 "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
 <typeHandlers>
 <typeHandler handler="net.itaem.handler.PersonTypeHandler"
  javaType="net.itaem.less.PersonType" jdbcType="CHAR"/>
 </typeHandlers>
 <!-- mapping 文件路径配置 -->
 <mappers>
 <mapper resource="resource/PersonMapper.xml" />
 </mappers>
</configuration> 

创建测试用例

/**
 * @author: Fighter168
 */
public class SpringTest { 

 public static void main(String[] args) {
 ApplicationContext context=new ClassPathXmlApplicationContext("resource/ApplicationContext.xml");
 PersonDao personDao=(PersonDao) context.getBean("personDao");
 List<Person> list=personDao.query();
 for(Person p:list){
  System.out.println(p.toString());
 }
 }
} 

测试结果展示

结果是成功自动转换成了我们想要的枚举

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

(0)

相关推荐

  • Mybatis中自定义TypeHandler处理枚举详解

    在Mybatis中,处理枚举类的TypeHandler有两个: EnumTypeHandler: 用于保存枚举名 EnumOrdinalTypeHandler: 用于保存枚举的序号. 在实际项目中,以上往往不能满足我们的需求. 需求分析 枚举需要包含两个属性,label(用于显示), value(实际的枚举值).数据库保存枚举值(value). 这很明显Mybatis提供的两个枚举TypeHandler不能满足我们的需求.此时,我们可以自定义一个通用的枚举TypeHandler来满足我们的需求.

  • MyBatis中如何优雅的使用枚举详解

    问题 本文主要给大家介绍的是关于MyBatis使用枚举的相关内容,我们在编码过程中,经常会遇到用某个数值来表示某种状态.类型或者阶段的情况,比如有这样一个枚举: public enum ComputerState { OPEN(10), //开启 CLOSE(11), //关闭 OFF_LINE(12), //离线 FAULT(200), //故障 UNKNOWN(255); //未知 private int code; ComputerState(int code) { this.code =

  • mybatis中实现枚举自动转换方法详解

    前言 最近在工作中遇到一个问题,在设计数据库的时候,我们有时候会把表里的某个字段的值设置为数字或者为英文来表示他的一些特殊含义.就拿设置成数字来说,假如1对应是学生,2对应是教师,在Java里面定义成这样的枚举,但是一般使用mybatis查出来的话,我们想要让它自动装换成我们想要的枚举,不需要再手动根据数值去判断设置成我们想要的枚举.要是实现这样的效果,那么我们就要用到mybatis的BaseTypeHandler了. BaseTypeHandler介绍 让我们来看看要继承BaseTypeHan

  • SpringBoot在RequestBody中使用枚举参数案例详解

    前文说到 优雅的使用枚举参数 和 实现原理,本文继续说一下如何在 RequestBody 中优雅使用枚举. 本文先上实战,说一下如何实现.在 优雅的使用枚举参数 代码的基础上,我们继续实现. 确认需求 需求与前文类似,只不过这里需要是在 RequestBody 中使用.与前文不同的是,这种请求是通过 Http Body 的方式传输到后端,通常是 json 或 xml 格式,Spring 默认借助 Jackson 反序列化为对象. 同样的,我们需要在枚举中定义 int 类型的 id.String

  • Mybatis中Mapper映射文件使用详解

    紧接上文所述,在这篇文章中我将对Mapper映射文件进行详细的说明. Mapper映射文件是一个xml格式文件,必须遵循相应的dtd文件规范,如ibatis-3-mapper.dtd.我们先大体上看看支持哪些配置?如下所示,从Eclipse里截了个屏: 从上图可以看出,映射文件是以<mapper>作为根节点,在根节点中支持9个元素,分别为insert.update.delete.select(增删改查);cache.cache-ref.resultMap.parameterMap.sql. 下

  • Mybatis中注解@MapKey的使用详解

    mybatis的原身是ibatis,现在已经脱离了apache基金会,新官网是http://www.mybatis.org/. 在研究Mybatis源码之前并不知道这个注解的妙用的,但是当我看到参数解析的时候 有这个一个注解,所以我了解了一下,当我们返回像Map<String, Map<String, Object>>这种类型的时候,我们往往很难做到,因为这里面可能是多个表的数据,所以我们不可能再建一个模型. 这时候我们就可以使用这个注解了 @Retention(Retention

  • MyBatis中的JdbcType映射使用详解

    Java项目涉及到数据库交互,以往常用的是JDBC,现在则有Hibernate.Mybatis等这些持久化支持. 项目中用到了MyBatis,和JDBC最显著的区别,就是SQL语句配置化,通过xml文件定义SQL语句,当然JDBC也可以将SQL配置化,需要定制开发,MyBatis则直接支持这种方法. 官方对于MyBatis的介绍, MyBatis is a first class persistence framework with support for custom SQL, stored

  • MyBatis中OGNL的使用教程详解

    前言 本文主要给大家讲如何在MyBatis中使用OGNL的相关内容,分享出来供大家参考学习,感兴趣的朋友们下面来一起看看详细的介绍: 如果我们搜索OGNL相关的内容,通常的结果都是和Struts有关的,你肯定搜不到和MyBatis有关的,虽然和Struts中的用法类似但是换种方式理解起来就有难度. MyBatis常用OGNL表达式 e1 or e2 e1 and e2 e1 == e2,e1 eq e2 e1 != e2,e1 neq e2 e1 lt e2:小于 e1 lte e2:小于等于,

  • MyBatis中Mapper的注入问题详解

    在 SpringBoot 体系中,MyBatis 对 Mapper 的注入常见的方式我知道的有 2 种: 1.@MapperScan MapperScan 类是 mybatis-spring 包里面的. 通过在启动类上使用 @MapperScan,然后通过 basePackages 属性指定 Mapper 文件所在的目录来进行扫描装载,默认情况下指定目录下的所有.java文件都会被当做 Mapper 来加载处理. @MapperScan(basePackages = "com.test.spri

  • PHP中Enum(枚举)用法实例详解

    本文实例讲述了PHP中Enum(枚举)用法.分享给大家供大家参考,具体如下: PHP其实有Enum类库的,需要安装perl扩展,所以不是php的标准扩展,因此代码的实现需要运行的php环境支持. (1)扩展类库SplEnum类.该类的摘要如下: SplEnum extends SplType { /* Constants */ const NULL __default = null ; /* 方法 */ public array getConstList ([ bool $include_def

  • Mybatis中@Param注解的用法详解

    目录 1.概述 2.实例: 实例一:@Param注解基本类型的参数 实例二:@Param注解JavaBean对象 3.注意点 附:为什么要用@param 总结 1.概述 首先明确这个注解是为SQL语句中参数赋值而服务的. @Param的作用就是给参数命名,比如在mapper里面某方法A(int id),当添加注解后A(@Param("userId") int id),也就是说外部想要取出传入的id值,只需要取它的参数名userId就可以了.将参数值传如SQL语句中,通过#{userId

  • Swift编程中的一些类型转换方法详解

    验证一个实例的类型'类型转换'在 Swift 语言编程中.它是用来检查实例类型是否属于特定超类或子类或其自己的层次结构定义. Swift 类型转换提供两个操作符:"is" 检查值的类型和 'as' 将类型值转换为不同的类型值. 类型转换还检查实例类型是否符合特定的协议一致性标准. 定义一个类层次结构 类型转换用于检查实例的类型或者它属于特定类型.此外,检查类和它的子类层次结构来检查并转换这些实例,使之作为一个相同的层次结构. 复制代码 代码如下: class Subjects {   

随机推荐