当前位置:   article > 正文

Mybatis-Plus+JPA+postgresql存储复杂类型、TypeHandle使用_mybatisplus jacksontypehandle

mybatisplus jacksontypehandle

在使用Mybatis-Plus + PostgreSQL开发时,我们会遇到一种情况,需要将Object类型或者List<Object>类型数据存入数据库,这时候我们需要将数据转化为jsonString以字符串的形式存入数据库,我在学习过程中发现,List格式的jsonString在直接存入postgreSql时会报错。那么有没有一种好的方式可以在存入和取出时自动对Object和List<Object>进行格式化呢?Mybatis-Plus为我们提供了TypeHandle接口,供用户进行自定义属性转换。下面列举了一些例子。

一、Entity定义

  1. package com.xia.xiatest.entity;
  2. import com.baomidou.mybatisplus.annotation.IdType;
  3. import com.baomidou.mybatisplus.annotation.TableField;
  4. import com.baomidou.mybatisplus.annotation.TableId;
  5. import com.baomidou.mybatisplus.annotation.TableName;
  6. import com.vladmihalcea.hibernate.type.array.IntArrayType;
  7. import com.vladmihalcea.hibernate.type.array.StringArrayType;
  8. import com.vladmihalcea.hibernate.type.json.JsonBinaryType;
  9. import com.vladmihalcea.hibernate.type.json.JsonStringType;
  10. import com.xia.xiatest.typeHandle.JsonTypeHandle;
  11. import lombok.Data;
  12. import org.apache.ibatis.type.ArrayTypeHandler;
  13. import org.apache.ibatis.type.JdbcType;
  14. import org.hibernate.annotations.Type;
  15. import org.hibernate.annotations.TypeDef;
  16. import org.hibernate.annotations.TypeDefs;
  17. import javax.persistence.*;
  18. import java.util.List;
  19. @Data
  20. @Entity
  21. @Table(name = "banner")
  22. @TableName(value = "banner",autoResultMap = true)
  23. @TypeDefs(value = {
  24. @TypeDef(name = "string-array", typeClass = StringArrayType.class),
  25. @TypeDef(name = "int-array", typeClass = IntArrayType.class),
  26. @TypeDef(name = "json", typeClass = JsonStringType.class),
  27. @TypeDef(name = "jsonb", typeClass = JsonBinaryType.class)
  28. })
  29. public class Banner {
  30.     @TableId(value = "id", type = IdType.AUTO)
  31. @Id
  32. @GeneratedValue(strategy = GenerationType.IDENTITY)
  33. private Long id;
  34. @TableField(value = "num_arr", jdbcType = JdbcType.ARRAY, typeHandler = ArrayTypeHandler.class)
  35. @Type(type = "int-array")
  36. @Column(columnDefinition = "int[]")
  37. private Integer[] numArr;
  38. @TableField(value = "str_arr", jdbcType = JdbcType.ARRAY, typeHandler = ArrayTypeHandler.class)
  39. @Type(type = "string-array")
  40. @Column(columnDefinition = "varchar[]")
  41. private String[] strArr;
  42. @TableField(value = "json_obj", jdbcType = JdbcType.VARCHAR, typeHandler = JsonTypeHandle.class)
  43. @Type(type = "jsonb")
  44. @Column(columnDefinition = "varchar")
  45. private List<Object> jsonObj;
  46. }
  1. @TableName(value = "banner",autoResultMap = true) autoResultMap必须设置为true,这里是mybatis-plus序列化使用。

  1. @Type要设置为jsonb,@Column设置为varchar。这里是给JPA自动建表用。

