post入参问题

问题描述:在使用@PostMapping注解时,导致入参错误的问题,代码如下

1
2
3
4
@PostMapping(value = "xxx")
public Result<Void> xxx(Long id) throws Exception {
// TODO
}

问题解析:如果不指定接收类型,会从Content-Type中的x-www-form-urlencoded中接收值,使用@RequestBody注解指定后,会从请求体raw中进行取值,但Long类型(前端传的是json串,类型不匹配)无法进行反序列化(错误如下)所以在接收的时候建议使用get的方式进行请求

org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize instance of java.lang.Long out of START_OBJECT token; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of java.lang.Long out of START_OBJECT token

备注:@RequestParam用来接收Content-Type的x-www-form-urlencoded类型,相当于url中拼接参数值
@RequestBody用来接收Content-Type的请求体raw(一般指定application/json)可以为list,map,自定义对象等

jpa映射对象的问题

很多情况下表对应的实体类并不能解决实际的业务问题,这时候就需要单独建立一个模型对象来取自己需要的字段值,使用原生sql来查询所需要的字段并且映射到自定义对象上就显得十分重要,在策略项目中基本是按照继承的方法或者自定义原生sql来返回需要的结果

如何利用jpa查询的结果来转化为自定义对象?

通常的做法有这么几种

  • 按照各个实体类查出来拼到一个对象里
    存在的问题:两三张表还好说,多了的话代码污染了属于是,不是一个一劳永逸的方法
  • 查询结果用map接收
    存在的问题:虽然可通过map的隐式转化转为自定义对象,但实际进行了两次强转,可能存在隐患(ClassCastException警告),而且集合不指定泛型代码可读性也不强,也不符合编码规范
  • 使用jpql
    这个是JPA的特有语法。之前一直用的mybaits,可采用配置的方式解决,JPA给我整不会了,查阅资料后并进行了使用。JPA使用面向对象的语法可以让查询的结果直接注入到自定义对象中,之前还吐槽jpa种种槽点。。现在啥也不说了JPA牛逼!但存在的问题也显而易见了,有学习成本,sql是程序员必备技能,但jpql不是。

    总结

    也许还有另外或者更好的方法,可见技术广度还是很重要的,它决定了在遇到问题的时候会有几种思路,从而选择一个最优解。

案例对比

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Query(value = "SELECT\n" +
"obc.id AS 'categoryId'," +
"obc.cate_id AS 'cateId'," +
"obc.category," +
"obc.category_alias AS 'categoryAlias'," +
"ocb.id AS 'competeId'," +
"ocb.rival_brand_id AS 'rivalBrandId'," +
"ocb.rival_brand AS 'rivalBrand'," +
"ocb.rival_brand_alias AS 'rivalBrandAlias'\n" +
"FROM overall_brand_category obc\n" +
"LEFT JOIN overall_brand_category_mapping obcm on obcm.category_id = obc.id\n" +
"LEFT JOIN overall_compete_brand ocb on obcm.compete_brand_id = ocb.id\n" +
"WHERE obc.brand_id = :brandId\n" +
"AND obc.data_source = 'STRATEGY'\n" +
"AND obc.enable = TRUE\n" +
"AND ocb.enable = TRUE'\n" +
"ORDER BY obc.cate_id,ocb.rival_brand_id",
nativeQuery = true)
1
2
3
4
5
6
7
8
9
10
@Query(value = "SELECT new com.xinluex.unii.insight.backend.domain.entity.overall.dto.OverallCategoryCompeteDTO" +
"(obc.id,obc.cateId,obc.category,obc.categoryAlias,ocb.id,ocb.rivalBrandId,ocb.rivalBrand,ocb.rivalBrandAlias)\n" +
"FROM OverallBrandCategory obc\n" +
"LEFT JOIN OverallBrandCategoryMappping obcm ON obcm.categoryId = obc.id\n" +
"LEFT JOIN OverallCompeteBrand ocb ON obcm.competeBrandId = ocb.id\n" +
"WHERE obc.brandId = :brandId\n" +
"AND obc.dataSource = 'STRATEGY'\n" +
"AND obc.enable = TRUE\n" +
"AND ocb.enable = TRUE\n" +
"ORDER BY obc.cateId,ocb.rivalBrandId")

JPA查询缓存的带来的问题

场景描述:JPA自带的方法有一个findAll(),它可以查询该表的所有数据,在开发中用findAll()查出的结果,将该结果属性改变后,重新在调用findAll()查询的结果为改变后的,也就是说不会再次调用数据库中的数据

带来的问题:某些场景需要对查询的对象属性进行更改,但改完之后无法再次查询数据库得到原始数据,这样就需要去讲原来查询的结果拷贝一份,这里的结果通常是一个集合无法通过BeanUtils.copyProperties()的方法来进行拷贝,创建一个集合使用addAll()/putAll()的方法实际上进行的是浅拷贝,修改新集合的对象依旧会对原始数据造成影响,此时就需要一次进行深拷贝。这里就是通过遍历原始集合数据赋值到新集合中,这样如果原始集合嵌套很多,深拷贝也会有一定时间成本。

换一种思路:能不能不用jpa的缓存?我找过了,目前没有什么配置可以把jpa的缓存关闭,尝试使用了flush(),结果把数据库表全更新了,毁灭性打击。还好修改表数据不多,也还好是开发环境,于是就纳闷儿了,我没调用save()也会更新表?这真是离大谱,连忙去网上找资料,一来二去,这属于JPA特性,flush()会将缓存中 的数据推送到数据库,因为在原始数据上进行了修改,所以数据库也会进行修改(反人类),我这个前提是没有开启事务。如果开启事务直接调findAll()会直接更新,事务在每次查询数据库的时候先将缓存中的数据进行推送,确保查询的数据是最新的(此处口吐芬芳)

处理方式:在不开启事务的前提下,查询一次findAll()先使用原始数据调用业务,在用处理过的数据调用业务。(原来是反过来的,相当于调用了两次findAll()在没进行深拷贝的前提下会带来隐患)

如何消除缓存数据的影响:实际业务中想做到多次使用查出的一个结果集,可以通过序列化,反序列化的方式进行解决,代码示例如下

1
objectMapper.readValue(objectMapper.writeValueAsString(结果集), new TypeReference<希望转化的类型>() {});

mvn install报错

报错详情

1
[ERROR] No goals have been specified for this build. You must specify a valid lifecycle phase or a goal in the format <plugin-prefix>:<goal> or <plugin-group-id>:<plugin-artifact-id>[:<plugin-version>]:<goal>. Available lifecycle phases are: validate, initialize, generate-sources, process-sources, generate-resources, process-resources, compile, process-classes, generate-test-sources, process-test-sources, generate-test-resources, process-test-resources, test-compile, process-test-classes, test, prepare-package, package, pre-integration-test, integration-test, post-integration-test, verify, install, deploy, pre-clean, clean, post-clean, pre-site, site, post-site, site-deploy. -> [Help 1]

该错误无法通过mvn命令进行打包安装打tag等一系列操作

目前在终端未得到解决,本质原因是依赖有公司私服包拉不下来,可以使用idea的maven功能,可以暂时的替代终端

set无法去重的问题

image-20220429110004617

解决方案:前端也是无法去重,过一天之后发现又可以了,之前试了很多方法