为什么$ expand在我的JPA/Olingo项目中无法正常工作 [英] Why is $expand not working correct in my JPA/Olingo project

查看:127
本文介绍了为什么$ expand在我的JPA/Olingo项目中无法正常工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在研究基于JPA/Olingo的odata服务.使用的Olingo版本是2.0.7.使用的JPA实现是eclipselink 2.5.1版.有两个实体通过OneToMany关系连接(公司,页面).在没有$ expand的情况下从服务中请求公司(例如/odata/v2/Companies)可以正常工作.请求页面也一样.请求页面和扩展CompanyDetails也可以正常工作.以某种方式请求公司并扩展关联的页面(例如/odata/v2/Companies?$ expand = Pages),尽管在调用延迟链接时(例如/odata/v2/Companies('P') /Pages)返回预期的页面数组.

I am currently working on a JPA/Olingo based odata service. The Olingo version used is 2.0.7. The JPA implementation used is eclipselink version 2.5.1. There are two entities connected through a OneToMany relationship (Company, Page). Requesting the company from the service (e.g. /odata/v2/Companies) without an $expand works fine. The same for requesting the pages. Requesting pages and expanding the CompanyDetails works fine as well. Somehow requesting the company and expanding the associated pages (e.g. /odata/v2/Companies?$expand=Pages) returns a zero size array for the pages allthough when calling the deferred link (e.g. /odata/v2/Companies('P')/Pages) in the company entity returns the array of pages as expected.

这是我的persistence.xml(省略其他尚未测试的实体):

Here's my persistence.xml (ommiting other not yet tested entities):

<?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>

我的公司类如下:

@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;
    }
}

我的Page类如下:

@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);
    }

}

我正在扩展ODataJPAServiceFactory并覆盖 initializeODataJPAContext方法:

I am extending the ODataJPAServiceFactory and override the initializeODataJPAContext method:

    @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;
    }

如下创建EntityManagerFactory:

The EntityManagerFactory is created as follows:

    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;
    }

我的映射文件如下:

<?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>

推荐答案

我针对此问题测试了不同的解决方案,这些解决方案已在我的原始帖子的评论中进行了讨论:

I tested different solutions for this issue which were already discussed in the comments of my original post:

  • @Cache(type = CacheType.NONE):根据EclispeLink的文档(

  • @Cache(type=CacheType.NONE): according to the documentation of EclispeLink (https://eclipse.org/eclipselink/api/2.0/org/eclipse/persistence/config/CacheType.html) the use of this annotation is discouraged.

使用@EntityListeners向Page类注册PostPersistListener类,并在以@PostPersist注释的方法中执行"invalidateAll".结果不可靠.

registering a PostPersistListener class with the Page class using @EntityListeners and do an "invalidateAll" in the method annotated with @PostPersist. The result was not reliable.

@Cache(isolation = CacheIsolationType.ISOLATED):此注释可以满足我的需要.

@Cache(isolation=CacheIsolationType.ISOLATED): This annotation does what I need.

所以我的问题现在已经解决了.认为将其记录给遇到相同问题的任何人都是一个好主意.(对我来说,下次记住它是;-))

So my problem has been solved for now. Thought it's a good idea to document it for anyone experiencing the same issue.. (And for me to remember it the next time ;-))

这篇关于为什么$ expand在我的JPA/Olingo项目中无法正常工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