Rumah >Java >javaTutorial >Bagaimana untuk menyelesaikan masalah kehilangan ketepatan selepas ID kunci utama algoritma kepingan salji SpringBoot dihantar ke hujung hadapan
Julat hujung belakang Java Jenis panjang
-2^63~2^63, iaitu: -9223372036854775808~ 9223372036854775807, iaitu angka ke-19.
Nombor ini boleh diperolehi melalui kaedah: Long.MAX_VALUE, Long_MIN_VALUE.
Julat jenis angka JS bahagian hadapan
-2^53~2^53, yang ialah: -9007199254740991 ~9007199254740991, iaitu 16 bit.
Nombor ini boleh didapati melalui kaedah: Number.MAX_SAFE_INTEGER, Number.MIN_SAFE_INTEGER.
Kesimpulan
Ia boleh dilihat bahawa lebar Panjang bahagian belakang Java adalah lebih besar daripada bahagian hujung hadapan. Algoritma kepingan salji biasanya menjana nombor dengan lebar 18 atau 19 bit, jadi masalah akan berlaku pada masa ini.
1. Struktur jadual
Jenis kunci utama ialah BIGINT, yang menyimpan ID yang dijana oleh algoritma kepingan salji.
CREATE TABLE `user` ( `id` BIGINT(32) NOT NULL COMMENT '用户id', ... PRIMARY KEY (`id`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
2.Entiti
Gunakan jenis Long untuk sepadan dengan jenis BIGINT ID pangkalan data.
Algoritma kepingan salji MybatisPlus digunakan di sini untuk menjana nombor tulen 19 digit secara automatik sebagai ID kunci utama. (Sudah tentu, anda juga boleh menjana ID secara manual menggunakan algoritma kepingan salji)
import lombok.Data; @Data public class User { @TableId(type = IdType.ASSIGN_ID) private Long id; //其他成员 }
3 Balas ke hujung hadapan
Balas ke hujung hadapan dengan data JSON. biasanya
{ "id": 1352166380631257089, ... }
Instance
Pengawal
package com.knife.controller; import com.knife.entity.UserVO; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("user") public class UserController { @GetMapping("find") public UserVO find(Long id) { UserVO userVO = new UserVO(); userVO.setId(id); userVO.setUsername("Tony"); return userVO; } }
Entiti
package com.knife.entity; import lombok.Data; @Data public class UserVO { private Long id; private String username; }
Ujian
Lawati: http: //localhost:8080/user/find ?id=1352213368413982722
Hasil
Sebagaimana anda boleh lihat dari atas tiada masalah.
Kenapa tiada masalah?
Halaman hadapan dihantar ke hujung belakang: SpingMVC akan menukar ID jenis String secara automatik kepada jenis Panjang, dan tidak akan ada masalah bahagian belakang bertindak balas kepada bahagian hadapan-. akhir: ia dalam format JSON, tiada kaitan dengan JS, dan tidak akan menyebabkan masalah
Bilakah sesuatu akan berlaku?
Selepas bahagian hadapan menerima JSON, ia mensirikannya menjadi objek JS dan kemudian melakukan operasi lain. Akan ada masalah apabila menukar JSON kepada objek JS, seperti berikut:
Seperti yang anda lihat, id asal ialah 1352213368413982722, dan selepas disirikan ke dalam objek JS, ia menjadi 1352213368413982700
Kodnya ialah:
const json = '{"id": 1352213368413982722, "name": "Tony"}'; const obj = JSON.parse(json); console.log(obj.id); console.log(obj.name);
Terdapat dua penyelesaian seperti berikut
medan Tukar id reka bentuk jadual pangkalan data daripada jenis Long kepada jenis String.
Halaman hadapan menggunakan jenis String untuk menyimpan ID untuk mengekalkan ketepatan, dan bahagian belakang dan pangkalan data terus menggunakan jenis Long (BigINT)
Pilihan 1 menggunakan jenis Rentetan Apabila melakukan ID pangkalan data, prestasi pertanyaan akan menurun dengan ketara. Jadi pilihan 2 harus diterima pakai. Artikel ini memperkenalkan pilihan 2.
Pengenalan
Pemeta Objek Tersuai.
Pilihan 1: ToStringSerializer (disyorkan)
package com.knife.config; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; @Configuration public class JacksonConfig { @Bean public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) { ObjectMapper objectMapper = builder.createXmlMapper(false).build(); // 全局配置序列化返回 JSON 处理 SimpleModule simpleModule = new SimpleModule(); // 将使用String来序列化Long类型 simpleModule.addSerializer(Long.class, ToStringSerializer.instance); simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance); objectMapper.registerModule(simpleModule); return objectMapper; } }
Ujian
Lawati: http://localhost:8080/user/find?id=1352213368413982722
Pilihan 2: Pengsiri tersuai (tidak disyorkan)Pensiripackage com.knife.config; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; import com.fasterxml.jackson.databind.ser.std.NumberSerializer; import java.io.IOException; /** * 超出 JS 最大最小值 处理 */ @JacksonStdImpl public class BigNumberSerializer extends NumberSerializer { /** * 根据 JS Number.MAX_SAFE_INTEGER 与 Number.MIN_SAFE_INTEGER 得来 */ private static final long MAX_SAFE_INTEGER = 9007199254740991L; private static final long MIN_SAFE_INTEGER = -9007199254740991L; /** * 提供实例 */ public static final BigNumberSerializer instance = new BigNumberSerializer(Number.class); public BigNumberSerializer(Class<? extends Number> rawType) { super(rawType); } @Override public void serialize(Number value, JsonGenerator gen, SerializerProvider provider) throws IOException { // 超出范围 序列化位字符串 if (value.longValue() > MIN_SAFE_INTEGER && value.longValue() < MAX_SAFE_INTEGER) { super.serialize(value, gen, provider); } else { gen.writeString(value.toString()); } } }Konfigurasi ObjectMapper
package com.knife.config; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; @Configuration public class JacksonConfig { @Bean public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) { ObjectMapper objectMapper = builder.createXmlMapper(false).build(); // 全局配置序列化返回 JSON 处理 SimpleModule simpleModule = new SimpleModule(); // 将使用自定义序列化器来序列化Long类型 simpleModule.addSerializer(Long.class, BigNumberSerializer.instance); simpleModule.addSerializer(Long.TYPE, BigNumberSerializer.instance); objectMapper.registerModule(simpleModule); return objectMapper; } }Ujian
Lawati: http://localhost:8080/user/find?id=1352213368413982722 Kaedah 2: Rawatan setempat
Arahan
Tambah: @JsonSerialize(using= ToStringSerializer.class) pada medan.Instance
package com.knife.entity; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; import lombok.Data; @Data public class UserVO { @JsonSerialize(using= ToStringSerializer.class) private Long id; private String username; }Ujian Lawati: http://localhost:8080/user/find?id=1352213368413982722
Atas ialah kandungan terperinci Bagaimana untuk menyelesaikan masalah kehilangan ketepatan selepas ID kunci utama algoritma kepingan salji SpringBoot dihantar ke hujung hadapan. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!