【Java】那些踩过的坑

BigDecimal 相等问题

切记,不能根据字面来判断

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class BigDecimalTest {
public static void main(String[] args) throws Exception {
String num1 = "0";
String num2 = "0.00";
BigDecimal bd1 = new BigDecimal(num1);
BigDecimal bd2 = new BigDecimal(num2);
boolean result1 = bd1.equals(bd2);
boolean result2 = bd1.compareTo(bd2) == 0;
System.out.println("result1:" + result1);
System.out.println("result2:" + result2);
}
}
/*
* output:
* result1:false
* result2:true
*///~

gson 不能正确解析双花括号语法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
public class cronTest {
private static long count;

public static void main(String[] args) {

ArrayList<Item> items = getItemsWithDoubleBrackets();
System.out.println("getItemsWithDoubleBrackets:");
System.out.println(items);
System.out.println(new Gson().toJson(items));

System.out.println();

System.out.println("getItemsNormalWay:");
items = getItemsNormalWay();
System.out.println(items);
System.out.println(new Gson().toJson(items));
}

@NonNull
private static ArrayList<Item> getItemsWithDoubleBrackets() {
count = 0;
ArrayList<Item> items = new ArrayList<>();
for (int i = 0; i < 3; i++) {
items.add(new Item() {{ // double brackets
setContent("美好的一天" + count++);
}});
}
return items;
}

@NonNull
private static ArrayList<Item> getItemsNormalWay() {
count = 0;
ArrayList<Item> items = new ArrayList<>();
for (int i = 0; i < 3; i++) {
Item item = new Item();
item.setContent("美好的一天" + count++);
items.add(item);
}
return items;
}

static class Item {

private String content;

public void setContent(String content) {
this.content = content;
}

@Override
public String toString() {
return "{" +
"content='" + content + '\'' +
'}';
}
}
} /*
getItemsWithDoubleBrackets:
[{content='美好的一天0'}, {content='美好的一天1'}, {content='美好的一天2'}]
[null,null,null]

getItemsNormalWay:
[{content='美好的一天0'}, {content='美好的一天1'}, {content='美好的一天2'}]
[{"content":"美好的一天0"},{"content":"美好的一天1"},{"content":"美好的一天2"}]
*///~

原因是:添加的时候是匿名内部类,此匿名内部类不符合 gson 序列化规则,所以会是 null

image-20210809152411331image-20210809153711267

Gson doesn’t deserialise Long numbers correctly

RecordUtils.toRecord(proxyStocksOrders),让 flow_id 变成了重复的了,解决办法是用 Record 来逐个写;
如,ProxyDaoImpl.lock()方法里的 save() 方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
class RecordUtils {

/**
* 实体类转record
*/
public static Record toRecord(Object data) {

if (data == null) {
return null;
}

@SuppressWarnings("unchecked")
Map<String, Object> json = new Gson().fromJson(
new GsonBuilder()
.setFieldNamingStrategy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
.setDateFormat(CONST.FORMAT)
.create().toJson(data, data.getClass()),
HashMap.class
);
return new Record().setColumns(json);
}
}
class Main{
public static void main(String[] args) {
List<Record> records = new ArrayList<>();
List<Order> orders = new ArrayList<>();
for (int i = 0; i < 10; i++) {
Order order = new Order();
long flowId = Long.parseLong(Common.getPsoFlowId());
order.setFlowId(flowId);
order.setName(String.valueOf(flowId));

orders.add(order);
records.add(RecordUtils.toRecord(order));
}
System.out.println("----------");
records.forEach(System.out::println);
System.out.println("----------");
orders.forEach(System.out::println);
}
}

原因是,gson 将 long 类型的数据做了转换(如:把20200426163033383转换成了2.0200426163033384E16,把20200426163034384 也转换成了 2.0200426163034384E16
有一种解决办法是,对于这种 flow_id 这种类型的字段,用 string 类型,而不是 long 类型。

还有一种办法,添加:LongSerializationPolicy

1
2
3
4
5
6
// https://github.com/google/gson/issues/1084
new GsonBuilder()
.setFieldNamingStrategy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
.setDateFormat(CONST.FORMAT)
.setLongSerializationPolicy(LongSerializationPolicy.STRING) // add this line
.create().toJson(data, data.getClass()),

mybatis 语句拼接问题

1
2
3
4
5
6
7
8
9
/**
* 从 provider_marketable_goods 表中删除数据
*
* @param providerIds 拼接的 providerId
*/
@Update("<script>" +
"delete from goods where provider_id in (#{providerIds})" +
"</script>")
void removeGoodsByProviderId(@Param("providerIds") String providerIds);

实际的运行 sql 语句是: delete from goods where provider_id in (‘23,432,4432,4432’)

下面这个才是你想要的:

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
* 从 provider_marketable_goods 表中删除数据
*
* @param providerIds 拼接的 providerId
*/
@Update("<script>" +
"delete from goods where provider_id in (" +
"<foreach collection='providerIds' item='providerId' separator=','>" +
"#{providerId}" +
"</foreach>" +
")" +
"</script>")
void removeGoodsByProviderId(@Param("providerIds") Set<Long> providerIds);

实际的运行 sql 语句是: delete from goods where provider_id in (23,432,4432,4432)

作用域问题

搞错作用域,会导致获取的数据莫名其妙。
例如下面,本该放在循环内的,结果放在了循环之内(这种 bug 比较难找,要小心才是)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
private void divideToHandleProviderIdToGoodsIdListMap(Consumer<Map<Long, List<Integer>>> consumer) {

Map<Long, List<Integer>> map = Maps.newHashMap(); // outside the loop
final int number = 100;
int count = 0;
List<ProviderGoods> list;
do {
list = providerMarketableDao.getProviderGoodsFromGoods(count * number, number);
list.stream().collect(Collectors.groupingBy(ProviderGoods::getProviderId))
.forEach((providerId, providerGoodsList) -> {
map.put(providerId, providerGoodsList.stream()
.map(ProviderGoods::getGoodsId)
.collect(Collectors.toList()));
});
consumer.accept(map);
count++;
} while (isNotEmptyList(list));
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
private void divideToHandleProviderIdToGoodsIdListMap(Consumer<Map<Long, List<Integer>>> consumer) {

final int number = 100;
int count = 0;
List<ProviderGoods> list;
do {
Map<Long, List<Integer>> map = Maps.newHashMap(); // within the loop
list = providerMarketableDao.getProviderGoodsFromGoods(count * number, number);
list.stream().collect(Collectors.groupingBy(ProviderGoods::getProviderId))
.forEach((providerId, providerGoodsList) -> {
map.put(providerId, providerGoodsList.stream()
.map(ProviderGoods::getGoodsId)
.collect(Collectors.toList()));
});
consumer.accept(map);
count++;
} while (isNotEmptyList(list));
}