【问题标题】:Unable to Save Objectify entity with Map<string,Object> in Embedded classes?无法在嵌入式类中使用 Map<string,Object> 保存 Objectify 实体?
【发布时间】:2020-08-11 15:38:56
【问题描述】:

我有一个嵌入实体,它的字段类型为 Map

地图的所有键都是字符串类型。

下面是实体

@Entity
@Index
@Getter @Setter
public class NiftySurveys {
    @Id
    private Long id;
    private List<SurveyQuestions> questions;
    private Long createddate;
    private Long updatedDate;
}

@Getter @Setter
public class SurveyQuestions {
    private String label;
    private String code;
    private SurveyQuestionGroups questionGroup;
    private Map<String,Object> optionGroup;
}

我无法使用 optionGroup 保存实体。

从前端提交的示例实体

{
    "questions": [{
        "label": "jio",
        "code": null,
        "questionGroup": {
            "name": "Date Time",
            "value": "DATI"
        },
        "optionGroup": {
            "labels": [{
                "label": "Date / Time"
            }],
            "collectDateInfo": true,
            "collectTimeInfo": true,
            "dateFormat": "MM/DD/YYYY",
            "validationMessage": "Please Enter a Valid Date!"
        }
    }, {
        "code": null,
        "label": "Q2",
        "questionGroup": {
            "name": "Multiple Choice Questions",
            "value": "MCQ"
        },
        "optionGroup": {
            "name": "Agree - Disagree",
            "code": "AGDAG",
            "options": [{
                "label": "YES",
                "value": "Y"
            }, {
                "label": "NO",
                "value": "N"
            }]
        }
    }]
}

地图的所有键都是字符串。

错误信息:

exception: "com.googlecode.objectify.SaveException"
message: "Error saving com.nifty.niftyfeedbacks.domain.NiftySurveys@4ac88d5e: java.lang.IllegalStateException: Embedded Map keys must be of type String/Enum/Key<?> or field must specify @Stringify"

链接到堆栈跟踪 https://drive.google.com/file/d/1fqpPLiJutWLif5GnrlqLEZ6Wr_PdLdC-/view?usp=sharing

【问题讨论】:

  • 这看起来应该没问题。什么是完整的堆栈跟踪?一般来说,最好在没有 java 序列化的情况下对对象图进行建模,如果可以的话。将来您将无法从 python 或其他语言读取@Serialized 数据。
  • 我已经更新了问题并添加了完整的堆栈跟踪。
  • 看起来地图内部列表中的内部地图导致了问题。你没有提到这是v5还是v6;如果是 v6,它可能使用 v6,我不确定。 Objectify 对 Object 的作用有很大的限制,这是您的地图上限值的类型。 @Serialize 是正确的答案。或者,如果您想要更便携的东西,您可以将原生字段设为私有字符串,并在生命周期方法中将其序列化/反序列化为 JSON。

标签: java google-cloud-datastore objectify


【解决方案1】:

要了解@Stringify 的工作原理,请查看https://github.com/objectify/objectify/wiki/Entities#stringify

In order to use non-String keys with Maps, you may specify the @Stringify annotation:

import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.Id;
import com.googlecode.objectify.annotation.Stringify;
import com.googlecode.objectify.stringifier.Stringifier;

class DateStringifier implements Stringifier<LocalDate> {
    @Override
    public String toString(LocalDate obj) {
        return obj.getString();
    }

    @Override
    public LocalDate fromString(String str) {
        return new LocalDate(str);
    }
}

@Entity
class Car {
    @Id Long id;
    @Stringify(DateStringifier.class)
    Map<LocalDate, ServiceRecord> serviceHistory = new HashMap<>();
}

之前的回复: 错误消息很清楚:您必须提供“字符串方式”来处理您的嵌入式实体。所以你应该在你的嵌入式实体中编写一个toString() 方法,或者酌情使用@Stringify 注释。

它似乎是 JSON,所以你尝试使用 @JsonUnwrapped : @见https://stackoverflow.com/a/10077262/390462

class Item {
    private String title;

    @JsonProperty("date")
    private Date createdAt;

    // How to map this?
    @JsonUnwrapped
    private Author author;
}

您也可以通过一个很好的 JPA 教程来处理嵌入式对象:

  1. https://examples.javacodegeeks.com/enterprise-java/jpa/jpa-embedded-embeddable-example/
  2. https://www.logicbig.com/tutorials/java-ee-tutorial/jpa/embeddable-classes.html
  3. https://www.tutorialspoint.com/ejb/ejb_embeddable_objects.htm

【讨论】:

  • 我用过@stringify,但没有用。它在嵌套映射中失败,即第一个数组中的标签和第二个具有嵌套映射的数组中的选项。
  • 你试过@JsonUnwrapped 吗?是否如您所愿?
  • @Jsonunwrapped 不是必需的 我需要使用名为 question 的 Key 保存问题,并且该错误特定于 >>Objectify
  • 然后阅读:github.com/objectify/objectify/wiki/Entities。响应已更新。
  • 我所有的键都是来自第一个选项组的字符串labels,collectDateInfo,collectTimeInfo,validationMessage,dateFormat 和来自第二个选项组的name,options,code
【解决方案2】:

对复杂的对象图使用@Serialize注解。 From Objectify Docs

这解决了我的问题。

@Getter @Setter
public class SurveyQuestions implements Serializable{
    private static final long serialVersionUID = -6930992373082651231L;
    @Serialize
    private Map<String,Object> optionGroup;
    
    
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-03-01
    • 1970-01-01
    • 2012-10-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-29
    • 2018-12-31
    • 2018-03-22
    相关资源
    最近更新 更多