EclipseLink , эталонная реализация JPA, имеет поддержку JPA для баз данных NoSQL (MongoDB и Oracle NoSQL) начиная с версии 2.4. В этом руководстве мы обсудим использование базы данных MongoDB с поддержкой JPA EclipseLink. Транзакция, ранее выполненная с использованием консоли и собственного драйвера java, будет выполнена в веб-приложении с помощью EclipseLink.
Инструменты и технологии, используемые в примере приложения, следующие:
- MongoDB версия 2.4.1
- MongoDB Java Driver версия 2.11.1
- JSF версия 2.2
- PrimeFaces версия 3.5
- EclipseLink версия 2.4
- Jetty 7.x Maven Плагин
- JDK версия 1.7
- Maven 3.0.4
Зависимости проекта
<dependency> <groupId>org.glassfish</groupId> <artifactId>javax.faces</artifactId> <version>2.2.0-SNAPSHOT</version> </dependency> <dependency> <groupId>org.primefaces</groupId> <artifactId>primefaces</artifactId> <version>3.5</version> </dependency> <dependency> <groupId>org.primefaces.themes</groupId> <artifactId>bootstrap</artifactId> <version>1.0.10</version> </dependency> <dependency> <groupId>org.eclipse.persistence</groupId> <artifactId>org.eclipse.persistence.jpa</artifactId> <version>2.4.0-SNAPSHOT</version> </dependency> <dependency> <groupId>org.eclipse.persistence</groupId> <artifactId>org.eclipse.persistence.nosql</artifactId> <version>2.4.0-SNAPSHOT</version> </dependency> <dependency> <groupId>jboss</groupId> <artifactId>jboss-j2ee</artifactId> <version>4.2.2.GA</version> </dependency> <dependency> <groupId>org.mongodb</groupId> <artifactId>mongo-java-driver</artifactId> <version>2.11.1</version> </dependency> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3</version> </dependency>
Класс сущности
@Entity
@NoSql(dataFormat=DataFormatType.MAPPED)
public class Article implements Serializable {
public Article() {
}
@Id
@GeneratedValue
@Field(name="_id")
private String id;
@ElementCollection
private List<Categories> categoryLists = new ArrayList<Categories>();
@Basic
private String title;
@Basic
private String content;
@Basic
@Temporal(javax.persistence.TemporalType.DATE)
private Date date;
@Basic
private String author;
@ElementCollection
private List<Tags> tagLists = new ArrayList<Tags>();
Нотация @NoSQL устанавливает формат и тип данных и отображает данные NoSQL. Из-за использования MongoDB в нашем примере приложения и документов в MongoDB, хранящихся в
формате BSON ,
MAP используется в качестве типа данных.
Нотация @ElementCollection отображает встроенную коллекцию в родительский документ. Так как в нашем примере приложения было бы более одной категории и тега, связанных со статьей, мы отображаем их как коллекцию элементов.
Встроенные объекты
@Embeddable
@NoSql(dataFormat=DataFormatType.MAPPED)
public class Categories implements Serializable {
@Basic
private String category;
@Embeddable
@NoSql(dataFormat=DataFormatType.MAPPED)
public class Tags implements Serializable {
@Basic
private String tag;
Мы видим
нотацию @Embeddable вверху класса
Categories и
Tags в отличие от
класса сущности Article . Документы, хранящиеся в родительском документе, отображаются в этой записи.
Обратите внимание, что встроенные объекты не нуждаются в уникальном поле.
persistence.xml
<?xml version="1.0" encoding="UTF-8" ?>
<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"
version="2.0" xmlns="http://java.sun.com/xml/ns/persistence">
<persistence-unit name="kodcuMongo" transaction-type="RESOURCE_LOCAL">
<class>com.kodcu.entity.Article</class>
<class>com.com.kodcu.entity.Categories</class>
<class>com.kodcu.entity.Tags</class>
<properties>
<property name="eclipselink.target-database"
value="org.eclipse.persistence.nosql.adapters.mongo.MongoPlatform"/>
<property name="eclipselink.nosql.connection-spec"
value="org.eclipse.persistence.nosql.adapters.mongo.MongoConnectionSpec"/>
<property name="eclipselink.nosql.property.mongo.port" value="27017"/>
<property name="eclipselink.nosql.property.mongo.host" value="localhost"/>
<property name="eclipselink.nosql.property.mongo.db" value="kodcu"/>
<property name="eclipselink.logging.level" value="FINEST"/>
</properties>
</persistence-unit>
</persistence>
CRUD Операции
<h:form id="articleForm">
<p:growl id="growl"/>
<h:panelGrid columns="2" cellpadding="2" cellspacing="2">
<p:panel styleClass="registrationForm" header="Registration Form">
<h:panelGrid id="registrationPanelGrid" columns="2" cellpadding="2" cellspacing="2">
<h:outputLabel value="Category"/>
<p:inputText value="#{myBean.categories}" styleClass="inputTextWidth"/>
<h:outputLabel value="Title"/>
<p:inputText value="#{myBean.article.title}" required="#{param['saveArticle']=='true'}" requiredMessage="The title field is required." styleClass="inputTextWidth"/>
<h:outputLabel value="Content"/>
<p:inputTextarea value="#{myBean.article.content}" required="#{param['saveArticle']=='true'}" requiredMessage="The content field is required." styleClass="inputTextAreaWidthHeight"/>
<h:outputLabel value="Author"/>
<p:inputText value="#{myBean.article.author}" required="#{param['saveArticle']=='true'}" requiredMessage="The author field is required." styleClass="inputTextWidth"/>
<h:outputLabel value="Tags"/>
<p:inputText value="#{myBean.tags}" styleClass="inputTextWidth" />
</h:panelGrid>
</p:panel>
<p:panel header="Article Directory" styleClass="articleDirectory">
<p:dataTable id="articleTable" var="article" value="#{myBean.articleList}" selectionMode="single"
selection="#{myBean.selectArticle}" paginator="true" paginatorPosition="bottom" rows="5"
rowKey="#{article.id}">
<p:ajax event="rowSelect" listener="#{myBean.articleSelect}"
update=":articleForm:registrationPanelGrid :articleForm:removeArticle"/>
<p:column width="200">
<f:facet name="header">
<h:outputLabel value="Title"/>
</f:facet>
<h:outputLabel value="#{article.title}"/>
</p:column>
<p:column width="350">
<f:facet name="header">
<h:outputLabel value="Content"/>
</f:facet>
<h:outputLabel value="#{article.content}"/>
</p:column>
<p:column width="200">
<f:facet name="header">
<h:outputLabel value="Author"/>
</f:facet>
<h:outputLabel value="#{article.author}"/>
</p:column>
<p:column width="40">
<f:facet name="header">
<h:outputLabel value="Date"/>
</f:facet>
<h:outputLabel value="#{article.date}">
<f:convertDateTime pattern="dd/MM/yyyy"/>
</h:outputLabel>
</p:column>
</p:dataTable>
</p:panel>
<h:panelGroup>
<p:commandButton id="newArticle" action="#{myBean.initArticle}" value="New"
update="registrationPanelGrid articleTable removeArticle"/>
<p:commandButton id="saveArticle" action="#{myBean.saveArticle}" value="Save"
update="registrationPanelGrid articleTable growl">
<f:param name="saveArticle" value="true"/>
</p:commandButton>
<p:commandButton id="removeArticle" disabled="#{null == myBean.selectArticle}" action="#{myBean.removeArticle}"
value="Remove" update="registrationPanelGrid articleTable @this"/>
</h:panelGroup>
</h:panelGrid>
</h:form>
MyBean.java
public void saveArticle() {
em.getTransaction().begin();
if(null == article.getId())
em.persist(article);
else
em.merge(article);
em.getTransaction().commit();
}
public void removeArticle() {
em.getTransaction().begin();
em.remove(selectArticle);
em.getTransaction().commit();
}
6. Демо-приложение
Реальный контент выше и демонстрационное приложение, могут быть доступны в
NoSQL с JPA
