search
HomeJavajavaTutorialHow to solve the problem of precision loss after the primary key ID of SpringBoot snowflake algorithm is transmitted to the front end

Problem description

Range of Java backend Long type

  • ##-2^63~2^63, that is: -9223372036854775808~ 9223372036854775807, which is the 19th digit of

    .

  • This number can be obtained through the methods: Long.MAX_VALUE, Long_MIN_VALUE.
The range of numeric types in front-end JS

##-2^53~2^53, that is: -9007199254740991 ~9007199254740991, it is
    16 bits
  • .

    This number can be obtained through the methods: Number.MAX_SAFE_INTEGER, Number.MIN_SAFE_INTEGER.
  • Conclusion

It can be seen that the Long width of the Java backend is larger than that of the front end. The snowflake algorithm generally generates numbers with a width of 18 or 19 bits, so problems will occur at this time.

Project scenario

1. Table structure

The primary key type is BIGINT, which stores the ID generated by the snowflake algorithm.

CREATE TABLE `user` (
  `id` BIGINT(32) NOT NULL COMMENT '用户id',
	...
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';

2.Entity

Use the Long type to correspond to the BIGINT type of the database ID.

The snowflake algorithm of MybatisPlus is used here to automatically generate a 19-digit pure number as the primary key ID. (Of course, you can also manually generate the ID using the snowflake algorithm)

import lombok.Data;
 
@Data
public class User {
    @TableId(type = IdType.ASSIGN_ID)
    private Long id;
	
    //其他成员
}

3. Respond to the front end

Response to the front end with JSON data is normal

{
  "id": 1352166380631257089,
   ...
}

Problem Description

Instance

Controller

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;
    }
}

Entity

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

Test

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

Result

Problem RecurrenceHow to solve the problem of precision loss after the primary key ID of SpringBoot snowflake algorithm is transmitted to the front end

As you can see from the above, there is no problem.

Why is there no problem?

The front end is passed to the back end: SpingMVC will automatically convert the String type ID to the Long type, and there will be no problem. The back end responds to the front end: it is in JSON format, has nothing to do with JS, and there will be no problem. Question

When will something go wrong?

After the front end receives the JSON, it serializes it into a JS object and then performs other operations. There will be problems when converting JSON to JS objects, as follows:

As you can see, the original id is 1352213368413982722, and after being serialized into a JS object, it becomes 1352213368413982700How to solve the problem of precision loss after the primary key ID of SpringBoot snowflake algorithm is transmitted to the front end

The code is:

const json = '{"id": 1352213368413982722, "name": "Tony"}';
const obj = JSON.parse(json);
 
console.log(obj.id);
console.log(obj.name);

Solution

There are two solutions as follows

Change the id field of the database table design from Long type to String type.
  • The front end uses the String type to save the ID to maintain accuracy, and the back end and database continue to use the Long (BigINT) type
  • Option 1 uses the String type When doing database ID, query performance will drop significantly. So option 2 should be adopted. This article introduces option 2.
Method 1: Global processing

Introduction

Customize ObjectMapper.

Option 1: ToStringSerializer (recommended)

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;
    }
}

Test

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

Option 2: Custom serializer (not recommended)How to solve the problem of precision loss after the primary key ID of SpringBoot snowflake algorithm is transmitted to the front end

Serializer

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());
		}
	}
}

ObjectMapper configuration

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;
    }
}

Test

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

Method 2: Local processingHow to solve the problem of precision loss after the primary key ID of SpringBoot snowflake algorithm is transmitted to the front end

Instructions

Add: @JsonSerialize(using= ToStringSerializer.class) to the field.

Example

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;
}
Test

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

The above is the detailed content of How to solve the problem of precision loss after the primary key ID of SpringBoot snowflake algorithm is transmitted to the front end. For more information, please follow other related articles on the PHP Chinese website!

Statement
This article is reproduced at:亿速云. If there is any infringement, please contact admin@php.cn delete

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Article

R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)
1 months agoBy尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Best Graphic Settings
1 months agoBy尊渡假赌尊渡假赌尊渡假赌
Will R.E.P.O. Have Crossplay?
1 months agoBy尊渡假赌尊渡假赌尊渡假赌

Hot Tools

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser is a secure browser environment for taking online exams securely. This software turns any computer into a secure workstation. It controls access to any utility and prevents students from using unauthorized resources.

WebStorm Mac version

WebStorm Mac version

Useful JavaScript development tools

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

Integrate Eclipse with SAP NetWeaver application server.

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

This project is in the process of being migrated to osdn.net/projects/mingw, you can continue to follow us there. MinGW: A native Windows port of the GNU Compiler Collection (GCC), freely distributable import libraries and header files for building native Windows applications; includes extensions to the MSVC runtime to support C99 functionality. All MinGW software can run on 64-bit Windows platforms.

Atom editor mac version download

Atom editor mac version download

The most popular open source editor