2016-10-12 2 views
2

Ich arbeite gerade an einem JPA/Olingo basierten Odatendienst. Die verwendete Olingo-Version ist 2.0.7. Die verwendete JPA-Implementierung ist eclipselink Version 2.5.1. Es gibt zwei Entitäten, die über eine OneToMany-Beziehung verbunden sind (Firma, Seite). Es ist in Ordnung, das Unternehmen vom Dienst (z. B./odata/v2/Companies) ohne einen $ expand anzurufen. Dasselbe gilt für das Anfordern der Seiten. Das Anfordern von Seiten und das Erweitern der CompanyDetails funktioniert ebenfalls. Irgendwie gibt das Anfordern des Unternehmens und das Erweitern der zugehörigen Seiten (z. B./odata/v2/Companies? $ Expand = Pages) ein Array der Größe null für die Seiten zurück, auch wenn der verzögerte Link aufgerufen wird (zB/odata/v2/Companies ('P')/Pages) in der Entität "company" gibt das Array der Seiten erwartungsgemäß zurück.

Hier ist meine persistence.xml (andere noch nicht getestet Einheiten ommiting):

@Entity 
@Table(name = "HUM_COMPANY") 
public class Company { 
    private static final Logger log = 
LoggerFactory.getLogger(Company.class); 

    @Id 
    private String id; 

    @Column 
    private String datacenterUrl; 

    @OneToMany(fetch = FetchType.EAGER, mappedBy = "company", cascade = 
CascadeType.ALL) 
    @CascadeOnDelete 
    private List<Page> pages; 

    @Temporal(TemporalType.TIMESTAMP) 
    @Column(insertable = false, updatable = false) 
    private Date modified; 

    @Temporal(TemporalType.TIMESTAMP) 
    @Column(insertable = false, updatable = false) 
    private Date created; 

    @PrePersist 
    public void prePersist() { 
     Date now = new Date(); 
     created = now; 
     modified = now; 
    } 

    @PreUpdate 
    public void preUpdate() { 
     modified = new Date(); 
    } 

    public Date getModified() { 
     return modified; 
    } 

    public void setModified(Date modified) { 
     log.debug("Olingo trying to set date {}", modified); 
    } 

    public Date getCreated() { 
     return created; 
    } 

    public void setCreated(Date created) { 
     log.debug("Olingo trying to set date {}", created); 
    } 

    public String getId() { 
     return id; 
    } 

    public void setId(String id) { 
     this.id = id; 
    } 

    public String getDatacenterUrl() { 
     return datacenterUrl; 
    } 

    public void setDatacenterUrl(String datacenterUrl) { 
     this.datacenterUrl = datacenterUrl; 
    } 

    public List<Page> getPages() { 
     return pages; 
    } 

    public void setPages(List<Page> pages) { 
     this.pages = pages; 
    } 
} 

Meine Seite Klasse sieht wie folgt aus:

@Entity 
@Table(name = "HUM_PAGE") 
public class Page implements Serializable { 
    private static final Logger log = LoggerFactory.getLogger(Page.class); 

    /** 
    * 
    */ 
    private static final long serialVersionUID = 1L; 


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

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

    @Column 
    private String description; 

    @OneToOne 
    private Context context; 

    @ManyToOne(cascade = CascadeType.REFRESH) 
    @JoinColumn(name = "company_id", nullable = false) 
    private Company company; 

    @Temporal(TemporalType.TIMESTAMP) 
    @Column(nullable = false) 
    private Date modified; 

    @Temporal(TemporalType.TIMESTAMP) 
    @Column(nullable = false) 
    private Date created; 

    @PrePersist 
    public void prePersist() { 
     Date now = new Date(); 
     created = now; 
     modified = now; 
    } 

    @PreUpdate 
    public void preUpdate() { 
     modified = new Date(); 
    } 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

    public String getDescription() { 
     return description; 
    } 

    public void setDescription(String description) { 
     this.description = description; 
    } 

    public Long getId() { 
     return id; 
    } 

    public Date getModified() { 
     return modified; 
    } 

    public Date getCreated() { 
     return created; 
    } 

    public Company getCompany() { 
     return company; 
    } 

    public void setCompany(Company company) { 
     this.company = company; 
    } 

    public void setId(Long id) { 
     log.debug("Olingo trying to set Id {}", id); 
    } 

    public void setModified(Date modified) { 
     log.debug("Olingo trying to set date {}", modified); 
    } 

    public void setCreated(Date created) { 
     log.debug("Olingo trying to set date {}", created); 
    } 

} 

<?xml version="1.0" encoding="UTF-8"?> 
<persistence version="2.0" 
    xmlns="http://java.sun.com/xml/ns/persistence" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence 
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> 
    <persistence-unit name="s.h.backend" 
     transaction-type="RESOURCE_LOCAL"> 
     <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> 
     <class>c.p.s.h.data.Company</class> 

... 

     <class>c.p.s.h.data.Page</class> 

... 

     <properties> 
      <property name="eclipselink.ddl-generation" 
value="create-tables" /> 
      <property name="eclipselink.logging.level" value="INFO" /> 
      <property name="eclipselink.jpql.parser" 
value="org.eclipse.persistence.queries.ANTLRQueryBuilder" /> 
     </properties> 
    </persistence-unit> 
</persistence> 

wie diese My Company Klasse sieht

Ich erweitern die ODataJPAServiceFactory und überschreiben die initializeODat aJPAContext Methode:

@Override 
    public ODataJPAContext initializeODataJPAContext() throws 