二、序列化与反序列化静态方法编写

  1. package com.xia.xiatest.utils;
  2. import com.fasterxml.jackson.core.JsonProcessingException;
  3. import com.fasterxml.jackson.core.type.TypeReference;
  4. import com.fasterxml.jackson.databind.ObjectMapper;
  5. import com.xia.xiatest.exception.http.SystemException;
  6. import org.springframework.beans.factory.annotation.Autowired;
  7. import org.springframework.stereotype.Component;
  8. import javax.annotation.PostConstruct;
  9. import java.util.List;
  10. @Component
  11. public class GenericAndJson {
  12. private static ObjectMapper mapper;
  13. @Autowired
  14. private ObjectMapper mapper1;
  15. @PostConstruct
  16. public void setMapper(){
  17. mapper = mapper1;
  18. }
  19. //    两种静态属性注入方式
  20. // @Autowired
  21. // public void setMapper(ObjectMapper mapper) {
  22. // GenericAndJson.mapper = mapper;
  23. // }
  24. public static <T> String objectToJson(T obj) {
  25. try {
  26. String str = mapper.writeValueAsString(obj);
  27. return str;
  28. } catch (JsonProcessingException e) {
  29. e.printStackTrace();
  30. throw new SystemException(500);
  31. }
  32. }
  33. public static <T> T jsonToObject(String s, TypeReference<T> tr) {
  34. try {
  35. if(s == null) {
  36. return null;
  37. }
  38. T t = mapper.readValue(s, tr);
  39. return t;
  40. } catch (JsonProcessingException e) {
  41. e.printStackTrace();
  42. throw new SystemException(500);
  43. }
  44. }
  45. // 两种方法,其实有上面那个就够了
  46. public static <T> List<T> jsonToList(String s) {
  47. try {
  48. if(s == null) {
  49. return null;
  50. }
  51. List<T> t = mapper.readValue(s, new TypeReference<List<T>>(){
  52. });
  53. return t;
  54. } catch (JsonProcessingException e) {
  55. e.printStackTrace();
  56. throw new SystemException(500);
  57. }
  58. }
  59. }

三、自定义TypeHandle

  1. package com.xia.xiatest.typeHandle;
  2. import cn.hutool.core.util.ObjectUtil;
  3. import com.fasterxml.jackson.core.type.TypeReference;
  4. import com.xia.xiatest.utils.GenericAndJson;
  5. import org.apache.ibatis.type.BaseTypeHandler;
  6. import org.apache.ibatis.type.JdbcType;
  7. import java.sql.CallableStatement;
  8. import java.sql.PreparedStatement;
  9. import java.sql.ResultSet;
  10. import java.sql.SQLException;
  11. public class JsonTypeHandle<T> extends BaseTypeHandler<T> {
  12. @Override
  13. public void setNonNullParameter(PreparedStatement preparedStatement, int i, T t, JdbcType jdbcType) throws SQLException {
  14. if(ObjectUtil.isNotEmpty(t)){
  15. String str = GenericAndJson.objectToJson(t);
  16. preparedStatement.setString(i, str);
  17. }else{
  18. preparedStatement.setString(i, null);
  19. }
  20. }
  21. @Override
  22. public T getNullableResult(ResultSet resultSet, String s) throws SQLException {
  23. String str = resultSet.getString(s);
  24. if(str == null){
  25. return null;
  26. } else {
  27. T result = GenericAndJson.jsonToObject(str, new TypeReference<T>() {
  28. });
  29. return result == null? null : result;
  30. }
  31. }
  32. @Override
  33. public T getNullableResult(ResultSet resultSet, int i) throws SQLException {
  34. String str = resultSet.getString(i);
  35. if(str == null){
  36. return null;
  37. } else {
  38. T result = GenericAndJson.jsonToObject(str, new TypeReference<T>() {
  39. });
  40. return result == null? null : result;
  41. }
  42. }
  43. @Override
  44. public T getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
  45. String str = callableStatement.getString(i);
  46. if(str == null){
  47. return null;
  48. } else {
  49. T result = GenericAndJson.jsonToObject(str, new TypeReference<T>() {
  50. });
  51. return result == null? null : result;
  52. }
  53. }
  54. }

这样就可以在Entity中使用啦

 @TableField(value = "json_obj", jdbcType = JdbcType.VARCHAR, typeHandler = JsonTypeHandle.class)

四、测试一下

存入截图

返回数据截图

五、优缺点总结

  1. 优点:通用,不用定义多个TypeHandle。

  1. 缺点:这种通用方式反序列化出来的对象没有类型约束,如图jsonObject反序列化出来的类型为LinkedHashMap,如果有类型约束需求,则需要给不同的类型定义不同的TypeHandle。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/爱喝兽奶帝天荒/article/detail/870351
推荐阅读
相关标签
  

闽ICP备14008679号