【问题标题】:Doing a post on spring boot olingo on an entity with a relationship在有关系的实体上发布关于 Spring Boot olingo 的帖子
【发布时间】:2025-12-21 17:50:15
【问题描述】:

我有一些由 spring-boot 和 olingo 构建的 odata V2 api。我正在尝试向有关系的实体发帖

public class CompanyProfileDetail {

    private Long id;

    @NotNull
    private Long version;

    @NotNull
    @OneToOne
    @JoinColumn(name = "company_profile_id", referencedColumnName = "id")
    private CompanyProfile companyProfile;
...
}

public class CompanyProfile {

    private Long id;
    
    @NotNull
    private Long version;

...
}

所以当我尝试使用 CompanyProfileDetails api 发布此内容时

{
    "Version": "1",
    "CompanyProfile": "1"
}

它不起作用,但这个

{
    "Version": "1",
    "CompanyProfileDetails" : {
        "__metadata": {
                "id": "http://localhost:8080/odata/CompanyProfiles(1L)",
                "uri": "http://localhost:8080/odata/CompanyProfiles(1L)",
                "type": "default.CompanyProfile"
            }
    }
}

有效。所以现在我想知道这是否是发布关系的 odata 标准,或者是否有一些设置可以接受第一个结构。

仅供参考,第二个数据结构中的“CompanyProfileDetails”是 olingo 自动命名相关实体的方式。它实际上是 CompanyProfiles 实体

再举一个例子:

public class CompanyProfile {

    private Long id;
    
    @NotNull
    private Long version;

    @ManyToOne
    @JoinColumn(name = "address", referencedColumnName = "id")
    private Location address;

    @Column(name="contact_number")
    private String contactNumber;

    @NotNull
    @Column(name="name")
    private String name;

    @NotNull
    @Column(name="status")
    private String status;
...
}

public class Location {
    
    @Id
    @Column(name = "id")
    @NotNull
    private Long id;


    private Long version;

    @ManyToOne
    @JoinColumn(name = "city", referencedColumnName = "id")
    private CityMunicipality city;

    @ManyToOne
    @JoinColumn(name = "province", referencedColumnName = "id")
    private Province province;
}

工作请求如下所示:

{
    "Version": "1",
    "ContactNumber": "1245",
    "Name": "OIL Tycoon corporation",
    "Status": "OK",
    "LocationDetails" : {
        "__metadata": {
                "id": "http://localhost:8080/odata/Locations(2L)",
                "uri": "http://localhost:8080/odata/Locations(2L)",
                "type": "default.Location"
            }
    }
}

但这不起作用:

{
    "Version": "1",
    "ContactNumber": "1245",
    "Name": "OIL Tycoon corporation",
    "Status": "OK",
    "Address" : "2",
}

在这种情况下存在 ID 为 2 的位置。

根据要求提供 $ 元数据。这是第二个例子。希望这会有所帮助!

<EntityType Name="CompanyProfile">
                <Key>
                    <PropertyRef Name="Id"></PropertyRef>
                </Key>
                <Property Name="Address" Type="Edm.Int64" Nullable="true"></Property>
                <Property Name="ContactNumber" Type="Edm.String" Nullable="true" MaxLength="255"></Property>
                <Property Name="Id" Type="Edm.Int64" Nullable="false"></Property>
                <Property Name="Version" Type="Edm.Int64"></Property>
                <Property Name="Name" Type="Edm.String"></Property>
                <NavigationProperty Name="LocationDetails" Relationship="default.CompanyProfile_Location_Many_ZeroToOne0" FromRole="CompanyProfile" ToRole="Location"></NavigationProperty>
</EntityType>
<EntityType Name="Location">
                <Key>
                    <PropertyRef Name="Id"></PropertyRef>
                </Key>
                <Property Name="City" Type="Edm.String" Nullable="true"></Property>
                <Property Name="Id" Type="Edm.Int64" Nullable="false"></Property>
                <Property Name="Province" Type="Edm.String" Nullable="true"></Property>
                <Property Name="Region" Type="Edm.Region" Nullable="true"></Property>
                <Property Name="Version" Type="Edm.Int64" Nullable="true"></Property>
</EntityType> 

【问题讨论】:

  • 当我们在公司简介中而不是在公司简介详细信息中时,这里的一对一映射是真正有意义的。
  • 啊,这只是一个简化版本,用于显示代码中的关系是如何建立的。此外,本例中的 CompanyProfile 已经存在。我没有创建新的 CompanyProfile,我只是将其设置为 CompanyProfildeDetails。
  • 不要在一个 json 中包含所有属性。具有关系的属性应该是子 json。您可以参考我的答案并尝试该格式。希望这应该工作

标签: java spring-boot odata olingo


【解决方案1】:

Olingo 2.0 JPA 处理器的默认实现以 &lt;Navigation Property Name&gt;Details 的格式命名导航属性,例如,如果您有一个名为 Location 的连接,则导航属性将命名为 LocationDetails

要执行 DeepInset,您可以使用以下有效负载

{
    "version": "1",
    "contactNumber" : "",
    "LocationDetails": {
        "id":"",
        "version":"",
         "CityMunicipalityDetails":{
             // all attributes of city class
          },
         "ProvinceDetails":{
            // all attributes of province class
          }
    
    }
}

另外,您还可以查看 OData 2 中 $batch 的实现,因为深度插入是 OData 实现的更高版本的一部分,但 Olingo 2.0 JPA 处理器也在 2.0 版中实现。

PS:请检查$metadata 以获取导航属性名称,如果此解决方案无法解决问题,请尽可能发布$metadata 内容。

【讨论】:

  • 对不起@Shiva 我忘了早点问这个。作为后续问题,这是 Spring-boot snd/或 olingo 的怪癖吗?并且无论如何要更改它,以便它也接受直接放置 id 的格式,如 "Address" : "2"?
  • 这是 Olingo 和 OData,与 Spring Boot 无关。要以不相交的方式创建实体,我建议查看 $batch 方法来创建实体
【解决方案2】:

您指定了两个无效的发布请求。对于第一个,下面的请求正文应该可以工作。

{
    "version": "1",
    "companyProfile": {
        "id" : 1,
        "version" : "1"
    
    }
}

第二个,

{
    "version": "1",
    "contactNumber" : "",
    "address": {
        "id":"",
        "version":"",
         "city":{
             // all attributes of city class
          },
         "province":{
            // all attributes of province class
          }
    
    }
}

【讨论】:

  • 您好 Karthick,感谢您的回复。不幸的是,它仍然不起作用。我收到了一个畸形的身体错误。可以肯定的是,这种方法是否也不会在子对象中创建它们?我尝试仅在我的案例中使用 Id,因为我试图创建关系而不是创建子对象。不过,在这种情况下,我并不完全确定 odata 的标准是什么。我应该补充一点,这是一个 odata api。我刚刚也将它添加到标签中。
  • 请贴出接收请求的api方法。您还可以通过此链接和 cmets 来查看请求是如何发布的。 callicoder.com/…