用到 mybatis-plus时,

字段类型处理器

类型处理器,用于 JavaType 与 JdbcType 之间的转换,用于 PreparedStatement 设置参数值和从 ResultSet 或 CallableStatement 中取出一个值,本文讲解 mybaits-plus 内置常用类型处理器如何通过TableField注解快速注入到 mybatis 容器中。

按照理解,其实就是一个帮助我们保存和查询时把对应的对象转换为json格式的数据,

pojo层添加字段类型,对应oracle数据类型为varchar2(1000)

    /**
     * 注意!! 必须开启映射注解
     *
     * @TableName(autoResultMap = true)
     *
     * 以下两种类型处理器,二选一 也可以同时存在
     *
     * 注意!!选择对应的 JSON 处理器也必须存在对应依赖包
     */
    @TableField(typeHandler = JacksonTypeHandler.class)
    private Wallet wallet; 

    @TableField(typeHandler = FastjsonTypeHandler.class)
    private OtherInfo otherInfo;
/**
 * 钱包
 */
@Data
@AllArgsConstructor
public class Wallet {
    /**
     * 名称
     */
    private String name;
    /**
     * 各种货币
     */
    private List<Currency> currencyList;
}
/**
 * 货币
 */
@Data
public class Currency {
    /**
     * 类型: 人民币 RMB , 美元 USD
     */
    private String type;
    /**
     * 金额
     */
    private Double amount;
}

 

/**
 * 其他信息
 */
@Data
public class OtherInfo {
    /**
     * 性别
     */
    private String sex;
    /**
     * 居住城市
     */
    private String city;
}

声明转换类

@Component
public class MpJsonConfig implements CommandLineRunner {

    /**
     * 可以set进去自己的
     */
    @Override
    public void run(String... args) throws Exception {
        JacksonTypeHandler.setObjectMapper(new ObjectMapper());
        GsonTypeHandler.setGson(new Gson());
    }
}

单元测试发现保存时转换json正常,但是查询时,这两个json字段都是null,

@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoJsonTest {
	
	 @Autowired
	 private DemoMapper demoMapper;
	 
	 /**
	  *  Execute SQL:INSERT INTO DEMO ( id, NAME, SCHOOL, operator, wallet, other_info, cost, create_time )
	  *   VALUES ( 'c776708a100753b5529362ef1d2fc6fb', '222', '剑桥假sss的', 'Jetty', 
	  *   '{"name":"我的钱包","currencyList":[{"type":"doller","amount":500.0},{"type":"renminbi","amount":1000.0},
	  *   {"type":"riyuan","amount":300.0}]}', '{"city":"南京","sex":"nan"}',
	  *    444.55000000000001136868377216160297393798828125, '2020-12-07T23:06:01.738+0800' )
	  */
//    @Test
    public void saveTest() {
    	Demo demo = new Demo();
    	demo.setName("222"); 
    	demo.setSchool("剑桥假sss的");   
    	
    	List list = new ArrayList<Currency>();
    	Currency curr1 = new Currency();
    	curr1.setType("doller");
    	curr1.setAmount(500.00);
    	list.add(curr1);
    	
    	Currency curr2 = new Currency();
    	curr2.setType("renminbi");
    	curr2.setAmount(1000.00);
    	list.add(curr2);
    	
    	Currency curr3 = new Currency();
    	curr3.setType("riyuan");
    	curr3.setAmount(300.00);
    	list.add(curr3);
    	Wallet wallet = new Wallet("我的钱包", list);
    	demo.setWallet(wallet);
    	
    	OtherInfo other = new OtherInfo();
    	other.setCity("南京");
    	other.setSex("nan");
    	demo.setOtherInfo(other);
    	
    	demoMapper.insert(demo);
    } 
	 
	 @Test
	public void selectJson()
	{
		// 先查询
		Demo demo = demoMapper.selectById("fc40b691903659a449e3b6d7fe42bfe2");
//		List<Demo> list = demoMapper.selectList(null);
//		Demo demo = list.get(0);
		System.err.println(demo.getWallet().getName());
		System.err.println(demo.getOtherInfo().getCity());
	}

问题是在pojo类上面添加  @TableName(autoResultMap = true)  

@Data
@EqualsAndHashCode(callSuper = false)
//@TableName("DEMO")
@TableName(autoResultMap = true)   //开启映射注解,才可以查询时转换json
//@Accessors(chain = true)
//public class Demo implements Serializable {
public class Demo extends BaseEntity {

不过查询回来转换会有异常,

Caused by: java.lang.RuntimeException: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `cn.com.git.batch.entity.typehandler.Wallet` (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
 at [Source: (String)"{"name":"我的钱包","currencyList":[{"type":"doller","amount":500.0},{"type":"renminbi","amount":1000.0},{"type":"riyuan","amount":300.0}]}"; line: 1, column: 2]
	at com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler.parse(JacksonTypeHandler.java:54)
	at com.baomidou.mybatisplus.extension.handlers.AbstractJsonTypeHandler.getNullableResult(AbstractJsonTypeHandler.java:41)
	at org.apache.ibatis.type.BaseTypeHandler.getResult(BaseTypeHandler.java:85)
	... 74 more
Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `cn.com.git.batch.entity.typehandler.Wallet` (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
 at [Source: (String)"{"name":"我的钱包","currencyList":[{"type":"doller","amount":500.0},{"type":"renminbi","amount":1000.0},{"type":"riyuan","amount":300.0}]}"; line: 1, column: 2]
	at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67)
	at com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1615)
	at com.fasterxml.jackson.databind.DatabindContext.reportBadDefinition(DatabindContext.java:400)
	at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1077)
	at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1332)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:331)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:164)
	at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4526)
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3468)
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3436)
	at com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler.parse(JacksonTypeHandler.java:52)
	... 76 more

查了下,是需要 默认构造函数,

解决方案

给数据类增加默认构造函数
constructor() : this(ObjectId.get().toString(), "", null, null)
这种情况出现在反序列化对象的嵌套对象没有默认构造函数时.

但是我不太想写,改成使用FastjsonTypeHandler解析,查询解析正常。

//    @TableField(typeHandler = JacksonTypeHandler.class)
    @TableField(typeHandler = FastjsonTypeHandler.class) 
    private Wallet wallet; 

    @TableField(typeHandler = FastjsonTypeHandler.class)
    private OtherInfo otherInfo;

 


版权声明:本文为xiaxiaorui2003原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/xiaxiaorui2003/article/details/110851903