ogm session_带有Hibernate OGM的NoSQL –第三部分:在WildFly上构建REST应用程序

ogm session

欢迎回到我们的教程系列“带有Hibernate OGM的NoSQL”! 感谢Gunnar Morling( @gunnarmorling )创建了本教程。 在这一部分中,您将学习如何在WildFly服务器上运行的Java EE应用程序中使用Hibernate OGM。 使用本教程前面部分已经知道的实体模型 ,我们将构建一个基于REST的小型应用程序来管理加息。 如果您还没有阅读本系列的前两期,可以在这里找到它们:

  • 带有Hibernate OGM的NoSQL –第一部分:持久化您的第一个实体
  • 带有Hibernate OGM的NoSQL –第二部分:查询数据

在下面的内容中,您将学习如何准备WildFly以使其与Hibernate OGM一起使用,配置JPA持久性单元,创建用于访问数据的存储库类以及在这些之上提供REST资源。 在本文中,我们将主要关注与持久性相关的方面,因此使用REST / JAX-RS的一些基本经验可能会有所帮助。 本教程的完整源代码托管在GitHub上。

准备WildFly

WildFly服务器运行时基于JBoss Modules系统。 这提供了一个模块化的类加载环境,其中每个库(例如Hibernate OGM)都是其自己的模块,声明了它依赖的其他模块的列表,并且仅从那些其他依赖项中“看到”了类。 这种隔离使人们摆脱了可怕的“类路径地狱”。

SourceForge提供了包含Hibernate OGM所有必需模块的ZIP文件。 我们昨天发布的 Hibernate OGM 4.2支持WildFly 9,因此请下载hibernate-ogm-modules-wildfly9-4.2.0.Final.zip 。 如果您使用的是WildFly 8,请使用Hibernate OGM 4.1并获取hibernate-ogm-modules-wildfly8-4.1.3.Final.zip 。

将与您的WildFly版本相对应的归档文件解压缩到应用程序服务器的modules目录中。 如果您希望原始的WildFly目录保持不变,则还可以将Hibernate OGM模块档案解压缩到任何其他文件夹,并将其配置为服务器要使用的“模块路径”。 为此,请导出以下两个环境变量,以匹配您的特定环境:

export JBOSS_HOME=/path/to/wildfly
export JBOSS_MODULEPATH=$JBOSS_HOME/modules:/path/to/ogm/modules

如果您正在使用Maven WildFly插件 (例如在开发过程中启动WildFly),则可以通过在POM文件中使用以下插件配置来实现相同的目的:

...
<plugin><groupId>org.wildfly.plugins</groupId><artifactId>wildfly-maven-plugin</artifactId><version>1.1.0.Alpha1</version><configuration><jboss-home>/path/to/wildfly</jboss-home><modules-path>/path/to/ogm/modules</modules-path></configuration>
</plugin>
...

设置项目

首先使用“ war”包装类型创建一个新的Maven项目。 将以下内容添加到您的pom.xml中

...
<dependencyManagement><dependencies><dependency><groupId>org.hibernate.ogm</groupId><artifactId>hibernate-ogm-bom</artifactId><type>pom</type><version>4.2.0.Final</version><scope>import</scope></dependency></dependencies>
</dependencyManagement>
...

这样可以确保获得匹配版本的Hibernate OGM模块和任何(可选)依赖项。 然后将依赖项添加到Java EE 7 API和Hibernate OGM后端模块之一,例如Infinispan ,JBoss的高性能,分布式键/值数据网格(其他任何诸如hibernate-ogm-mongodb或全新的hibernate -ogm-cassandra模块也可以工作):

...
<dependencies><dependency><groupId>javax</groupId><artifactId>javaee-api</artifactId><version>7.0</version><scope>provided</scope></dependency><dependency><groupId>org.hibernate.ogm</groupId><artifactId>hibernate-ogm-infinispan</artifactId><scope>provided</scope></dependency>
</dependencies>
...

