SAP / olingo-jpa-processor-v4

The JPA Processor fills the gap between Olingo V4 and the database, by providing a mapping between JPA metadata and OData metadata, generating queries and supporting the entity manipulations.
Apache License 2.0
127 stars 79 forks source link

ManyToOne Mapping throws exception "com.sap.olingo.jpa.metadata.core.edm.mapper.exception.ODataJPAModelException: Error when creating Referential Constraints" #63

Closed saupan closed 3 years ago

saupan commented 5 years ago

I am trying to make a simple demo application using this library. I get the above error when using a ManyToOne mapping between my entities.

Entity BeerRating

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "BEER_RATING_ID_GENERATOR")
    @Column(name = "ID", nullable = false, precision = 10)
    private BigDecimal id;

    @ManyToOne
    @JoinColumn(name = "BEER_ID", referencedColumnName = "ID")
    private Beer beer;

Entity Beer

@Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "BEER_ID_GENERATOR")
    @Column(name = "ID", nullable = false, precision = 10)
    private BigDecimal id;

    @Column(name = "NAME", nullable = false)
    private String name;

    @Column(name = "BRAND", nullable = false)
    private String brand;
wog48 commented 5 years ago

Hello,

in opposite of JPA the JPA Processor needs, as of now, the join column as attribute. You need add the following to BeerRating:

  @EdmIgnore
  @Column(name = "BEER_ID", precision = 10, insertable = false, updatable = false)
  private BigDecimal beerId;

Now the error is gone and BeerId wont appear as property in the metadata document.

wzagrajcz commented 5 years ago

Hello, I had similar issue and Your solution helped me. Thanks a lot.

However, I wanted to have my relationship bidirectional. So keeping the same entities as in original post I would like to use both

ODataDemo.svc/BeerRatings?$expand=Beer and ODataDemo.svc/Beers?$expand=BeerRating The first one is working perfectly. To achieve the second I added to the Beer something like that

@OneToMany(mappedBy = "beer")
private List<BeerRating> beerRating = new ArrayList<>();

However it does not work - I got error of null code with error message Element BeerId does not correspond to an element in the query result. Do You happen to know what I'm doing wrong? Error message does not tell much to me especially since beerId located in BeerRating have @EdmIgnore annotation.

Thanks

wog48 commented 5 years ago

I was not able to reproduce your error. I assume because I did some changes during the development of the last release. Please try that one. If it does not work. Please let me know.

wog48 commented 5 years ago

@saupan Have you tried it with the latest version? Do you still get the problem?

mdanaher1 commented 2 years ago

Not sure what the outcome of this issue was way back when, but I appear to be having a similar one. Testing with the two below relatively simple classes.

@Entity
@Table(name="BRAND")
@Getter
@Setter
public class Brand {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

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

    @OneToMany(mappedBy = "brand", orphanRemoval = true, cascade = CascadeType.ALL)
    private List<Model> models;
}
@Entity
@Table(name = "MODEL")
@Getter
@Setter
public class Model {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String name;

    @ManyToOne(optional = false, fetch = FetchType.LAZY)
    @JoinColumn(name = "brand_id")
    private Brand brand;
}

Trying to hit $metadata or anything, I get the below.

"error": {
        "code": null,
        "message": "com.sap.olingo.jpa.metadata.core.edm.mapper.exception.ODataJPAModelException: Error when
        creating Referential Constraints for 'models': Property for 'brand_id' not found at 'Model'."
    }

Adding @EdmIgnore to brand property in Model, throws the below

"error": {
        "code": null,
        "message": "Cannot invoke \"com.sap.olingo.jpa.metadata.core.edm.mapper.impl.IntermediateNavigationProperty.getJoinTable()\" because the return value of \"com.sap.olingo.jpa.metadata.core.edm.mapper.impl.IntermediateStructuredType.getAssociation(String)\" is null"
    }
wog48 commented 2 years ago

Hello,

currently the JPA Processor requires that all necessary properties to generate queries a explicitly mentioned in the entity definition. In case you add the following it should work:

public class Model {
...
  @EdmIgnore
  @Column(name = "brand_id", insertable = false, updatable = false)
  private Long brandId;
...
}

Please not that @EdmIgnore prevents that the property is exposed in the metadata