Firebase 字段名自动添加下划线前缀的解决方案

发布时间 - 2026-01-21 00:00:00    点击率:

firebase sdk 基于 javabean 规范解析 getter/setter 方法名,将 `get_location_name()` 误判为 `_location_name` 属性的访问器,导致写入 firestore 或 realtime database 时字段名自动带

`_` 前缀;正确做法是遵循驼峰命名(如 `getlocationname()`)或显式使用 `@propertyname` 注解指定字段名。

Firebase 在序列化 Java 对象(如 PoIs 类)到数据库时,并不直接读取私有字段名,而是依赖 JavaBean 标准命名约定:它通过反射扫描 public getter 方法(如 getXxx()),并根据方法名推断对应的数据字段名。关键规则如下:

  • 方法 getXxx() → 推断字段名为 xxx(首字母小写,去除 get 前缀)
  • 方法 get_xxx() → 下划线被视为单词分隔符,推断字段名为 _xxx(即保留开头下划线)
  • 同理,is_xxx()、set_xxx(...) 等也会被识别为 _xxx 属性

在你的代码中:

public Integer get_location_id() { ... }
public String get_location_name() { ... }

Firebase 将其解析为属性 _location_id 和 _location_name,因此最终写入数据库的键名就变成了 _location_id、 _location_name、_location_address —— 这正是你观察到的现象。

推荐解决方案(二选一)

方案 1:改用标准驼峰命名(最简洁、无侵入)
重命名所有 getter/setter 方法,严格遵循 JavaBean 规范(无下划线,首字母大写):

public class PoIs {
    private Integer locationId;        // 推荐:字段也用驼峰(非强制但最佳实践)
    private String locationName;
    private String locationAddress;

    // 构造函数保持不变(注意:原代码中构造函数有笔误:this.category_id = category_id; —— 应删除或修正)

    public Integer getLocationId() {
        return locationId;
    }

    public void setLocationId(Integer locationId) {
        this.locationId = locationId;
    }

    public String getLocationName() {
        return locationName;
    }

    public void setLocationName(String locationName) {
        this.locationName = locationName;
    }

    public String getLocationAddress() {
        return locationAddress;
    }

    public void setLocationAddress(String locationAddress) {
        this.locationAddress = locationAddress;
    }
}

✅ 写入后字段名将自动变为 locationId、locationName、locationAddress(纯驼峰)。若你希望保持 location_id 这类蛇形命名,请使用方案 2。

方案 2:使用 @PropertyName 显式声明(精准控制,兼容蛇形)
在 getter/setter 或字段上添加注解(需引入 com.google.firebase.firestore.PropertyName):

import com.google.firebase.firestore.PropertyName;

public class PoIs {
    @PropertyName("location_id")
    private Integer location_id;

    @PropertyName("location_name")
    private String location_name;

    @PropertyName("location_address")
    private String location_address;

    // 构造函数(修正原代码中的 category_id 错误)
    public PoIs(Integer location_id, String location_name, String location_address) {
        this.location_id = location_id;
        this.location_name = location_name;
        this.location_address = location_address;
    }

    // getter/setter 可保留原名,但建议同步加注解以确保双向映射一致
    @PropertyName("location_id")
    public Integer get_location_id() { return location_id; }

    @PropertyName("location_id")
    public void set_location_id(Integer location_id) { this.location_id = location_id; }

    // 其他字段同理...
}

⚠️ 注意事项:

  • @PropertyName 注解需同时作用于 getter 和 setter(或字段),否则反序列化(读取)可能失败;
  • 若使用 Firestore,确保类已添加无参构造函数(你已有 public PoIs() {},符合要求);
  • Realtime Database 同样支持 @PropertyName,但仅限 Android SDK v16.0.1+;
  • 原代码构造函数中存在未定义变量 category_id,请务必检查并移除该行,避免编译错误。