provided作用域使这些依赖项可用于编译,但是阻止将它们添加到生成的WAR文件中。 那是因为Java EE API已经是WildFly的一部分,而Hibernate OGM将通过您之前解压缩的模块来贡献。

但是,仅将这些模块添加到服务器并不会削减它。 还需要将它们注册为应用程序的模块依赖项。 为此,添加具有以下内容的文件src / main / webapp / WEB-INF / jboss-web.xml

<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structurexmlns="urn:jboss:deployment-structure:1.2"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><deployment><dependencies><module name="org.hibernate" slot="ogm" services="import" /><module name="org.hibernate.ogm.infinispan" services="import" /><module name="org.hibernate.search.orm" services="import" /></dependencies></deployment>
</jboss-deployment-structure>

这将使Hibernate OGM核心和Infinispan后端以及Hibernate Search可用于您的应用程序。 后者将很快用于运行JP-QL查询。

添加实体类和存储库

有了基本的项目基础结构之后,就该添加实体类和存储库类以访问它们了。 实体类型与第1部分中的基本相同,只是现在使用@Indexed进行注释,以允许它们通过Hibernate Search和Lucene进行查询:

@Entity
@Indexed
public class Person {@Id@GeneratedValue(generator = "uuid")@GenericGenerator(name = "uuid", strategy = "uuid2")private String id;private String firstName;private String lastName;@OneToMany(mappedBy = "organizer",cascade = { CascadeType.PERSIST, CascadeType.MERGE },fetch = FetchType.EAGER)private Set<Hike> organizedHikes = new HashSet<>();// constructors, getters and setters...
}
@Entity
@Indexed
public class Hike {@Id@GeneratedValue(generator = "uuid")@GenericGenerator(name = "uuid", strategy = "uuid2")private String id;private String description;private Date date;private BigDecimal difficulty;@ManyToOneprivate Person organizer;@ElementCollection(fetch = FetchType.EAGER)@OrderColumn(name = "sectionNo")private List<HikeSection> sections;// constructors, getters and setters...
}
@Embeddable
public class HikeSection {private String start;private String end;// constructors, getters and setters...
}

为了使用这些实体,必须定义一个JPA持久性单元。 为此,创建文件src / main / resources / META-INF / persistence.xml

<?xml version="1.0" encoding="utf-8"?>
<persistence 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_1_0.xsd"version="1.0"><persistence-unit name="hike-PU" transaction-type="JTA"><provider>org.hibernate.ogm.jpa.HibernateOgmPersistence</provider><class>org.hibernate.ogm.demos.ogm101.part3.model.Person</class><class>org.hibernate.ogm.demos.ogm101.part3.model.Hike</class><properties><property name="hibernate.ogm.datastore.provider" value="INFINISPAN" /><property name="hibernate.ogm.datastore.database" value="hike_db" /><property name="hibernate.ogm.datastore.create_database" value="true" /></properties></persistence-unit>
</persistence>

在这里,我们定义了一个名为“ hike-PU”的持久性单元。 Infinispan是一个完全事务性的数据存储,使用JTA作为事务类型可以使持久性单元参与容器管理的事务。 将HibernateOgmPersistence指定为提供程序类将启用Hibernate OGM(而不是Hibernate ORM),它已为设置后端(在这种情况下为INFINISPAN),数据库名称等配置了一些属性。

请注意,实际上,当在Java EE容器(例如WildFly)中运行时,实际上不需要在persistence.xml中指定实体类型。 相反,它们应该被自动拾取。 使用Hibernate OGM时,目前很不幸。 这是一个已知的限制(请参阅OGM-828 ),我们希望尽快解决。

下一步是实现用于访问远足和组织者数据的存储库类。 例如,下面显示了PersonRepository类:

@ApplicationScoped
public class PersonRepository {@PersistenceContextprivate EntityManager entityManager;public Person create(Person person) {entityManager.persist( person );return person;}public Person get(String id) {return entityManager.find( Person.class, id );}public List<Person> getAll() {return entityManager.createQuery( "FROM Person p", Person.class ).getResultList();}public Person save(Person person) {return entityManager.merge( person );}public void remove(Person person) {entityManager.remove( person );for ( Hike hike : person.getOrganizedHikes() ) {hike.setOrganizer( null );}}
}

实现很简单; 通过@ApplicationScoped批注,该类被标记为应用程序范围的CDI bean(即,该bean的单个实例在应用程序的整个生命周期中都存在)。 它通过依赖注入获得JPA实体管理器,并使用该实体管理器来实现一些简单的CRUD方法(创建,读取,更新,删除)。

请注意, getAll()方法如何使用JP-QL查询返回所有人员对象。 执行后,此查询将转换为等效的Lucene索引查询,该查询将通过Hibernate Search运行。

远足资料库看起来非常相似,因此为简洁起见在此省略。 您可以在GitHub上找到其源代码 。

公开REST服务

JAX-RS使构建基于REST的Web服务变得轻而易举。 它定义了一个声明式编程模型,您可以在其中注释简单的旧Java类,以提供HTTP端点的GET,POST,PUT等操作的实现。

深入描述JAX-RS超出了本教程的范围,例如,如果您想了解更多信息,请参考Java EE 7教程 。 让我们以资源类管理人员的一些方法为例:

@Path("/persons")
@Produces("application/json")
@Consumes("application/json")
@Stateless
public class Persons {@Injectprivate PersonRepository personRepository;@Injectprivate ResourceMapper mapper;@Injectprivate UriMapper uris;@POST@Path("/")public Response createPerson(PersonDocument request) {Person person = personRepository.create( mapper.toPerson( request ) );return Response.created( uris.toUri( person ) ).build();}@GET@Path("/{id}")public Response getPerson(@PathParam("id") String id) {Person person = personRepository.get( id );if ( person == null ) {return Response.status( Status.NOT_FOUND ).build();}else {return Response.ok( mapper.toPersonDocument( person ) ).build();}}@GET@Path("/")public Response listPersons() { … }@PUT@Path("/{id}")public Response updatePerson(PersonDocument request, @PathParam("id") String id) { … }@DELETE@Path("/{id}")public Response deletePerson(@PathParam("id") String id) { … }
}

@Path@Produces@Consumes注释由JAX-RS所定义。 它们将资源方法绑定到特定的URL,以期望并创建基于JSON的消息。 @GET@GET @POST@GET @PUT@DELETE配置每个方法负责哪个HTTP动词。

@Stateless注释将此POJO定义为无状态会话Bean。 可以通过基于@Inject的依赖项注入来获取诸如PersonRepository的依赖项。 实现会话bean使您可以通过容器进行透明的事务管理。 对Persons方法的调用将自动包装在一个事务中,并且Hibernate OGM与数据存储区的所有交互都将参与其中。 这意味着您对托管实体所做的任何更改(例如,通过PersonRepository#create()持久保存新人员或修改从实体管理器检索到的Person对象)都将在方法调用返回后提交到数据存储中。

映射模型

请注意,我们的REST服务的方法本身不会返回并接受托管实体类型,而是返回特定的传输结构,例如PersonDocument

public class PersonDocument {private String firstName;private String lastName;private Set<URI> organizedHikes;// constructors, getters and setters...
}

这样做的理由是以URI的形式表示关联的元素( Person#organizedHikesHike#organizer ),这使客户端能够根据需要获取这些链接的资源。 例如,对http:// myserver / ogm-demo-part3 / hike-manager / persons / 123的GET调用可能返回如下的JSON结构:

{"firstName": "Saundra","lastName": "Johnson","organizedHikes": ["http://myserver/ogm-demo-part3/hike-manager/hikes/456","http://myserver/ogm-demo-part3/hike-manager/hikes/789"]
}

内部模型(例如,实体Person )和外部模型(例如PersonDocument )之间的映射可能很快成为一项繁琐而乏味的任务,因此需要一些基于工具的支持。 存在一些用于此工作的工具,其中大多数使用反射或运行时字节代码生成来在不同模型之间传播状态。

MapStruct寻求另一种方法,这是我的一个业余项目,并在编译时(例如,使用Maven或在您的IDE中)通过Java注释处理器生成bean映射器实现。 它生成的代码是类型安全的,快速的(它使用简单的方法调用,没有反射)并且没有依赖关系。 您只需要使用所需的源和目标类型的映射方法声明Java接口,MapStruct就会在编译过程中生成一个实现:

@Mapper(// allows to obtain the mapper via @InjectcomponentModel = "cdi",// a hand-written mapper class for converting entities to URIs; invoked by the generated// toPersonDocument() implementation for mapping the organizedHikes propertyuses = UriMapper.class
)
public interface ResourceMapper {PersonDocument toPersonDocument(Person person);List<PersonDocument> toPersonDocuments(Iterable<Person> persons);@Mapping(target = "date", dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ")HikeDocument toHikeDocument(Hike hike);// other mapping methods ...
}

然后可以在Persons REST资源中使用生成的实现,以从内部模型映射到外部模型,反之亦然。 如果您想了解有关此模型映射方法的更多信息,请查看GitHub上的完整mapper界面或MapStruct参考文档 。

结语

在本系列教程的这一部分中,您学习了如何将Hibernate OGM添加到WildFly应用程序服务器,并使用它来访问Infinispan作为小型REST应用程序的数据存储。

WildFly是使用Hibernate OGM的应用程序的绝佳运行时环境,因为它提供了现成的大多数必需构建块(例如JPA / Hibernate ORM,JTA,事务管理等),并且紧密集成并可以使用。 我们的模块ZIP可以非常轻松地将Hibernate OGM模块放入组合中,而无需每次在您的应用程序中重新部署它们。 有了WildFly Swarm ,还支持微服务体系结构样式,但是我们将再留一点时间来展示如何将Hibernate OGM与Wildfly Swarm一起使用(当前,WildFly Swarm仍然缺少JPA支持)。

您可以在GitHub上找到该项目的源代码。 要构建项目,请运行mvn clean install (它使用Arquillian本身对一个令人兴奋的主题执行REST服务的集成测试 )。 另外,Maven WildFly插件可用于启动WildFly实例并通过mvn wildfly:run部署应用程序,这非常适合手动测试,例如通过curl或wget发送HTTP请求。

如果您有任何疑问,请在下面的评论中告诉我们,或发送推文到@Hibernate 。 也欢迎您对本教程的后续部分的希望。 敬请关注!

翻译自: https://www.javacodegeeks.com/2015/06/nosql-with-hibernate-ogm-part-three-building-a-rest-application-on-wildfly.html

ogm session

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/337830.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java的define,关于预处理器:Java中的#define

我开始用Java编程&#xff0c;我想知道是否相当于C EDCOX1(0)的存在。对谷歌的快速搜索表明它没有&#xff0c;但有人能告诉我是否存在类似的东西吗&#xff1f;在Java中&#xff1f;我正在努力使我的代码更可读。例如&#xff0c;我希望能够编写myArray[PROTEINS]&#xff0c;…

c语言中函数是怎么理解?

点击上方蓝字关注我&#xff0c;了解更多咨询1、C语言中的函数是一个可以重复使用的代码&#xff0c;用于独立完成某个功能。2、它可以接收用户传输的参数&#xff0c;也可以不接收&#xff0c;将代码段封装成函数的过程称为函数定义。如果有返回值&#xff0c;使用return语句返…

java g1 收集调优_Java性能调优:充分利用垃圾收集器

java g1 收集调优JVM背后发生了什么&#xff0c;垃圾回收如何影响Java性能&#xff1f; 性能调优世界是一个危险的地方&#xff0c;一个JVM标志失衡&#xff0c;事情很快就会变得繁琐。 因此 &#xff0c;我们决定求助于Java性能调优专家&#xff0c; 单调 JVM探查器mjprof的创…

java的构造函数详解,Java构造函数与普通函数用法详解

函数也被称为方法&#xff01;函数的作用及特点&#xff1a;1、用于定义功能&#xff0c;将功能封装。2、可以提高代码的复用性。函数注意事项&#xff1a;1、不能进行函数套用(不可以在函数内定义函数)。2、函数只有被调用才能被执行。3、基本数据类型(String、int、….)修饰的…

c语言中函数的声明和定义

点击上方蓝字关注我&#xff0c;了解更多咨询1、函数声明&#xff0c;无需实现该函数的功能。函数声明只是一个空壳&#xff0c;不会有特定的函数实现。2、函数定义&#xff0c;必须实现该函数的功能&#xff0c;要实现函数的实现。#include<stdio.h>实例//使用函数前&am…

bean注入属性_摆脱困境:将属性值注入配置Bean

bean注入属性Spring Framework对将从属性文件中找到的属性值注入到bean或Configuration类中提供了很好的支持。 但是&#xff0c;如果将单个属性值注入这些类中&#xff0c;则会遇到一些问题。 这篇博客文章指出了这些问题&#xff0c;并描述了我们如何解决它们。 让我们开始…

php 浏览器 打印控件,JavaScript_JavaScript 实现打印,打印预览,打印设置,WebBrowser是IE内置的浏览器控件 - phpStudy...

JavaScript 实现打印,打印预览,打印设置WebBrowser是IE内置的浏览器控件&#xff0c;无需用户下载.一、WebBrowser控件二、WebBrowder控件的方法 //打印WebBrowser1.ExecWB(6,1);//打印设置WebBrowser1.ExecWB(8,1);//打印预览WebBrowser1.ExecWB(7,1);关于这个组件还有其他的用…

c语言中常规函数和指针函数区别

点击上方蓝字关注我&#xff0c;了解更多咨询1、在函数名前面多了一个*号&#xff0c;而这个函数就是一个指针函数。2、其返回值是一个int类型的指针&#xff0c;是一个地址。实例#include<stdio.h>int* fun1(int* x) //传入指针 {int* tmp x; //指针tmp指向xret…

jvm崩溃的原因_JVM崩溃时:如何调查最严重错误的根本原因

jvm崩溃的原因当应用程序崩溃时&#xff0c;您可以学到什么&#xff1f; 我认为&#xff0c;“后见之明是20 /”是最喜欢的短语之一托马斯罗梅尔 &#xff0c;工程ZeroTurnaround的副总裁。 好吧&#xff0c;我实际上不确定在他的短语中占什么位置&#xff0c;但是我已经听过他…

golang web php,GitHub - kai-xx/goWeb: golang web 接口实现 -- 类似PHP的laravel

goWebgorose ormdotweb框架实现接口 -- 类似PHP的laravel项目结构说明因为 gorose orm 和 dotweb 框架 都是基于独立的组件, 所以我们可以对项目的目录做出自由的规划.在这里, 我们便规划一个遵循一般的mvc结构的项目目录.为了项目的易维护性和高可用性, 我们尽量采取成熟的架构…

jboss项目导入idea_JBoss BPM Suite快速指南–将外部数据模型导入BPM项目

jboss项目导入idea您正在从事一个大项目&#xff0c;在企业中开发规则&#xff0c;事件和流程以满足关键业务需求。 部分要求指出&#xff0c;某个业务部门将提供您的数据模型供您利用。 不会在JBoss BPM Suite数据建模器中设计此数据模型&#xff0c;但是在从业务中心仪表板…

mysql协议重传,MySQL · 源码分析 · 网络通信模块浅析

MySQL 网络通信浅析MySQL的网络通信协议主要包含以下几个层次&#xff0c;从最上层的MySQL数据包协议层到最底层的socket传输&#xff1a;| THD| Protocol| NET| VIO| SOCKET本文主要扫一下相关的代码&#xff0c;以下分析基于MySQL5.7。创建会话在MySQL5.7中对会话协议层的代码…

C语言代码优化11种实用方法

点击蓝字关注我1、选择合适的算法和数据结构选择一种合适的数据结构很重要&#xff0c;如果在一堆随机存放的数中使用了大量的插入和删除指令&#xff0c;那使用链表要快得多。数组与指针语句具有十分密切的关系&#xff0c;一般来说&#xff0c;指针比较灵活简洁&#xff0c;而…

spring boot注释_使用Spring Boot和注释支持配置Spring JMS应用程序

spring boot注释1.简介 在以前的文章中&#xff0c;我们学习了如何使用Spring JMS配置项目。 如果查看有关使用Spring JMS进行消息传递的文章介绍 &#xff0c;您会注意到它是使用XML配置的。 本文将利用Spring 4.1版本中引入的改进 &#xff0c;并仅使用Java config配置JMS项目…

obendclean php命令,ob_end_clean

用户评论:[#1]Sam Yong - hellclanner at live dot com [2011-05-04 22:14:35]Take note that if you change zlib output compression setting in between ob_start and ob_end_clean or ob_end_flush, you will get an error: ob_end_flush() failed to delete buffer zlib o…

C语言 | 简单工厂方法模式实现例子

点击蓝字关注我们1、简介简单工厂方法定义一个用于创建对象的类&#xff0c;该类接受一个参数&#xff0c;通过参数决定创建不同的对象。GOF并没有把简单工厂方法定义为23种设计模式之一&#xff0c;可以认为简单工厂方法是工厂方法的简化形式。为了体现简单工厂方法和工厂方法…

grpc 流式传输_编写下载服务器。 第一部分:始终流式传输,永远不要完全保留在内存中...

grpc 流式传输下载各种文件&#xff08;文本或二进制文件&#xff09;是每个企业应用程序的生死攸关的事情。 PDF文档&#xff0c;附件&#xff0c;媒体&#xff0c;可执行文件&#xff0c;CSV&#xff0c;超大文件等。几乎每个应用程序迟早都必须提供某种形式的下载。 下载是通…

matlab plot errorbar,如何为MATLAB errorbar plot的点和垂直线设置不同的图例?

这建立在Jens Boldsen’s answer之上,它添加了以下内容&#xff1a;>可以旋转表示图例中错误栏的线条使其垂直,或保持默认的水平方向;>该行的末尾用短线“关闭”.该方法非常通用,因为它支持&#xff1a;>任意颜色,线型和标记作为错误栏的参数.请注意,实际条形图始终绘…

C语言 / C++基础面试知识大集合

点击蓝字关注我们相对而言&#xff0c;C语言和C相关的面试题比较少见&#xff0c;没有Java方向写的人那么多&#xff0c;这是一篇 C 语言与 C面试知识点总结的文章&#xff0c;个人感觉非常难得&#xff0c;希望能对大家有所帮助。const作用修饰变量&#xff0c;说明该变量不可…

input发送a.jax_Java REST JAX-RS 2.0 –如何处理日期,时间和时间戳记数据类型

input发送a.jax无论是X-Form-Urlencoded还是JSON HTTP发布到REST资源端点&#xff0c;对于与日期或时间相关的数据都没有特定的“数据类型”。 大多数开发人员会将这些数据发布为“字符串”&#xff0c;或者只是将它们转换为Unix时间戳值&#xff08;例如1435061152&#xff09…