ODataJPARuntimeException { 
     ODataJPAContext oDataJPAContext = getODataJPAContext(); 
     try { 

oDataJPAContext.setEntityManagerFactory(JpaEntityManagerFactory.getEntityManagerFactory()); 

oDataJPAContext.setPersistenceUnitName(JpaEntityManagerFactory.PERSISTENCE_UNIT_NAME); 
      oDataJPAContext.setJPAEdmMappingModel("HumEdmMapping.xml"); 
     } catch (NamingException | SQLException e) { 
      throw new ODataRuntimeException(e); 
     } 
     return oDataJPAContext; 
    } 

Die EntityManagerFactory wird wie folgt erstellt:

public static synchronized EntityManagerFactory 
getEntityManagerFactory() 
      throws NamingException, SQLException { 
     if (entityManagerFactory == null) { 
      InitialContext ctx = new InitialContext(); 
      DataSource ds = (DataSource) ctx.lookup(DATA_SOURCE_NAME); 
      Map<String, Object> properties = new HashMap<String, Object>(); 
      properties.put(PersistenceUnitProperties.NON_JTA_DATASOURCE, 
ds); 
      entityManagerFactory = Persistence.createEntityManagerFactory(
        PERSISTENCE_UNIT_NAME, properties); 
     } 
     return entityManagerFactory; 
    } 

Meine Mapping-Datei wie folgt aussieht:

<?xml version="1.0" encoding="UTF-8"?> 
<JPAEDMMappingModel 

xmlns="http://www.apache.org/olingo/odata2/jpa/processor/api/model/mapping"> 
    <PersistenceUnit name="s.h.backend"> 
     <JPAEntityTypes> 
      <JPAEntityType name="Company"> 
       <EDMEntityType>Company</EDMEntityType> 
       <EDMEntitySet>Companies</EDMEntitySet> 
       <JPAAttributes> 
        <JPAAttribute name="created">Created</JPAAttribute> 
        <JPAAttribute 
name="datacenterUrl">DatacenterUrl</JPAAttribute> 
        <JPAAttribute name="id">Id</JPAAttribute> 
        <JPAAttribute name="modified">Modified</JPAAttribute> 
       </JPAAttributes> 
       <JPARelationships> 
        <JPARelationship 
name="pages">Pages</JPARelationship>    
       </JPARelationships> 
      </JPAEntityType> 
      <JPAEntityType name="Page"> 
       <EDMEntityType>Page</EDMEntityType> 
       <EDMEntitySet>Pages</EDMEntitySet> 
       <JPAAttributes> 
        <JPAAttribute name="created">Created</JPAAttribute> 
        <JPAAttribute name="name">Name</JPAAttribute> 
        <JPAAttribute 
name="description">Description</JPAAttribute> 
        <JPAAttribute name="id">Id</JPAAttribute> 
        <JPAAttribute name="modified">Modified</JPAAttribute> 
       </JPAAttributes> 
       <JPARelationships> 
        <JPARelationship 
name="company">Company</JPARelationship>    
       </JPARelationships> 
      </JPAEntityType> 

... 

     </JPAEntityTypes> 
     <JPAEmbeddableTypes> 
     </JPAEmbeddableTypes> 
    </PersistenceUnit> 
</JPAEDMMappingModel> 
+0

Hast du es geschafft, das Problem zu lösen? Ich bin derzeit genau das gleiche Problem und weiß nicht, wie es zu lösen ist ... – 3dDi92

+0

Nein, ich habe es bis jetzt nicht gelöst. Ich war mit anderen Aufgaben beschäftigt, werde aber versuchen, es wieder zu lösen, wenn ich etwas Freizeit habe. In der Zwischenzeit werden wir es einfach vermeiden, das $ expand-Schlüsselwort in unserem Projekt zu verwenden, was sehr schade ist. – defect

+0

Ich habe bereits einen Workaround gefunden, aber dieser funktioniert irgendwie nur für Testdaten, die vom Backend generiert werden. In Ihrem Fall müssten Sie in Ihrer Unternehmensklasse eine bestimmte Methode definieren, um den Listenseiten eine einzelne Seite hinzuzufügen. Nachdem eine neue Seite erhalten wurde, müssen Sie im Prinzip den übergeordneten Datensatz (die Firma) aufrufen und die neue persistente Seite hinzufügen. Nichtsdestotrotz funktioniert es nur für meine Testdaten und nicht in der produktiven Version und ich dachte, dass dies vom JPA-Framework gehandhabt würde ... – 3dDi92

Antwort

1

ich verschiedene Lösungen für dieses Problem untersucht, die in bereits diskutiert wurden die Kommentare von meinem ursprünglichen Beitrag:

  • @Cache (type = CacheType.NONE): Gemäß der Dokumentation von EclispeLink (https://eclipse.org/eclipselink/api/2.0/org/eclipse/persistence/config/CacheType.html) wird von der Verwendung dieser Anmerkung abgeraten.

  • Registrierung einer PostPersistListener-Klasse mit der Page-Klasse mit @EntityListeners und eine "InvalidateAll" in der Methode, die mit @PostPersist kommentiert. Das Ergebnis war nicht zuverlässig.

  • @Cache (Isolation = CacheIsolationType.ISOLATED): Diese Annotation tut was ich brauche.

So wurde mein Problem für jetzt gelöst. Ich dachte, es ist eine gute Idee, es für jeden zu dokumentieren, der das gleiche Problem hat. (Und damit ich es das nächste Mal merke ;-))

Verwandte Themen