用到 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 版权协议,转载请附上原文出处链接和本声明。