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

SpringBoot项目中使用JPA存储自定义类列表失败求助

解决SpringBoot JPA存储自定义类列表到数据库的问题

问题根源

你代码里的核心错误是同时使用了@OneToMany和@Column注解:

  • @OneToMany是用来定义一对多的实体关联关系,这种关系需要单独的关联表(或在多端实体中添加外键),不是把列表存在单个字段里。
  • 两种注解混用导致JPA生成的DDL语句逻辑混乱,最终触发JDBC语法错误。

解决方案分两种场景

场景1:用一对多关联关系(符合关系型数据库设计规范)

如果Authors是独立实体(需要单独建表),按以下方式修改代码:

  1. Books实体类:移除@Column,指定关联的反向字段
@Entity
public class Books {
    @Id
    private Long isbn;
    private String title;
    private Float price;
    private Integer year;
    private String genre;

    // mappedBy指向Authors类中关联Books的字段名
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "book")
    private List<Authors> authors = new ArrayList<>();

    // getter、setter方法
}
  1. Authors实体类:添加多对一关联,指定外键
@Entity
public class Authors {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String email;

    // 多对一关联Books,外键存储在authors表中
    @ManyToOne
    @JoinColumn(name = "book_isbn")
    private Books book;

    // getter、setter方法
}

修改后JPA会自动生成authors表,通过book_isbn外键与books表关联,完全符合关系型数据库的设计逻辑。

场景2:将列表作为JSON字段存储到books表

如果不想单独建authors表,可将列表序列化为JSON字符串存在单个字段中:

方式1:自定义转换器(兼容Spring Boot 2+)
  1. 创建JSON转换类
import jakarta.persistence.AttributeConverter;
import jakarta.persistence.Converter;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.List;

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

    @Override
    public String convertToDatabaseColumn(List<Authors> authors) {
        try {
            return objectMapper.writeValueAsString(authors);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("序列化作者列表失败", e);
        }
    }

    @Override
    public List<Authors> convertToEntityAttribute(String dbData) {
        try {
            return objectMapper.readValue(dbData, 
                objectMapper.getTypeFactory().constructCollectionType(List.class, Authors.class));
        } catch (JsonProcessingException e) {
            throw new RuntimeException("反序列化作者列表失败", e);
        }
    }
}
  1. 在Books实体中使用转换器
@Entity
public class Books {
    @Id
    private Long isbn;
    private String title;
    private Float price;
    private Integer year;
    private String genre;

    @Column(name = "authors", columnDefinition = "TEXT")
    @Convert(converter = AuthorsListConverter.class)
    private List<Authors> authors = new ArrayList<>();

    // getter、setter方法
}
方式2:使用Spring Boot 3+原生注解

无需自定义转换器,直接用Hibernate的注解实现JSON转换:

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import org.hibernate.annotations.JdbcTypeCode;
import org.hibernate.type.SqlTypes;
import java.util.ArrayList;
import java.util.List;

@Entity
public class Books {
    @Id
    private Long isbn;
    private String title;
    private Float price;
    private Integer year;
    private String genre;

    @Column(name = "authors", columnDefinition = "JSON")
    @JdbcTypeCode(SqlTypes.JSON)
    private List<Authors> authors = new ArrayList<>();

    // getter、setter方法
}

注意:这种方式要求数据库支持JSON类型(如MySQL 5.7+、PostgreSQL等),且Authors类需有默认构造函数和字段的getter/setter。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.06 14:12:02