【问题标题】:JPA fetch from multiple tables to single POJO with named queryJPA 使用命名查询从多个表中获取单个 POJO
【发布时间】:2015-02-16 23:07:47
【问题描述】:

我一直在尝试将数据从 2 个不同的表中提取到 JPA 中的单个实体,但没有结果。

从两个不同的表中保存数据的实体如下:

@Data @Entity @JsonSnakeCase

public class WareHouse {

  @Id
  @GeneratedValue
  private long id;

  @Column(unique = true)
  private String fcId;

  @Enumerated(EnumType.STRING)
  private FCStatus status;

  @OneToMany(cascade = CascadeType.PERSIST, fetch = FetchType.EAGER, mappedBy = "fcId")
  private List<WorkingHours> workingHours;

  @Enumerated(EnumType.STRING)
  private IntegrationType integrationType;
}

另一个实体WorkingHours是:

@Data
@Entity
@JsonSnakeCase
public class WorkingHours {
    @Id
    @GeneratedValue
    private long id;

    private String fcId;
    private LocalDate date;
    private DateTime start;
    private DateTime end;
}

WareHouseWorkingHours 表具有一对多关系,fcId 是连接它们的列。

在我的用例中,我必须在上面定义的单个实体 WareHouse 中获取 WareHouse 详细信息及其 WorkingHours。我如何做到这一点?

命名查询(如下)仅获取WareHouse 数据,而WorkingHours 将变为空。数据模型错了吗?还是查询错误? (我认为 JPA 在给定注释 OneToManyFetchType 等时会自动从相关表中获取数据。)

<named-query name="searchByFcId">
        <query>
            <![CDATA[
            select f from WareHouse f where f.fcId = :fc_id
            ]]>
        </query>
    </named-query>

【问题讨论】:

  • 看起来不错,但可能会因为您在Warehouse 实体和WorkingHours 实体中都有fcId 而感到困惑,所以我猜真正的映射列不是fcId。检查你的真实数据库,看看 FK 是什么。
  • fcID 是数据库中的外键。
  • 但是仓库的PK不是引用它的字段吗?
  • 是的。引用的列不是 PK 而是唯一的受约束列。
  • 对不起,我沟通不好。如果您查看 Warehouse 表,引用 WorkingHours 的列名是什么?

标签: java mysql jpa named-query


【解决方案1】:

您可以尝试以下映射。 JPA 2.0 规范说明 (11.1.21) 说明:

If the referencedColumnName element is missing, the foreign key is assumed to 
refer to the primary key of the referenced table.

但它还继续指出:

Support for referenced columns that are not primary key columns of the 
referenced table is optional. Applications that use such mappings 
will not be portable.

所以这是否有效将取决于您的提供商。

仓库:

@Data 
@Entity 
@JsonSnakeCase
public class WareHouse {

  @Id
  @GeneratedValue
  private long id;

  @Column(unique = true)
  private String fcId;

  @Enumerated(EnumType.STRING)
  private FCStatus status;

  @OneToMany(mappedBy = "warehouse", cascade = CascadeType.PERSIST, fetch = FetchType.EAGER)
  private List<WorkingHours> workingHours;

  @Enumerated(EnumType.STRING)
  private IntegrationType integrationType;
}

工作时间:

@Data
@Entity
@JsonSnakeCase
public class WorkingHours {

    @Id
    @GeneratedValue
    private long id;

    @ManyToOne
    @JoinColumn(name = "fcId", referencedColumnName="fcid")
    private Warehouse warehouse;

    private LocalDate date;
    private DateTime start;
    private DateTime end;
}

【讨论】:

  • 是的。这解决了它。后来我不得不为日期类型注释 jadira 时间类型以避免序列化错误,然后我必须对引用的对象进行 JsonIgnoreProperties 以避免无限循环。但是,是的,这解决了我最初提出的问题。谢谢。
  • 好的,很好。实际上没有必要使关系双向(导致无限循环)。删除 WorkingHour > Warehouse 的映射,将 '@JoinColumn' 注释移动到 Warehouse 中的 '@OneToMany' 并删除 mappedBy 将解决此问题,一切仍应按预期工作。
  • 有趣。我会试试的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-18
  • 1970-01-01
  • 2019-04-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多