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

Micronaut中数据库实体关联加载失败问题求助

Micronaut中OneToMany关联的Software无法加载(SQL生成正常但映射失败)

我存在Fleet->Configuration->Software的一对多关联关系,希望获取关联单个Fleet的所有Configuration数据,同时加载每个Configuration对应的全部Software。但目前Micronaut无法正确加载关联的Software列表,具体情况如下:

注意事项

  • 已尝试组合使用@Join和@JoinSpecifications,未生效
  • 生成的SQL语句正确,问题仅出现在结果映射环节

相关代码

Configuration类

@javax.persistence.Entity
@MappedEntity
@NoArgsConstructor
@Data
@Builder
public class Configuration {

    @Id
    @GeneratedValue(GeneratedValue.Type.AUTO)
    private Long id;

    // 其他字段

    @NotNull
    @ManyToOne(optional = false)
    @JoinColumn(nullable = false, updatable = false)
    private Fleet fleet;

    @NotNull
    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
    @Relation(value = Relation.Kind.ONE_TO_MANY)
    private List<Software> softwares;
}

Fleet类

@javax.persistence.Entity
@AllArgsConstructor
@NoArgsConstructor
@Data
@Builder
public class Fleet {

    @Id
    @GeneratedValue(GeneratedValue.Type.AUTO)
    private Long id;

    @NotNull
    @Size(min = 1, max = 255)
    @Column(unique = true)
    private String name;

    // 不需要映射到Configuration
}

Software类

@MappedEntity
@javax.persistence.Entity
@AllArgsConstructor
@NoArgsConstructor
@Data
@Builder
public class Software implements Entity {

    @Id
    @GeneratedValue(GeneratedValue.Type.AUTO)
    private Long id;

    // 其他字段

    @NotNull
    @ManyToOne(optional = false)
    @JoinColumn(nullable = false, updatable = false)
    @Relation(value = Relation.Kind.MANY_TO_ONE)
    @ToString.Exclude
    private Configuration configuration;
}

ConfigurationRepository接口

@JdbcRepository(dialect = Dialect.H2)
@JoinSpecifications(
        {
                @Join(value = "softwares", type = Join.Type.LEFT_FETCH),
                @Join(value = "fleet", type = Join.Type.LEFT_FETCH)
        }
)
public interface ConfigurationRepository extends ReactorPageableRepository<Configuration, Long> {}

生成的SQL语句

SELECT configuration_.`id`,
       configuration_.`name`,
       configuration_.`project_name`,
       configuration_.`version_w`,
       configuration_.`version_x`,
       configuration_.`version_y`,
       configuration_.`version_z`,
       configuration_.`version_description`,
       configuration_.`approved_date`,
       configuration_.`imported_date`,
       configuration_.`fleet_id`,
       configuration_softwares_.`id`                  AS softwares_id,
       configuration_softwares_.`name`                AS softwares_name,
       configuration_softwares_.`supplier`            AS softwares_supplier,
       configuration_softwares_.`description`         AS softwares_description,
       configuration_softwares_.`circuit_diagram`     AS softwares_circuit_diagram,
       configuration_softwares_.`comment`             AS softwares_comment,
       configuration_softwares_.`date`                AS softwares_date,
       configuration_softwares_.`version_w`           AS softwares_version_w,
       configuration_softwares_.`version_x`           AS softwares_version_x,
       configuration_softwares_.`version_y`           AS softwares_version_y,
       configuration_softwares_.`version_z`           AS softwares_version_z,
       configuration_softwares_.`version_description` AS softwares_version_description,
       configuration_softwares_.`checksum_cipher`     AS softwares_checksum_cipher,
       configuration_softwares_.`checksum_hash`       AS softwares_checksum_hash,
       configuration_softwares_.`system_id`           AS softwares_system_id,
       configuration_softwares_.`configuration_id`    AS softwares_configuration_id,
       configuration_fleet_.`name`                    AS fleet_name
FROM `configuration` configuration_
         LEFT JOIN `fleet` configuration_fleet_
                   ON configuration_.`fleet_id` = configuration_fleet_.`id`
         INNER JOIN `configuration_software` configuration_softwares_configuration_software_
                    ON configuration_.`id` =
                       configuration_softwares_configuration_software_.`configuration_id`
         INNER JOIN `software` configuration_softwares_
                    ON configuration_softwares_configuration_software_.`software_id` =
                       configuration_softwares_.`id`
ORDER BY configuration_.name ASC, configuration_.approved_date ASC, configuration_.imported_date ASC

解决方案

问题核心是双向关联的映射配置缺失,导致Micronaut Data无法正确将查询到的Software记录分组到对应的Configuration实例中。需要修改Configuration类中的softwares字段配置:

修改后的Configuration类字段

@NotNull
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "configuration")
@Relation(value = Relation.Kind.ONE_TO_MANY, mappedBy = "configuration")
private List<Software> softwares;

关键修改点:

  1. JPA的@OneToMany注解添加mappedBy = "configuration",指定双向关联的另一方字段(即Software类中的configuration属性)
  2. Micronaut Data的@Relation注解同样添加mappedBy = "configuration",让框架明确关联关系的映射方向

这样配置后,框架就能正确识别查询结果中Configuration和Software的关联关系,将对应的Software实例填充到Configuration的softwares列表中。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 19:40:07