如何将映射<字符串、列表<Integer>>从 JSON 映射到 JPA?



我已经尝试了许多不同的解决方案,但没有任何作用。这是我现在拥有的:

我的数据看起来像这样的播放器:

{
"id": 1,
"name": "Stalker",
"type": "dark",
"faction": 3,
"weaponAbilities": {
"normal": [
  5,
  1,
  0
],
"dark": [
  4,
  2,
  8
]}
}

我正在尝试映射能力。

这是我的代码:

@Data
@Entity
@Table(name = "player")
@EntityListeners(AuditingEntityListener.class)
public class Player {  
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    Long id;
    @OneToMany
    Map<String, Abilities> weaponAbilities;
}

,然后:

@Data
@Entity
@Table(name = "abilities")
@EntityListeners(AuditingEntityListener.class)
public class Abilities {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    Long id;
    @ElementCollection(targetClass = Integer.class )
    private List<Integer> ability;
}

我遇到的错误:

Caused by: org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize instance of `com.project.myapp.entity.Abilities` out of START_ARRAY token; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `com.project.myapp.entity.Abilities` out of START_ARRAY token
 at [Source: (PushbackInputStream); line: 1, column: 1067708] (through reference chain: java.lang.Object[][911]> com.project.myapp.entity.Player["weaponAbilities"]->java.util.LinkedHashMap["normal"])

首先,错误是JSON,而不是JPA,因此,如果您是指解决此问题,然后重新安排它。

我在这里回答如何映射JPA中的类,以便能够坚持这种类型的字段。由于您尚未定义如何在数据库中坚持这些信息,因此您可以做到这一点,而无需包含List<Integer>的人工实体如下

@Entity
public class Player 
{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    Long id;
    @CollectionTable
    @ElementCollection
    @Convert(attributeName="value",converter=ListIntegerStringConverter.class)
    Map<String, List<Integer>> weaponAbilities;
}

然后,这将将映射字段存储到一个单独的表中,其中键存储在varchar列中,并存储在varchar列中的值。如果需要以普通的JPA方式,则可以控制这些列的大小。List<Integer>可以存储为逗号分隔,JSON,也可以存储在此值列中。例如,使用逗号分隔

@Converter(autoApply=true)
public class ListIntegerStringConverter implements AttributeConverter<List<Integer>, String>
{
    public String convertToDatabaseColumn(List<Integer> attribute)
    {
        if (attribute == null)
        {
            return null;
        }
        StringBuilder str = new StringBuilder();
        for (Integer val : attribute)
        {
            if (str.length() > 0)
            {
                str.append(",");
            }
            str.append(val);
        }
        return str.toString();
    }
    public List<Integer> convertToEntityAttribute(String dbData)
    {
        if (dbData == null)
        {
            return null;
        }
        List<Integer> list = new ArrayList<>();
        StringTokenizer tokeniser = new StringTokenizer(dbData, ",");
        while (tokeniser.hasMoreTokens())
        {
            list.add(Integer.valueOf(tokeniser.nextToken()));
        }
        return list;
    }
}

,但这完全取决于您对此列表的要求,您是否有大量元素,是否要查询它,等等,这可能会对您是否会影响您是否会影响使用中间实体,或将其执行到单列中(如下所示(。

尝试使用:

private Map<String, List<Integer>> ability;

因为您正在尝试映射:

{
    "normal": [
        5,
        1,
        0
     ]
}

最新更新