使用Olingo V4和MySQL数据库连接的OData服务

时间:2017-01-06 07:56:11

标签: java git maven olingo

我正在关注一些example,我们可以在其中使用来自Java的Olingo (maven项目)构建 OData服务。提供的示例没有任何数据库交互。他们正在使用一些 Storage.class ,其中包含硬编码数据。

您可以在git上找到示例代码。请参阅提供的网址中的示例p0_all

有谁知道我们如何将git示例连接到某个数据库并进一步执行CRUD操作

请帮我一些好的例子或概念。

提前感谢你。

1 个答案:

答案 0 :(得分:3)

我最近使用Olingo构建了一个oData制作人,并发现自己同样感到沮丧。我认为问题的一部分是,使用Olingo构建oData服务确实有很多不同的方法,数据访问部分完全取决于开发人员在他们自己的项目中进行整理。

首先,您需要一个设置了数据库连接的应用程序。完全无视Olingo,你应该有一个连接到并可以查询数据库的应用程序。如果您不确定如何构建可以查询MySQL数据源的Java应用程序,那么您应该在Google周围寻找与该问题相关的教程,并与Olingo无关。

接下来,您需要编写方法和查询以在应用程序中执行CRUD操作。同样,这些方法与Olingo无关。

Olingo开始进入游戏的地方是你的处理器类的实现。 EntityCollectionProcessorEntityProcessor等(请注意,还有其他问题,例如设置CsdlEntityTypes和架构/服务文档等,但这些问题超出了您的问题范围)

让我们先看一下EntityCollectionProcessor。通过实现EntityCollectionProcessor类,您需要覆盖readEntityCollection()函数。此函数的目的是解析实体名称的oData URI,为EntityCollection获取Entity,然后将EntityCollection序列化为符合oData的响应。以下是您的示例链接中readEntityCollection()的实现:

public void readEntityCollection(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType responseFormat)
throws ODataApplicationException, SerializerException {

    // 1st we have retrieve the requested EntitySet from the uriInfo object
    // (representation of the parsed service URI)
    List<UriResource> resourcePaths = uriInfo.getUriResourceParts();
    UriResourceEntitySet uriResourceEntitySet = (UriResourceEntitySet)   resourcePaths.get(0); 
    // in our example, the first segment is the EntitySet
    EdmEntitySet edmEntitySet = uriResourceEntitySet.getEntitySet();

    // 2nd: fetch the data from backend for this requested EntitySetName
    // it has to be delivered as EntityCollection object
    EntityCollection entitySet = getData(edmEntitySet);

    // 3rd: create a serializer based on the requested format (json)
    ODataSerializer serializer = odata.createSerializer(responseFormat);

    // 4th: Now serialize the content: transform from the EntitySet object to   InputStream
    EdmEntityType edmEntityType = edmEntitySet.getEntityType();
    ContextURL contextUrl =   ContextURL.with().entitySet(edmEntitySet).build();

    final String id = request.getRawBaseUri() + "/" + edmEntitySet.getName();
    EntityCollectionSerializerOptions opts =       EntityCollectionSerializerOptions.with().id(id).contextURL(contextUrl).build();
    SerializerResult serializerResult =  serializer.entityCollection(serviceMetadata, edmEntityType, entitySet, opts);
    InputStream serializedContent = serializerResult.getContent();

    // Finally: configure the response object: set the body, headers and status code
    response.setContent(serializedContent);
    response.setStatusCode(HttpStatusCode.OK.getStatusCode());
    response.setHeader(HttpHeader.CONTENT_TYPE,   responseFormat.toContentTypeString());
}

除了“第二步”之外,您可以忽略(并重复使用)此示例中的所有内容:

EntityCollection entitySet = getData(edmEntitySet);

这行代码是Olingo最终开始与我们的底层系统交互的地方,我们在这里看到的模式告诉我们应该如何设置其余的CRUD操作。

在您想要的任何课程中,函数getData(edmEntitySet)可以是您想要的任何内容。唯一的限制是必须返回EntityCollection。因此,您需要做的是调用查询MySQL数据库的函数,并返回给定实体的所有记录(使用实体的字符串名称)。然后,一旦您拥有List或Set(或其他)记录,您需要将其转换为EntityCollection

顺便说一下,我认为这可能是Olingo示例和现实世界应用程序之间脱节的地方。 getData(edmEntitySet);调用背后的代码可以以无限不同的方式构建,具体取决于底层系统中使用的设计模式(MVC等),样式选择,可伸缩性要求等。

以下是我如何从查询返回的EntityCollection创建List的示例(请记住,我假设您知道如何查询MySQL数据源并已编写函数检索给定实体的所有记录):

private List<Foo> getAllFoos(){
    // ... code that queries dataset and retrieves all Foo records
}

// loop over List<Foo> converting each instance of Foo into and Olingo Entity 
private EntityCollection makeEntityCollection(List<Foo> fooList){
    EntityCollection entitySet = new EntityCollection();

    for (Foo foo: fooList){
        entitySet.getEntities().add(createEntity(foo));
    }

    return entitySet;
} 

 // Convert instance of Foo object into an Olingo Entity
 private Entity createEntity(Foo foo){
    Entity tmpEntity = new Entity()
            .addProperty(createPrimitive(Foo.FIELD_ID, foo.getId()))
            .addProperty(createPrimitive(Foo.FIELD_FOO_NAME, foo.getFooName()));

    return tmpEntity;
}

为了更加清晰,getData(edmEntitySet)可能如下所示:

public EntityCollection getData(String edmEntitySet){
    // ... code to determine which query to call based on entity name

    List<Foo> foos = getAllFoos();
    EntityCollection entitySet = makeEntityCollection(foos);
    return entitySet;
}

如果您可以找到使用DataProvider类的Olingo示例,则可以使用一些基本示例来说明如何设置// ...code to determine which query to call based on entity name。我最终使用Java反射大量修改了这种模式,但这与你的问题完全无关。

所以getData(edmEntitySet)是一个函数,它接受一个实体名称,在数据源中查询该实体的所有记录(返回List<Foo>),然后将List<Foo>转换为{{ 1}}。 EntityCollection是通过调用EntityCollection函数来生成的,该函数接受我的createEntity()对象的实例并将其转换为Olingo Foo。然后Entity返回到EntityCollection函数,可以正确序列化并作为oData响应返回。

这个例子揭示了Olingo的一些架构问题以及它自己的例子。在我的示例中,Foo是一个对象,其中包含用于标识字段名称的常量,Olingo使用这些常量来生成oData架构和服务文档。这个对象有一个返回它自己的readEntityCollection()的方法,以及一个构造函数,它自己的属性和getter / setter等。你不必以这种方式设置你的系统,但是对于我的可伸缩性要求这就是我选择做事的方式。

这是Olingo使用的一般模式。覆盖接口的方法,然后在系统的单独部分中调用函数,以期望的方式与数据交互。然后将数据转换为Olingo可读对象,以便他们可以执行响应中需要执行的任何“oData stuff”。如果要为单个实体实现CRUD,则需要实现EntityProcessor及其各种CRUD方法,并且在这些方法中,您需要调用系统中的函数(完全独立于任何Olingo代码){{1} },CsdlEntityType(单一实体),create()read()