Rumah > Java > javaTutorial > Bagaimana untuk menyelesaikan masalah kehilangan ketepatan selepas ID kunci utama algoritma kepingan salji SpringBoot dihantar ke hujung hadapan

Bagaimana untuk menyelesaikan masalah kehilangan ketepatan selepas ID kunci utama algoritma kepingan salji SpringBoot dihantar ke hujung hadapan

PHPz
Lepaskan: 2023-05-11 12:34:18
ke hadapan
2870 orang telah melayarinya

Penerangan masalah

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.

Senario projek

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='用户表';
Salin selepas log masuk

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;
	
    //其他成员
}
Salin selepas log masuk

3 Balas ke hujung hadapan

Balas ke hujung hadapan dengan data JSON. biasanya

{
  "id": 1352166380631257089,
   ...
}
Salin selepas log masuk

Penerangan Masalah

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;
    }
}
Salin selepas log masuk

Entiti

package com.knife.entity;
 
import lombok.Data;
 
@Data
public class UserVO {
    private Long id;
 
    private String username;
}
Salin selepas log masuk

Ujian

Lawati: http: //localhost:8080/user/find ?id=1352213368413982722

Hasil

Bagaimana untuk menyelesaikan masalah kehilangan ketepatan selepas ID kunci utama algoritma kepingan salji SpringBoot dihantar ke hujung hadapan

Penghasilan Semula Masalah

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:

Bagaimana untuk menyelesaikan masalah kehilangan ketepatan selepas ID kunci utama algoritma kepingan salji SpringBoot dihantar ke hujung hadapan

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);
Salin selepas log masuk

Penyelesaian

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.

Kaedah 1: Pemprosesan global

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;
    }
}
Salin selepas log masuk

Ujian

Lawati: http://localhost:8080/user/find?id=1352213368413982722

<🎜

Bagaimana untuk menyelesaikan masalah kehilangan ketepatan selepas ID kunci utama algoritma kepingan salji SpringBoot dihantar ke hujung hadapan

Pilihan 2: Pengsiri tersuai (tidak disyorkan)

Pensiri

package 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());
		}
	}
}
Salin selepas log masuk

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;
    }
}
Salin selepas log masuk

Ujian

Lawati: http://localhost:8080/user/find?id=1352213368413982722

Bagaimana untuk menyelesaikan masalah kehilangan ketepatan selepas ID kunci utama algoritma kepingan salji SpringBoot dihantar ke hujung hadapan

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;
}
Salin selepas log masuk
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!

Label berkaitan:
sumber:yisu.com
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan