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

如何使用Spring Data读取JSON并写入MySQL数据库?

使用Spring Data将JSON持久化到MySQL的完整步骤

看来你已经有了基础的模型类,接下来咱们一步步把JSON数据存到MySQL里,全程用Spring Data JPA来实现,省心又高效。

1. 完善实体类的JPA映射

首先得给你的三个模型类加上JPA注解,处理好它们之间的一对多关联关系,这样Spring Data才能正确生成数据库表和关联约束。

Portal.java(主实体)

import jakarta.persistence.*;
import java.util.ArrayList;
import java.util.List;

@Entity
public class Portal {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    private String portalName;

    // 一对多关联Spaces,级联操作+孤儿移除
    @OneToMany(mappedBy = "portal", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<Spaces> spaces = new ArrayList<>();

    // 构造方法(空参+带参)、getter/setter
    public Portal() {}

    public Portal(String portalName) {
        this.portalName = portalName;
    }

    // 辅助方法:添加Space时自动绑定关联关系
    public void addSpace(Spaces space) {
        space.setPortal(this);
        this.spaces.add(space);
    }

    // getter和setter省略,自行补全即可
}

Spaces.java(关联Portal和Indicators)

import jakarta.persistence.*;
import java.util.ArrayList;
import java.util.List;

@Entity
public class Spaces {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    private String spaceName;

    // 多对一关联Portal
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "portal_id") // 数据库外键字段名
    private Portal portal;

    // 一对多关联Indicators
    @OneToMany(mappedBy = "space", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<Indicators> indicators = new ArrayList<>();

    // 构造方法、getter/setter
    public Spaces() {}

    public Spaces(String spaceName) {
        this.spaceName = spaceName;
    }

    // 辅助方法:添加Indicator时自动绑定关联关系
    public void addIndicator(Indicators indicator) {
        indicator.setSpace(this);
        this.indicators.add(indicator);
    }

    // getter和setter省略
}

Indicators.java(最底层实体)

import jakarta.persistence.*;

@Entity
public class Indicators {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    private String indicatorName;
    private String indicatorCounter; // 你的JSON里是字符串类型,这里保持一致

    // 多对一关联Spaces
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "space_id")
    private Spaces space;

    // 构造方法、getter/setter
    public Indicators() {}

    public Indicators(String indicatorName, String indicatorCounter) {
        this.indicatorName = indicatorName;
        this.indicatorCounter = indicatorCounter;
    }

    // getter和setter省略
}

2. 创建Spring Data JPA Repository接口

每个实体对应一个Repository,Spring Data会自动实现CRUD方法,不用自己写SQL。

PortalRepository.java

import org.springframework.data.jpa.repository.JpaRepository;

public interface PortalRepository extends JpaRepository<Portal, Long> {
    // 可自定义查询方法,比如根据portalName查找
    Portal findByPortalName(String portalName);
}

同理,你也可以给Spaces和Indicators创建对应的Repository(如果后续需要单独操作它们的话),比如SpacesRepository extends JpaRepository<Spaces, Long>。

3. 配置MySQL数据源

在application.properties(或application.yml)里配置数据库连接信息,确保Spring能连接到你的MySQL实例:

# 数据库连接
spring.datasource.url=jdbc:mysql://localhost:3306/your_db_name?useSSL=false&serverTimezone=UTC&characterEncoding=utf8
spring.datasource.username=your_db_username
spring.datasource.password=your_db_password

# JPA配置
spring.jpa.hibernate.ddl-auto=update # 自动更新表结构,生产环境建议用none或validate
spring.jpa.show-sql=true # 控制台打印SQL,方便调试
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
spring.jpa.properties.hibernate.format_sql=true # 格式化SQL输出

记得把your_db_name、your_db_username、your_db_password换成你自己的数据库信息。

4. 编写JSON解析与持久化服务

用Jackson(Spring Boot默认自带)把JSON字符串解析成实体对象,然后通过Repository保存到数据库。

PortalService.java

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.stereotype.Service;
import java.io.IOException;

@Service
public class PortalService {
    private final PortalRepository portalRepository;
    private final ObjectMapper objectMapper;

    // 构造注入(Spring 4.3+支持无需@Autowired)
    public PortalService(PortalRepository portalRepository, ObjectMapper objectMapper) {
        this.portalRepository = portalRepository;
        this.objectMapper = objectMapper;
    }

    public Portal savePortalFromJson(String jsonString) throws IOException {
        // 把JSON字符串转成Portal对象
        Portal portal = objectMapper.readValue(jsonString, Portal.class);
        
        // 手动绑定关联关系(确保层级关联正确)
        portal.getSpaces().forEach(space -> {
            space.setPortal(portal);
            space.getIndicators().forEach(indicator -> indicator.setSpace(space));
        });
        
        // 保存到数据库,级联保存所有关联的Spaces和Indicators
        return portalRepository.save(portal);
    }
}

如果你的JSON字段和实体属性名不一致,可以用@JsonProperty("json_field_name")注解来映射,比如实体属性叫portalName,JSON里是portal_name,就加@JsonProperty("portal_name")在属性上。

5. 测试功能

可以写一个接口或者测试类来验证功能是否正常。

示例Controller(接收JSON字符串并保存)

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;

@RestController
@RequestMapping("/api/portal")
public class PortalController {
    private final PortalService portalService;

    public PortalController(PortalService portalService) {
        this.portalService = portalService;
    }

    @PostMapping("/import")
    public ResponseEntity<Portal> importPortal(@RequestBody String jsonString) {
        try {
            Portal savedPortal = portalService.savePortalFromJson(jsonString);
            return ResponseEntity.ok(savedPortal);
        } catch (IOException e) {
            e.printStackTrace();
            return ResponseEntity.badRequest().build();
        }
    }
}

JUnit测试类

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import static org.junit.jupiter.api.Assertions.*;

@SpringBootTest
public class PortalServiceTest {
    @Autowired
    private PortalService portalService;

    @Test
    public void testSaveFromJson() throws Exception {
        String json = "{ \"portalName\":\"office360\", \"spaces\": [ { \"spaceName\": \"Modèle d'Espace collaboratif\", \"indicators\": [ { \"indicatorName\": \"Created content\", \"indicatorCounter\": \"0\" }, { \"indicatorName\": \"answers reader\", \"indicatorCounter\": \"0\" } ] } ] }";
        
        Portal savedPortal = portalService.savePortalFromJson(json);
        
        // 验证保存结果
        assertNotNull(savedPortal.getId());
        assertEquals("office360", savedPortal.getPortalName());
        assertEquals(1, savedPortal.getSpaces().size());
        assertEquals(2, savedPortal.getSpaces().get(0).getIndicators().size());
    }
}

一些注意事项

  • 实体类命名:Spaces建议改成Space(单数形式更符合JPA惯例),不过如果你已经用了这个名字也没关系,只是数据库表名会是spaces(默认小写)。
  • 关联关系的懒加载:FetchType.LAZY是默认值,能避免不必要的数据库查询,提升性能。
  • 级联操作:CascadeType.ALL意味着保存/删除Portal时,会自动处理关联的Spaces和Indicators,orphanRemoval = true会移除和Portal解除关联的Spaces。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 08:32:37