? 验证方式:
在 setValue(p) 后,打开 Firebase Console → Realtime Database 或 Firestore 控制台,查看实际写入的 key 名是否已符合预期(如 location_name 而非 _location_name)。

总结:Firebase 的“自动加下划线”本质是 JavaBean 命名推导逻辑的副作用,而非 Bug。统一采用驼峰命名(getLocationName)是最符合生态规范、零配置、长期可维护的选择;而 @PropertyName 则为你保留蛇形命名提供了灵活且可靠的兜底方案。


# java  # android  # go  # google  # 编译错误 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: Laravel如何安装Breeze扩展包_Laravel用户注册登录功能快速实现【流程】  打造顶配客厅影院,这份100寸电视推荐名单请查收  如何在万网自助建站平台快速创建网站?  Laravel如何创建和注册中间件_Laravel中间件编写与应用流程  PHP 实现电台节目表的智能时间匹配与今日/明日轮播逻辑  网站设计制作书签怎么做,怎样将网页添加到书签/主页书签/桌面?  如何在阿里云香港服务器快速搭建网站?  手机钓鱼网站怎么制作视频,怎样拦截钓鱼网站。怎么办?  如何在 Go 中优雅地映射具有动态字段的 JSON 对象到结构体  Laravel如何实现全文搜索功能?(Scout和Algolia示例)  Laravel路由Route怎么设置_Laravel基础路由定义与参数传递规则【详解】  独立制作一个网站多少钱,建立网站需要花多少钱?  如何在Ubuntu系统下快速搭建WordPress个人网站?  千问怎样用提示词获取健康建议_千问健康类提示词注意事项【指南】  Laravel如何实现API资源集合?(Resource Collection教程)  西安市网站制作公司,哪个相亲网站比较好?西安比较好的相亲网站?  详解Android图表 MPAndroidChart折线图  zabbix利用python脚本发送报警邮件的方法  Android仿QQ列表左滑删除操作  高性能网站服务器部署指南:稳定运行与安全配置优化方案  Laravel的.env文件有什么用_Laravel环境变量配置与管理详解  Windows10如何删除恢复分区_Win10 Diskpart命令强制删除分区  微信推文制作网站有哪些,怎么做微信推文,急?  香港服务器建站指南:外贸独立站搭建与跨境电商配置流程  大连 网站制作,大连天途有线官网?  浅谈redis在项目中的应用  装修招标网站设计制作流程,装修招标流程?  EditPlus 正则表达式 实战(3)  Android 常见的图片加载框架详细介绍  如何在IIS中配置站点IP、端口及主机头?  laravel服务容器和依赖注入怎么理解_laravel服务容器与依赖注入解析  Laravel如何使用Gate和Policy进行权限控制_Laravel权限判定与策略规则配置  如何为不同团队 ID 动态生成多个独立按钮  Laravel如何实现密码重置功能_Laravel密码找回与重置流程  再谈Python中的字符串与字符编码(推荐)  Laravel怎么创建自己的包(Package)_Laravel扩展包开发入门到发布  Laravel怎么发送邮件_Laravel Mail类SMTP配置教程  英语简历制作免费网站推荐,如何将简历翻译成英文?  如何在万网利用已有域名快速建站?  HTML透明颜色代码怎么让下拉菜单透明_下拉菜单透明背景指南【技巧】  php结合redis实现高并发下的抢购、秒杀功能的实例  Laravel如何自定义错误页面(404, 500)?(代码示例)  Laravel如何配置和使用缓存?(Redis代码示例)  如何用搬瓦工VPS快速搭建个人网站?  微信小程序 五星评分(包括半颗星评分)实例代码  js实现获取鼠标当前的位置  如何在IIS管理器中快速创建并配置网站?  制作无缝贴图网站有哪些,3dmax无缝贴图怎么调?  网站制作大概要多少钱一个,做一个平台网站大概多少钱?  Laravel Facade的原理是什么_深入理解Laravel门面及其工作机制