MyBatis中TypeHandler的使用


最終遇到一個問題,就是在使用MyBatis保存數據的時候里面的javabean得字段不是單純的字段,而是包含了對象(也是javaBean)。這種方式並不奇怪,但是以為我這次遇到的是四次嵌套。所以我就使用了TypeHandler來處理試試,測試的時候還是以雙層嵌套為例子。

基本環境的准備

 

 

實體類代碼:

public class Person {
    private int id;
    private Student student;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public Student getStudent() {
        return student;
    }

    public void setStudent(Student student) {
        this.student = student;
    }

    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                ", student=" + student +
                '}';
    }
}
public class Student {
    private int id;
    private String name;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

Mapper接口

public interface PersonMapper {
    /**
     * 新增一條記錄
     *
     * @param p
     * @return
     */
    Integer insertOne(Person p);

    /**
     * 查詢一條記錄
     *
     * @param p
     * @return
     */
    Person query();


}

Mapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mybatistypehandler.mapper.PersonMapper">

    <resultMap id="BaseResultMap" type="com.example.mybatistypehandler.domain.Person">
        <id column="id" jdbcType="INTEGER" property="id"></id>
        <result column="student" jdbcType="VARCHAR" property="student"
                typeHandler="com.example.mybatistypehandler.util.JsonTypeHandler"/>
    </resultMap>


    <insert id="insertOne">

    INSERT INTO
        person(student)
    VALUES(#{student,typeHandler=com.example.mybatistypehandler.util.JsonTypeHandler})

    </insert>


    <select id="query" resultMap="BaseResultMap">
        select id,student from person limit 1
    </select>

</mapper>

service以及實現類

public interface PersonService {
    /**
     * 新增一條記錄
     *
     * @param p
     * @return
     */
    Integer insert(Person p);

    /**
     * 查詢一條記錄
     *
     * @param p
     * @return
     */
    Person query();
}
@Service
public class PersonServiceImpl implements PersonService {
    @Autowired(required = false)
    PersonMapper personMapper;

    @Override
    public Integer insert(Person p) {
        return personMapper.insertOne(p);
    }

    @Override
    public Person query() {
        return personMapper.query();
    }
}

Controller

@RestController
@RequestMapping("t")
public class MyTypeHandlerController {

    @Autowired
    PersonService personService;


    @RequestMapping("save")
    public String save(@RequestBody Person person) {
        personService.insert(person);
        return "SUCCESS";
    }

    @RequestMapping("query")
    public String query() {
        Person query = personService.query();
        System.out.println(query);
        System.out.println(query.getStudent());
        return "SUCCESS";
    }


}

 

yml配置文件

server:
  port: 8899
spring:
  application: TypeHandlerTest
  datasource:
    druid:
      #指定數據庫類型
      db-type: com.alibaba.druid.pool.DruidDataSource
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://192.168.20.152:3306/TypeHandlerTest?useUnicode=true&characterEncoding=utf8&useSSL=false
      username: root
      password: 111111


mybatis:
  mapper-locations: classpath:mapper/**.xml

工具類

public class JsonTypeHandler<T extends Object> extends BaseTypeHandler<T> {

    private Class<T> clazz;


    public JsonTypeHandler(Class<T> clazz) {
        if (clazz == null) {
            throw new IllegalArgumentException("Type argument cannot be null");
        }
        this.clazz = clazz;
    }

    @Override
    public void setNonNullParameter(PreparedStatement preparedStatement, int i, T t, JdbcType jdbcType) throws SQLException {
        preparedStatement.setString(i, this.toJson(t));
    }

    @Override
    public T getNullableResult(ResultSet resultSet, String columnName) throws SQLException {
        return this.toObject(resultSet.getString(columnName), clazz);
    }

    @Override
    public T getNullableResult(ResultSet resultSet, int columnIndex) throws SQLException {
        return this.toObject(resultSet.getString(columnIndex), clazz);
    }

    @Override
    public T getNullableResult(CallableStatement callableStatement, int columnIndex) throws SQLException {
        return this.toObject(callableStatement.getString(columnIndex), clazz);
    }

    private String toJson(T object) {
        try {
            return JSON.toJSONString(object);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private T toObject(String content, Class<?> clazz) {
        if (content != null && !content.isEmpty()) {
            try {
                return (T) JSON.parseObject(content, clazz);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        } else {
            return null;
        }
    }
}

啟動類

@SpringBootApplication
@MapperScan(basePackages = "com.example.mybatistypehandler.mapper")
public class MybatisTypehandlerApplication {

    public static void main(String[] args) {
        SpringApplication.run(MybatisTypehandlerApplication.class, args);
    }

}

 測試

http://localhost:8899/t/save 

 

{
  "student":{
     "name":"小明"
   }
}

 

 

 對象數據被成功轉成json保存到數據庫了

那么查詢的時候能否將json轉成對象保存起來呢?

http://localhost:8899/t/query

 

 

 

 

 

 json被成功的封裝到對象中了。

原理

在保存的時候,實際上走了這個方法:setNonNullParameter

斷點調試下看看是什么東西

 

 

 

 

最后一個是數據庫中的字段類型。

 

查詢的調試

 

 

 

 這就是為什么數據庫中是json,但是查出來卻能直接轉成對象的原因。

另外注意JsonTypeHandler是需要繼承BaseTypeHandler(或者是)實現TypeHandler接口。只要這樣MyBatis在處理類型的時候才會去執行相應的方法。

MyBatis中自帶的類型處理

 

 

 

 不畏艱險,踐踏實地!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM