栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java > SpringBoot

MyBatis通过TypeHandler自动编解码对象的Json属性

SpringBoot 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

MyBatis通过TypeHandler自动编解码对象的Json属性

mysql从5.7.版本开始支持json列。它本质上仍然是一个字符串,比起直接用varchar来说,它有专门对于json的的检索,修改方法。更加的灵活。

在jdbc规范中,还没json类型的定义。所以对象一般都是用String属性,映射数据库的json列。在存储和读取的时候,需要自己完成json的序列化和反序列化。

在使用MyBatis的框架,可以通过定义TypeHandler来自动完成Json属性的序列化和反序列化。

演示一个Demo

这里使用Gson的JsonElement作为对象的Json属性对象。我觉得它比较灵活,可以在JsonObject和JsonArray中随意转换。

整合MyBatis

… 略

表结构 & 模型对象 表结构
CREATE TABLE `website` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
  `name` varchar(255) NOT NULL COMMENT '网站名称',
  `properties` json DEFAULT NULL COMMENT '网站属性,这是一个Json列',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
模型对象
import com.google.gson.JsonElement;

public class WebSite {
	// 网站id
	private Integer id;
	// 网站名称
	private String name;
	// 网站属性,json
	private JsonElement properties;
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public JsonElement getProperties() {
		return properties;
	}
	public void setProperties(JsonElement properties) {
		this.properties = properties;
	}
	@Override
	public String toString() {
		return "WebSite [id=" + id + ", name=" + name + ", properties=" + properties + "]";
	}
}
自定义 TypeHandler

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

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

import com.google.gson.JsonElement;
import com.google.gson.JsonParser;

public class JsonElementTypeHandler extends baseTypeHandler {

	
	@Override
	public void setNonNullParameter(PreparedStatement ps, int i, JsonElement parameter, JdbcType jdbcType) throws SQLException {
		String value = parameter.toString();
		if (jdbcType == null) {
			ps.setObject(i, value);
		} else {
			ps.setObject(i, value, jdbcType.TYPE_CODE);
		}
	}

	
	@Override
	public JsonElement getNullableResult(ResultSet rs, String columnName) throws SQLException {
		String result = rs.getString(columnName);
		return result == null ? null : JsonParser.parseString(result);
	}

	
	@Override
	public JsonElement getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
		String result = rs.getString(columnIndex);
		return result == null ? null : JsonParser.parseString(result);
	}

	
	@Override
	public JsonElement getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
		String result = cs.getString(columnIndex);
		return result == null ? null : JsonParser.parseString(result);
	}
}

在mybatis配置文件中,配置handler



	
		
	

Mapper的定义
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Options;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;

import io.springboot.jpa.entity.WebSite;

@Mapper
public interface WebSiteMapper {
	
	@Insert("INSERT INTO `website`(`id`, `name`, `properties`) VALUES(#{id}, #{name}, #{properties});")
	@Options(useGeneratedKeys = true, keyColumn = "id", keyProperty = "id")
	int save(WebSite webSite);
	
	@Select("SELECT * FROM `website` WHERe `id` = #{id};")
	WebSite findById(@Param("id") Integer id);
}

测试
private static final Logger LOGGER = LoggerFactory.getLogger(JpaApplicationTest.class);

@Autowired
private WebSiteMapper webSiteMapper;

@Test
@Transactional
@Rollback(false)
public void test () {
	WebSite webSite = new WebSite();
	webSite.setName("SpringBoot中文社区");
	
	// 初始化properties属性
	JsonObject jsonObject = new JsonObject();
	jsonObject.addProperty("url", "https://springboot.io");
	jsonObject.addProperty("initializr", "https://start.springboot.io");
	jsonObject.addProperty("Github", "https://github.com/springboot-community");
	
	webSite.setProperties(jsonObject);
	
	// 存储
	this.webSiteMapper.save(webSite);
	
	// 根据id检索
	webSite = this.webSiteMapper.findById(webSite.getId());
	
	LOGGER.info("resut={}", new Gson().toJson(webSite));
}
日志输出
org.mybatis.spring.SqlSessionUtils: Creating a new SqlSession
org.mybatis.spring.SqlSessionUtils: Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@34be7efb]
o.m.s.t.SpringManagedTransaction  : JDBC Connection [HikariProxyConnection@885723920 wrapping com.mysql.cj.jdbc.ConnectionImpl@625487a6] will be managed by Spring
i.s.jpa.mapper.WebSiteMapper.save : ==>  Preparing: INSERT INTO `website`(`id`, `name`, `properties`) VALUES(?, ?, ?);
i.s.jpa.mapper.WebSiteMapper.save : ==> Parameters: null, SpringBoot中文社区(String), {"url":"https://springboot.io","initializr":"https://start.springboot.io","Github":"https://github.com/springboot-community"}(String)
i.s.jpa.mapper.WebSiteMapper.save : <==    Updates: 1
org.mybatis.spring.SqlSessionUtils: Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@34be7efb]
org.mybatis.spring.SqlSessionUtils: Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@34be7efb] from current transaction
i.s.jpa.mapper.WebSiteMapper.findById    : ==>  Preparing: SELECt * FROM `website` WHERe `id` = ?;
i.s.jpa.mapper.WebSiteMapper.findById    : ==> Parameters: 4(Integer)
i.s.jpa.mapper.WebSiteMapper.findById    : <==      Total: 1
org.mybatis.spring.SqlSessionUtils: Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@34be7efb]
i.s.jpa.test.JpaApplicationTest   : resut={"id":4,"name":"SpringBoot中文社区","properties":{"url":"https://springboot.io","Github":"https://github.com/springboot-community","initializr":"https://start.springboot.io"}}

不论是写入还是读取,都无误的对JsonElement完成了编码和解码。

核心只要明白了 TypeHandler的几个方法,不管是Gson, Fastjson, Jackson 甚至是自定义对象,都可以很简单的完成自动映射。

原文:https://springboot.io/t/topic/2455

转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号