検索
ホームページJava&#&チュートリアルSpringBootスノーフレークアルゴリズムの主キーIDがフロントエンドに送信された後の精度損失の問題を解決する方法

問題の説明

Java バックエンド Long 型の範囲

  • ##-2^63~2^63、つまり -9223372036854775808~9223372036854775807 、これは

    の 19 桁目です。

  • この数値は、Long.MAX_VALUE、Long_MIN_VALUE メソッドを通じて取得できます。
フロントエンド JS の数値型の範囲

##-2^53~2^53、つまり: -9007199254740991 ~9007199254740991、これは
    16 ビット
  • です。

    この数値は、Number.MAX_SAFE_INTEGER、Number.MIN_SAFE_INTEGER メソッドを通じて取得できます。
  • 結論

Java バックエンドの Long width がフロントエンドの Long width よりも大きいことがわかります。スノーフレーク アルゴリズムは通常、18 ビットまたは 19 ビット幅の数値を生成するため、この時点で問題が発生します。

プロジェクト シナリオ

1. テーブル構造

主キーのタイプは BIGINT で、スノーフレーク アルゴリズムによって生成された ID が格納されます。

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

2.Entity

データベース ID の BIGINT 型に対応するには Long 型を使用します。

ここでは、MybatisPlus のスノーフレーク アルゴリズムを使用して、19 桁の純粋な数値を主キー ID として自動的に生成します。 (もちろん、スノーフレーク アルゴリズムを使用して ID を手動で生成することもできます)

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

3. フロント エンドへの応答

JSON データでフロント エンドへの応答正常です

{
  "id": 1352166380631257089,
   ...
}

問題の説明

インスタンス

コントローラ

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

エンティティ

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

テスト

アクセス: http ://localhost:8080/user/find ?id=1352213368413982722

結果

問題の再発SpringBootスノーフレークアルゴリズムの主キーIDがフロントエンドに送信された後の精度損失の問題を解決する方法

ご覧のとおり、以上であれば問題ありません。

なぜ問題がないのでしょうか?

フロント エンドがバック エンドに渡される: SpingMVC は String 型 ID を Long 型に自動的に変換しますので、問題はありません。バック エンドはフロント エンドに応答します。 JSON 形式なので、JS とは関係がなく、問題ありません。

フロントエンドは JSON を受信した後、それを JS オブジェクトにシリアル化し、他の操作を実行します。 JSON を JS オブジェクトに変換するときに、次のような問題が発生します。

ご覧のとおり、元の ID は 1352213368413982722 で、JS オブジェクトにシリアル化された後、 1352213368413982700

になります。

コードは次のとおりです。

const json = '{"id": 1352213368413982722, "name": "Tony"}';
const obj = JSON.parse(json);
 
console.log(obj.id);
console.log(obj.name);
SpringBootスノーフレークアルゴリズムの主キーIDがフロントエンドに送信された後の精度損失の問題を解決する方法解決策

次の 2 つの解決策があります。

ID フィールドを変更します。データベースのテーブル設計をLong型からString型へ。

#フロントエンドは精度を維持するために String 型を使用して ID を保存し、バックエンドとデータベースは引き続き Long (BigINT) 型を使用します
  • オプション 1 では String 型を使用します。データベース ID を実行すると、クエリのパフォーマンスが大幅に低下します。したがって、オプション 2 を採用する必要があります。この記事ではオプション 2 を紹介します。
  • 方法 1: グローバル処理

  • はじめに

ObjectMapper をカスタマイズします。

オプション 1: ToStringSerializer (推奨)

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;
    }
}
テスト

アクセス: http://localhost:8080/user/find?id=1352213368413982722

オプション 2: カスタム シリアライザー (非推奨)

シリアライザー

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 構成SpringBootスノーフレークアルゴリズムの主キーIDがフロントエンドに送信された後の精度損失の問題を解決する方法

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

テスト

次を参照してください。 http://localhost:8080/user/find?id=1352213368413982722

方法 2: ローカル処理

手順

SpringBootスノーフレークアルゴリズムの主キーIDがフロントエンドに送信された後の精度損失の問題を解決する方法

@JsonSerialize(using= ToStringSerializer.class) をフィールドに追加します。

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

テスト

アクセス: http://localhost:8080/user/find?id=1352213368413982722

以上がSpringBootスノーフレークアルゴリズムの主キーIDがフロントエンドに送信された後の精度損失の問題を解決する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明
この記事は亿速云で複製されています。侵害がある場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

Dreamweaver Mac版

Dreamweaver Mac版

ビジュアル Web 開発ツール

PhpStorm Mac バージョン

PhpStorm Mac バージョン

最新(2018.2.1)のプロフェッショナル向けPHP統合開発ツール

MantisBT

MantisBT

Mantis は、製品の欠陥追跡を支援するために設計された、導入が簡単な Web ベースの欠陥追跡ツールです。 PHP、MySQL、Web サーバーが必要です。デモおよびホスティング サービスをチェックしてください。

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

Eclipse を SAP NetWeaver アプリケーション サーバーと統合します。

WebStorm Mac版

WebStorm Mac版

便利なJavaScript開発ツール