You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将JSON中的Map<String, List<Integer>>映射到JPA实体?

解决Player实体中weaponAbilities字段的JPA映射问题

看起来你在尝试用JPA映射JSON中的weaponAbilities字段时遇到了麻烦——你当前用的@OneToMany注解并不适合这种嵌套的JSON结构,因为@OneToMany是用来关联独立数据库实体的,而这里的weaponAbilities是Player自身的嵌套属性,属于单个实体的一部分。

下面给你几种可行的解决方案:

方案1:定义DTO类+JSON转换器(推荐,结构更清晰)

这种方法适合需要明确字段结构的场景,先为weaponAbilities定义一个对应的数据传输对象(DTO),再通过转换器实现与数据库JSON类型的映射。

步骤1:定义WeaponAbilities DTO

@Data
public class WeaponAbilities {
    private List<Integer> normal;
    private List<Integer> dark;
    // 后续新增能力类型时,直接添加对应字段即可
}

步骤2:修改Player实体类

结合数据库的JSON类型支持(比如MySQL 5.7+、PostgreSQL),用@Column指定字段类型,再通过自定义转换器完成对象与JSON字符串的互转:

@Data
@Entity
@Table(name = "player")
@EntityListeners(AuditingEntityListener.class)
public class Player {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    Long id;
    
    private String name;
    private String type;
    private Integer faction;
    
    // MySQL环境下的配置
    @Column(columnDefinition = "json")
    @Convert(converter = WeaponAbilitiesConverter.class)
    private WeaponAbilities weaponAbilities;
    
    // 如果是PostgreSQL,也可以用Hibernate的@Type注解(需引入hibernate-types依赖)
    // @Type(type = "jsonb")
    // @Column(columnDefinition = "jsonb")
    // private WeaponAbilities weaponAbilities;
}

步骤3:实现自定义转换器

import jakarta.persistence.AttributeConverter;
import jakarta.persistence.Converter;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

@Converter(autoApply = true)
public class WeaponAbilitiesConverter implements AttributeConverter<WeaponAbilities, String> {
    private final ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public String convertToDatabaseColumn(WeaponAbilities attribute) {
        try {
            return objectMapper.writeValueAsString(attribute);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("转换WeaponAbilities为JSON失败", e);
        }
    }

    @Override
    public WeaponAbilities convertToEntityAttribute(String dbData) {
        try {
            return objectMapper.readValue(dbData, WeaponAbilities.class);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("转换JSON为WeaponAbilities失败", e);
        }
    }
}

方案2:直接映射为Map<String, List>

如果不需要固定的DTO结构,也可以直接用Map类型来接收weaponAbilities的键值对:

修改Player实体类

@Data
@Entity
@Table(name = "player")
@EntityListeners(AuditingEntityListener.class)
public class Player {
    // 其他字段...
    
    @Column(columnDefinition = "json")
    @Convert(converter = WeaponMapConverter.class)
    private Map<String, List<Integer>> weaponAbilities;
}

实现对应的Map转换器

import jakarta.persistence.AttributeConverter;
import jakarta.persistence.Converter;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.List;
import java.util.Map;

@Converter(autoApply = true)
public class WeaponMapConverter implements AttributeConverter<Map<String, List<Integer>>, String> {
    private final ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public String convertToDatabaseColumn(Map<String, List<Integer>> attribute) {
        try {
            return objectMapper.writeValueAsString(attribute);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("转换武器能力Map为JSON失败", e);
        }
    }

    @Override
    public Map<String, List<Integer>> convertToEntityAttribute(String dbData) {
        try {
            return objectMapper.readValue(dbData,
                    objectMapper.getTypeFactory().constructMapType(Map.class, String.class, List.class));
        } catch (JsonProcessingException e) {
            throw new RuntimeException("转换JSON为武器能力Map失败", e);
        }
    }
}

为什么之前的@OneToMany无效?

@OneToMany是用于实体间的关联关系(比如一个Player对应多个独立的Weapon实体),这种场景需要单独创建weapon表,通过外键与player表关联。但你的weaponAbilities是Player的嵌套JSON属性,属于单个实体的一部分,不需要额外的数据库表,所以@OneToMany完全不适用,这也是你之前尝试无效的核心原因。


内容的提问来源于stack exchange,提问作者kmd12

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:34:22