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

欢迎回到我们的教程系列“带有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请求。

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

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

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

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

相关文章

关于创业公司的一些事情

最近终于离职了&#xff0c;离开了这家呆了快两年的公司&#xff0c;其中酸甜苦辣&#xff0c;不足为外人道&#xff0c;仅此记录下一些想法&#xff0c;供自己与大家思考。本文只讨论加入创业公司&#xff0c;并不讨论自己创业或者成为合伙人。 0. 该不该加入创业公司 我刚从研…

python时间去掉t_Python的set集合详解

Python 还包含了一个数据类型 —— set &#xff08;集合&#xff09;。 集合是一个无序不重复元素的集。基本功能包括关系测试和消除重复元素。 集合对象还支持 union&#xff08;联合&#xff09;&#xff0c;intersection&#xff08;交&#xff09;&#xff0c;difference&…

快乐学习 Ionic Framework+PhoneGap 手册1-3 {面板切换}

编程的快乐和乐趣&#xff0c;来自于能成功运行程序并运用到项目中,会在后面案例&#xff0c;实际运用到项目当中与数据更新一起说明 从面板切换开始&#xff0c;请看效果图和代码&#xff0c;这只是一个面板切换的效果 Index HTML Code <!DOCTYPE html> <html ng-ap…

去掉左边0_SLAM从0到1——11. 视觉里程计VO内容框架

「本文是之前学习VO 部分整理的思维导图&#xff0c;笔记写入之后均折叠了起来&#xff0c;正文中采用markdown格式展开&#xff0c;可看到笔记内容」放上来的目的其实是方便自己查阅笔记&#xff0c;同样给有需要的同学提供一点思路。整体上的结构分为5部分&#xff0c;包括常…

教程:如何实现Java OAuth 2.0以使用GitHub和Google登录

将Google和GitHub OAuth登录添加到Java应用程序的指南 我们添加到Takipi的最新功能之一是3rd party登录。 如果您像我一样懒惰&#xff0c;那么我想您也希望跳过填写表单和输入新密码的操作 。 只要有权限&#xff0c;许多人都希望使用第三方登录&#xff0c;只要他们要求的权…

工作生活随笔

11月10日&#xff1a;最近在看设计模式&#xff0c;争取把23种设计模式都用php写个示例。但是网上php实现的还是比较少&#xff0c;而且就算有例子也不太满意&#xff0c;倒是其他语言写的还不错。于是最近看了很多其他的语言编写的程序&#xff0c;其实都差不多。以后如果有时…

柔性太阳能电池pdf_房车旅行如何做到电力无忧,那就选择一套合适的太阳能供电系统吧...

“旅行途中房车电力够不够用&#xff1f;”是众多车友在购买房车时会考虑的因素之一。而房车外部供电方式一般有三种&#xff1a;电网供电、发电机发电和太阳能发电&#xff0c;其中太阳能发电因其结构简单、体积小且轻、易安装、维护简单、寿命长不易损坏、一次性投资、循环利…

POJ 3617

题意&#xff1a;给定长度为N的字符串S&#xff0c;现要构造一个字符串T&#xff08;起初为空串&#xff09;。任意进行一下的一种操作&#xff1a; 1>从S的头部删除一个字符&#xff0c;加到T的尾部 2>从S的尾部删除一个字符&#xff0c;加到T的尾部 目的使T的字典序最小…

echarts的词云图表类型有哪些_数据可视化之常见12种图表类型分析

数据可视化有众多展现方式&#xff0c;不同的数据类型要选择适合的展现方法&#xff0c;今天友创云天就整理分析了几种常见的类型&#xff0c;给大家提供参考。1.饼图饼图是一个划分为几个扇形的圆形统计图表。每个扇形的弧长&#xff08;以及圆心角和面积&#xff09;大小&…

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

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

两个饥肠咕咕的人

http://www.amznz.com/43/ Long long ago&#xff0c;有两个饥肠咕咕的人得到了一位长者的恩赐&#xff1a;一根鱼竿和一篓鲜活硕大的鱼。其中&#xff0c;一个人要了一篓鱼&#xff0c;另一个人要了一根鱼竿&#xff0c;于是他们分道扬镳了。得到鱼的人原地就用干柴搭起篝火煮…

室内主题元素分析图_2020届室内设计专业优秀毕业设计作品展(五)

“环”食疗养生空间概念设计△建筑外立面▲LOGO前 言每当人们提及健康时&#xff0c;人们的反应往往是运动、睡眠和饮食。现代的青年上班族&#xff0c;又因为快节奏的生活&#xff0c;工作压力大&#xff0c;饮食的不规律&#xff0c;生活不良习性的增加&#xff0c;导致了各…

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

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

C++输入cin详解

C输入cin详解 输入原理&#xff1a; 程序的输入都建有一个缓冲区&#xff0c;即输入缓冲区。一次输入过程是这样的&#xff0c;当一次键盘输入结束时会将输入的数据存入输入缓冲区&#xff0c;而cin函数直接从输入缓冲区中取数据。正因为cin函数是直接从缓冲区取数据的&#xf…

时间序列的截尾和拖尾_R语言:时间序列(一)

01 解决什么问题在社会活动中经常可见按照时间顺序记录下来的随机事件观察值&#xff0c;例如每年死亡人数序列&#xff0c;每年糖尿病发病人数序列&#xff0c;医院门诊每日诊治病例数序列。这类数据的特性是相邻时间点的观察值之间具有明显的相关性&#xff0c;这一特性不同于…

ulimit小结

1. limits是一个进程的资源&#xff0c;会被子进程继承2. soft limit -S, hard limits -Hhard limits只能被root用户修改&#xff0c;启动的时候会加载配置/etc/security/limits.confsoft limits可以被任何用户修改&#xff0c;但不能超过hard limits3. 在linux下&#xff0c;每…

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

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

常用个人密码管理软件

http://www.williamlong.info/archives/3100.html转载于:https://www.cnblogs.com/svennee/p/4099358.html

查看网口命令_20个常用Linux命令

今天总结几个非常常用的Linux命令,其中有几个在面试中很可能问相关命令的原理,比如后台运行命令。希望对大家有所帮助,最好自己去尝试在Linux操作系统中实践一下。 1、查看目录以及权限 在windows中,使用dir查看当前目录中文件。在Linux中使用ls(list)查看当前目录文件。 w…

爱摘苹果的小明

描述小明家的院子里有一棵苹果树&#xff0c;每到秋天树上就会结出10个苹果。苹果成熟的时候&#xff0c;小明就会跑去摘苹果。小明有个30厘米高的板凳&#xff0c;当她不能直接用手摘到苹果的时候&#xff0c;就会踩到板凳上再试试。现在已知10个苹果到地面的高度&#xff0c;…