Spring Data,MongoDB和JSF集成教程

示例应用程序简介(MongoShop产品目录)

在学习完本教程之后,将构建具有以下功能要求的示例应用程序(MongoShop产品目录):

1.搜索具有不同条件的产品(例如,sku,产品类型,标题,stc)

2.创建具有不同类别的新产品。

3.编辑选定的产品详细信息

4.从查询屏幕删除选定的产品。

表示层:

JSF在此示例应用程序中用作表示层技术。 PrimeFaces是用于增强JSF UI的轻量级组件之一。 前端交互由该层中的JSF支持bean控制。

服务层:

使用Spring管理的单例服务对象。 业务服务和应用程序逻辑编写在此层中

数据层:

使用Spring数据MongoDB组件。 它提供了与MongoDB面向文档的数据库的集成。 它提供了MongoTemplate,以便可以轻松执行MongoDB操作。 而且,Spring存储库样式数据访问层可以使用Spring数据MongoDB轻松编写。

MongoDB模式设计和数据准备

MongoDB简介

MongoDB是一个开源可扩展的高性能NoSQL数据库。 它是一个面向文档的存储。 它可以存储具有动态模式的JSON样式的文档。 在此应用程序中,每个产品都以JSON样式的文档存储在MongoDB中。

MongoDB中的架构设计

目录中的每个产品均包含常规产品信息(例如,sku,标题和产品类型),价格详细信息(例如,零售价格和标价)和产品子详细信息(例如,音频CD的曲目/书籍的章节)。 在此应用程序中,使用MongoDB。 模式设计将更侧重于数据使用。 它与传统的RDBMS模式设计不同。 MongoDB中的架构设计应为:

样本数据:
x= {
  sku: '1000001',
  type: 'Audio Album',
  title: 'A Love Supreme',
  description: 'by John Coltrane',
  publisher: 'Sony Music',
  pricing: {
    list: 1200,
    retail: 1100
  },

  details: {
    title: 'A Love Supreme [Original Recording Reissued]',
    artist: 'John Coltrane',
    genre:  'Jazz' ,
    tracks: [
      'A Love Supreme Part I: Acknowledgement',
      'A Love Supreme Part II - Resolution',
      'A Love Supreme, Part III: Pursuance',
      'A Love Supreme, Part IV-Psalm'
    ],
  }
}

y= {
  sku: '1000002',
  type: 'Audio Album',
  title: 'Love Song',
  description: 'by Khali Fong',
  publisher: 'Sony Music',
  pricing: {
    list: 1000,
    retail: 1200
  },

  details: {
    title: 'Long Song [Original Recording Reissued]',
    artist: 'Khali Fong',
    genre:  'R&B',
    tracks: [
      'Love Song',
      'Spring Wind Blow',
      'Red Bean',
      'SingAlongSong'
    ],
  }
}

z= {
  sku: '1000003',
  type: 'Book',
  title: 'Node.js for PHP Developers',
  description: 'by Owen Peter',
  publisher: 'OReilly Media',

  pricing: {
    list: 2500,
    retail: 2100
  },

  details: {
    title: 'Node.js for PHP Developers',
    author: 'Mark Owen',
    genre:  'Technology',
    chapters: [
      'Introduction to Node',
      'Server-side JS',
      'PHP API',
      'Example'
    ],
  }
}
示例查询以添加数据:
db.product.save(x);
db.product.save(y);
db.product.save(z);
示例查询以测试示例数据:
db.product.find({'sku':'1000004'});
db.product.find({'type':'Audio Album'});
db.product.find({'type':'Audio Album', 'details.genre': 'Jazz'});

JSF(PrimeFaces)和Spring数据MongoDB集成

项目的pom.xml
<project xmlns='http://maven.apache.org/POM/4.0.0' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
  xsi:schemaLocation='http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd'>
  <modelversion>4.0.0</modelVersion>
  <groupid>com.borislam</groupId>
  <artifactid>mongoShop</artifactId>
  <packaging>war</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>MongoShop Webapp</name>
  <url>http://maven.apache.org</url>
  <dependencies>
  <dependency>
     <groupid>org.jboss.el</groupId>
     <artifactid>com.springsource.org.jboss.el</artifactId>
     <version>2.0.0.GA</version>
 </dependency>
    <dependency>  
     <groupid>org.primefaces.themes</groupId>  
     <artifactid>all-themes</artifactId>  
     <version>1.0.9</version>  
    </dependency>
    <dependency>  
  <groupid>org.primefaces</groupId>  
  <artifactid>primefaces</artifactId>  
  <version>3.4.2</version>  
 </dependency>
 <dependency>
  <groupid>commons-beanutils</groupId>
  <artifactid>commons-beanutils</artifactId>
  <version>1.8.3</version>
 </dependency> 

 <dependency>
  <groupid>commons-codec</groupId>
  <artifactid>commons-codec</artifactId>
  <version>1.3</version>
 </dependency> 

 <dependency>
  <groupid>org.apache.directory.studio</groupId>
  <artifactid>org.apache.commons.lang</artifactId>
  <version>2.6</version>
 </dependency>

 <dependency>
  <groupid>commons-digester</groupId>
  <artifactid>commons-digester</artifactId>
  <version>1.8</version>
 </dependency>

 <dependency>
  <groupid>commons-collections</groupId>
  <artifactid>commons-collections</artifactId>
  <version>3.2</version>
 </dependency>

 <dependency>
  <groupid>org.apache.myfaces.core</groupId>
  <artifactid>myfaces-api</artifactId>
  <version>2.1.9</version>
 </dependency>

 <dependency>
  <groupid>org.apache.myfaces.core</groupId>
  <artifactid>myfaces-impl</artifactId>
  <version>2.1.9</version>
 </dependency>

   <dependency>
  <groupid>org.mongodb</groupId>
  <artifactid>mongo-java-driver</artifactId>
  <version>2.10.1</version>
 </dependency>
    <dependency>
      <groupid>junit</groupId>
      <artifactid>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
 <dependency>
  <groupid>org.springframework.data</groupId>
  <artifactid>spring-data-mongodb</artifactId>
  <version>1.0.3.RELEASE</version>
 </dependency> 
 <dependency>
   <groupid>org.springframework</groupId>
   <artifactid>spring-context</artifactId>
   <version>3.2.0.RELEASE</version>
 </dependency> 
 <dependency>
   <groupid>org.springframework</groupId>
   <artifactid>spring-web</artifactId>
   <version>3.2.0.RELEASE</version>
 </dependency>
  </dependencies>
  <repositories>
    <repository>
  <id>java.net</id>
  <url>https://maven.java.net/content/repositories/public/</url>
    </repository>
 <repository>  
  <id>prime-repo</id>  
  <name>PrimeFaces Maven Repository</name>  
  <url>http://repository.primefaces.org</url>  
  <layout>default</layout>  
 </repository>

 <repository>
  <id>com.springsource.repository.bundles.release</id>
  <name>SpringSource Enterprise Bundle Repository - SpringSource Releases</name>
  <url>http://repository.springsource.com/maven/bundles/release</url>
 </repository>

 <repository>
  <id>com.springsource.repository.bundles.external</id>
  <name>SpringSource Enterprise Bundle Repository - External Releases</name>
  <url>http://repository.springsource.com/maven/bundles/external</url>
 </repository>
 <repository>
         <releases>
           <enabled>false</enabled>
         </releases>
         <snapshots>
           <enabled>true</enabled>
         </snapshots>
         <id>apache.snapshots</id>
         <name>Apache Snapshot Repository</name>
         <url>https://repository.apache.org/content/repositories/snapshots</url>
    </repository> 
 <repository>
          <id>jboss-deprecated-repository</id>
          <name>JBoss Deprecated Maven Repository</name>
          <url>https://repository.jboss.org/nexus/content/repositories/deprecated/</url>
          <layout>default</layout>
          <releases>
            <enabled>true</enabled>
            <updatepolicy>never</updatePolicy>
          </releases>
          <snapshots>
            <enabled>false</enabled>
            <updatepolicy>never</updatePolicy>
          </snapshots>
        </repository>
  </repositories>
  <build>
    <finalname>mongoShop</finalName>
  </build>
</project>
我的脸

MyFaces用作此应用程序中的JSF实现。 以下详细信息应添加到web.xml中

PrimeFaces主题

如前所述,PrimeFaces库用于增强UI。 该库几乎不需要配置。 PrimeFaces为您的Web应用程序提供了许多预先设计的主题。 在本例中,我们使用“蓝天”主题。 我们只是在web.xml中添加以下设置

<context-param>
  <param-name>primefaces.THEME</param-name><param-value>glass-x</param-value></context-param>
JSF和Spring集成:

要将JSF与Spring集成,必须在Faces-config.xml中指定SpringBeanFacesELResolver

Faces-config.xml

<?xml version='1.0' encoding='UTF-8'?>
<faces-config version='2.0' xmlns='http://java.sun.com/xml/ns/javaee'
  xmlns:xi='http://www.w3.org/2001/XInclude'
  xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' 
  xsi:schemaLocation='http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd'>
   <application>
     <el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
   </application>
   <factory>
 <partial-view-context-factory>org.primefaces.context.PrimePartialViewContextFactory</partial-view-context-factory>
   </factory> 
</faces-config>

完整的web.xml

<?xml version='1.0' encoding='UTF-8'?>
<web-app id='WebApp_ID' version='3.0'
 xmlns='http://java.sun.com/xml/ns/javaee'
 xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' 
 xsi:schemaLocation='http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd'>
 <context-param>
 <param-name>contextConfigLocation</param-name><param-value>WEB-INF/spring-application-context.xml</param-value></context-param>
 <context-param>
  <param-name>errorPageUrl</param-name><param-value>/pages/systemError.do</param-value></context-param>
 <context-param>
  <param-name>facelets.DEVELOPMENT</param-name><param-value>false</param-value></context-param>
 <context-param>
   <param-name>facelets.REFRESH_PERIOD</param-name><param-value>2</param-value></context-param>
 <context-param>
   <param-name>javax.faces.STATE_SAVING_METHOD</param-name><param-value>client</param-value></context-param>
 <context-param>
   <param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name><param-value>resources.application</param-value></context-param>
 <context-param>
   <param-name>org.apache.myfaces.ALLOW_JAVASCRIPT</param-name><param-value>true</param-value></context-param>
  <context-param>
    <param-name>org.apache.myfaces.AUTO_SCROLL</param-name><param-value>false</param-value></context-param>
 <context-param>
    <param-name>org.apache.myfaces.DETECT_JAVASCRIPT</param-name><param-value>false</param-value></context-param>
 <context-param>
  <param-name>org.apache.myfaces.ERROR_HANDLING</param-name><param-value>false</param-value></context-param>
 <context-param>
  <param-name>org.apache.myfaces.EXPRESSION_FACTORY</param-name><param-value>org.jboss.el.ExpressionFactoryImpl</param-value></context-param>
 <context-param>
  <param-name>org.apache.myfaces.PRETTY_HTML</param-name><param-value>false</param-value></context-param>
 <context-param>
  <param-name>primefaces.THEME</param-name><param-value>glass-x</param-value></context-param>  
 <servlet>
   <servlet-name>Faces Servlet</servlet-name>
   <servlet-class>org.apache.myfaces.webapp.MyFacesServlet</servlet-class>
   <load-on-startup>1</load-on-startup>
  </servlet>
 <servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>*.jsf</url-pattern>
 </servlet-mapping>
 <listener>
 <listener-class>org.apache.myfaces.webapp.StartupServletContextListener</listener-class>
 </listener>
 <listener>
 <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
 </listener>
</web-app>

MongoDB连接详细信息

为了连接到MongoDB,您必须以XML注册MongoDbFactory实例。 连接详细信息在spring-application-context.xml中指定

spring-application-context.xml
<?xml version='1.0' encoding='UTF-8'?>
<beans xmlns='http://www.springframework.org/schema/beans'
xmlns:context='http://www.springframework.org/schema/context'
 xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
 xmlns:util='http://www.springframework.org/schema/util'
 xmlns:mongo='http://www.springframework.org/schema/data/mongo'
 xsi:schemaLocation='http://www.springframework.org/schema/beans        
    http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
          http://www.springframework.org/schema/data/mongo
          http://www.springframework.org/schema/data/mongo/spring-mongo.xsd            
              http://www.springframework.org/schema/data/repository
    http://www.springframework.org/schema/data/repository/spring-repository.xsd 
             http://www.springframework.org/schema/context
                http://www.springframework.org/schema/context/spring-context-3.2.xsd
                http://www.springframework.org/schema/util 
                http://www.springframework.org/schema/util/spring-util-3.2.xsd'>

 <context:annotation-config/>
 <context:component-scan base-package='com.borislam'/>

 <mongo:mongo host='localhost' port='27017'> 
  <mongo:options
       connections-per-host='5'       
       connect-timeout='30000'
       max-wait-time='10000'       
       write-number='1'
       write-timeout='0'
       write-fsync='true'/>
 </mongo:mongo>

 <mongo:db-factory dbname='test' mongo-ref='mongo'/>

 <mongo:repositories base-package='com.borislam.repository' />

 <bean id='mongoTemplate' class='org.springframework.data.mongodb.core.MongoTemplate'>
     <constructor-arg ref='mongo'/><constructor-arg name='databaseName' value='test'/></bean>
</beans>

使用Spring Data Repository和MongoTemplate来查询数据

Spring资料储存库:

Spring数据存储库抽象减少了用于编写应用程序数据访问层的样板代码。 Repository接口的自动实现提供了对mongoDB的简单操作。 它有助于我们的产品保存和删除功能,使

MongoTemplate:

MongoTemplate提供了方便的操作来创建,更新,删除和查询MongoDB文档,并提供了域对象和MongoDB文档之间的映射。 在我们的应用程序中,由于spring数据存储库无法满足搜索功能的要求,因此我们使用MongoTemplate来归档搜索功能。

自定义Spring数据存储库:

由于无法通过Spring数据存储库抽象轻松地实现产品搜索,因此我们想使用MongoDBTemplate实现多级Criteira产品搜索。 为了使用MongoTemplate丰富Spring数据存储库,我们可以执行以下操作来定制存储库:

ProductRepository.java
package com.borislam.repository;

import java.util.List;
import org.springframework.data.repository.PagingAndSortingRepository;
import com.borislam.domain.Product;

public interface ProductRepository  extends PagingAndSortingRepository<Product, String> , ProductRepostitoryCustom{

 List<product> findByType(String type);
 List<product> findByTypeAndTitle(String type, String title); 
 Product findBySku(String sku);
}
ProductRepositoryCustom.java
package com.borislam.repository;

import java.util.List;
import com.borislam.domain.Product;
import com.borislam.view.ProductSearchCriteria;

public interface ProductRepostitoryCustom {
 public List<product> searchByCriteria(ProductSearchCriteria criteria);

}
ProductRepositoryImpl.java
package com.borislam.repository.impl;

import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.util.StringUtils;
import com.borislam.domain.Product;
import com.borislam.repository.ProductRepostitoryCustom;
import com.borislam.view.ProductSearchCriteria;

public class ProductRepositoryImpl implements ProductRepostitoryCustom{

 @Autowired
 private MongoTemplate mongoTemplate;

 @Override
 public List<product> searchByCriteria(ProductSearchCriteria criteria) {
  Query query = new Query();
  if ( StringUtils.hasText(criteria.getSku())) 
  { 
   Criteria c = Criteria.where('sku').is(criteria.getSku());
   query.addCriteria(c);
  }
  if (StringUtils.hasText(criteria.getTitle())) {
   Criteria c = Criteria.where('title').regex('.*' + criteria.getTitle() + '.*', 'i');
   query.addCriteria(c);
  }
  if (StringUtils.hasText(criteria.getDescription())) {
   Criteria c = Criteria.where('description').regex('.*' + criteria.getDescription() + '.*', 'i');
   query.addCriteria(c);
  }
  if (StringUtils.hasText(criteria.getProductType())) {
   Criteria c = Criteria.where('type').is(criteria.getProductType());
   query.addCriteria(c);

  }  
  if (StringUtils.hasText(criteria.getTrack())) {
   Criteria c = Criteria.where('details.tracks').regex('.*' + criteria.getTrack() + '.*', 'i');
   query.addCriteria(c);
  }
  if (StringUtils.hasText(criteria.getChapter())) {
   Criteria c = Criteria.where('details.chapters').regex('.*' + criteria.getChapter() + '.*', 'i');
   query.addCriteria(c);
  }
  return mongoTemplate.find(query, Product.class);
 }

}
数据模型:Product.java
package com.borislam.domain;

public class Product {
  private String id;
  private String sku ;
  private String  type;
  private String title;
  private String description;
  private String publisher;
  private Pricing pricing;
  private Detail details;
 public String getId() {
  return id;
 }
 public void setId(String id) {
  this.id = id;
 }
 public String getSku() {
  return sku;
 }
 public void setSku(String sku) {
  this.sku = sku;
 }
 public String getType() {
  return type;
 }
 public void setType(String type) {
  this.type = type;
 }
 public String getTitle() {
  return title;
 }
 public void setTitle(String title) {
  this.title = title;
 }
 public String getDescription() {
  return description;
 }
 public void setDescription(String description) {
  this.description = description;
 }
 public String getPublisher() {
  return publisher;
 }
 public void setPublisher(String publisher) {
  this.publisher = publisher;
 }
 public Pricing getPricing() {
  return pricing;
 }
 public void setPricing(Pricing pricing) {
  this.pricing = pricing;
 }
 public Detail getDetails() {
  return details;
 }
 public void setDetails(Detail details) {
  this.details = details;
 }    
}
Pricing.java
package com.borislam.domain;

public class Pricing {
 private String id;
 private double list;
 private double retail;
 public String getId() {
  return id;
 }
 public void setId(String id) {
  this.id = id;
 }
 public double getList() {
  return list;
 }
 public void setList(double list) {
  this.list = list;
 }
 public double getRetail() {
  return retail;
 }
 public void setRetail(double retail) {
  this.retail = retail;
 }
 public Pricing(double list, double retail) {
  super();
  this.list = list;
  this.retail = retail;
 }

}
Detail.java
package com.borislam.domain;

import java.util.List;

public class Detail {
 private String id;
 private String title;
 private String author;
 private String artist;
 private String genre;
 private List<string> pic;
 private List<string> chapters;
 private List<string> tracks;
 public String getTitle() {
  return title;
 }
 public void setTitle(String title) {
  this.title = title;
 }
 public String getAuthor() {
  return author;
 }
 public void setAuthor(String author) {
  this.author = author;
 }
 public String getGenre() {
  return genre;
 }
 public void setGenre(String genre) {
  this.genre = genre;
 }
 public List<string> getPic() {
  return pic;
 }
 public void setPic(List<string> pic) {
  this.pic = pic;
 }
 public List<string> getChapters() {
  return chapters;
 }
 public void setChapters(List<string> chapters) {
  this.chapters = chapters;
 }
 public String getId() {
  return id;
 }
 public void setId(String id) {
  this.id = id;
 }
 public String getArtist() {
  return artist;
 }
 public void setArtist(String artist) {
  this.artist = artist;
 }
 public List<string> getTracks() {
  return tracks;
 }
 public void setTracks(List<string> tracks) {
  this.tracks = tracks;
 }

}
JSF部分:common.xhtml
<html xmlns='http://www.w3.org/1999/xhtml'
 xmlns:h='http://java.sun.com/jsf/html'
 xmlns:f='http://java.sun.com/jsf/core'
 xmlns:ui='http://java.sun.com/jsf/facelets'
 xmlns:p='http://primefaces.org/ui'>

<f:view contentType='text/html'>

 <h:head>

  <f:facet name='first'>
   <meta http-equiv='Content-Type' content='text/html; charset=utf-8'/>
   <title><ui:insert name='pageTitle'>Page Title</ui:insert></title>
   <ui:insert name='head' />
  </f:facet>

 </h:head>

 <h:body>
  <div style='margin:auto;width:1024px;'>
<div id='header' class='ui-widget' >
<div id='logo' style='border:1px  solid #acbece; border-bottom: none; '>
<p:graphicImage   value='/resources/image/mongoshopheader.jpg'/></div>
<div id='logo' style='border:1px solid #acbece;'>
<p:menubar style='border:none'><p:menuitem value='Search' url='/search.jsf' icon='ui-icon-search' /><p:menuitem value='New Product' url='/detail.jsf' icon='ui-icon-document' /></p:menubar></div>
</div>
<div id='page' class='ui-widget' style='overflow:hidden;'>
<div id='content'  style='display:block'>
<ui:insert name='content'>...</ui:insert>     
             </div>
</div>
</div>
</h:body>

</f:view>
</html>
Search.xhml
<html xmlns='http://www.w3.org/1999/xhtml'
 xmlns:ui='http://java.sun.com/jsf/facelets'
 xmlns:h='http://java.sun.com/jsf/html'
 xmlns:f='http://java.sun.com/jsf/core'
 xmlns:p='http://primefaces.org/ui'>

 <ui:composition template='/template/common.xhtml'>

  <ui:define name='pageTitle'>
   <h:outputText value='Product Search' />
  </ui:define>

  <ui:define name='content'>
      <h:form id='searchForm'>
       <p:growl id='mainGrowl' sticky='true'  /><p:panelGrid style='width:1024px'><f:facet name='header'>
     <p:row><p:column colspan='4'>Product Search
             </p:column></p:row></f:facet>  
       <p:row><p:column><h:outputLabel for='sku' value='sku: ' />
         </p:column><p:column><p:inputText id='sku' value='#{productSearchBean.criteria.sku}' /></p:column><p:column><h:outputLabel for='productType' value='Product Type: ' />
         </p:column><p:column><p:selectOneMenu id='productType'   label='Type'   value='#{productSearchBean.criteria.productType}'  ><f:selectItem itemLabel='Select One' itemValue='' />  
                 <f:selectItem itemLabel='Audio Album' itemValue='Audio Album' />  
                 <f:selectItem itemLabel='Book' itemValue='Book' /> 
             </p:selectOneMenu></p:column></p:row><p:row><p:column><h:outputLabel for='title' value='Title: ' />
         </p:column><p:column><p:inputText id='title' value='#{productSearchBean.criteria.title}' /></p:column><p:column><h:outputLabel for='description' value='Description: ' />
         </p:column><p:column><p:inputText id='description' value='#{productSearchBean.criteria.description}' /></p:column></p:row><p:row><p:column><h:outputLabel for='track' value='Track: ' />
         </p:column><p:column><p:inputText id='track' value='#{productSearchBean.criteria.track}' /></p:column><p:column><h:outputLabel for='chapter' value='Chapter: ' />
         </p:column><p:column><p:inputText id='chapter' value='#{productSearchBean.criteria.chapter}' /></p:column></p:row></p:panelGrid><p:commandButton value='search' icon='ui-icon-search'  actionListener='#{productSearchBean.doSearch}' update='dataTable'/><hr/><p:dataTable id='dataTable' var='prod' value='#{productSearchBean.productList}'  
     paginator='true' rows='10'><p:column><f:facet name='header'>  
                    <h:outputText value='Sku' />  
                </f:facet>  
                <h:outputText value='#{prod.sku}' />  
            </p:column><p:column><f:facet name='header'>  
                    <h:outputText value='Type' />  
                </f:facet>  
                <h:outputText value='#{prod.type}' />  
            </p:column><p:column><f:facet name='header'>  
                    <h:outputText value='Title' />  
                </f:facet>  
                <h:outputText value='#{prod.title}' />  
            </p:column><p:column><f:facet name='header'>  
                    <h:outputText value='Publisher' />  
                </f:facet>  
                <h:outputText value='#{prod.publisher}' />  
            </p:column><p:column><f:facet name='header'>  
                    <h:outputText value='Artist' />  
                </f:facet>  
                <h:outputText value='#{prod.details.artist}' />  
            </p:column><p:column><f:facet name='header'>  
                    <h:outputText value='Author' />  
                </f:facet>  
                <h:outputText value='#{prod.details.author}' />  
            </p:column></p:dataTable></h:form>
  </ui:define>
 </ui:composition>
</html>
ProductSearchCriteria.java
package com.borislam.view;

public class ProductSearchCriteria {
 private String sku;
 private String description;
 private String productType;
 private String track;
 private String chapter;
 private String title;
 public String getSku() {
  return sku;
 }
 public void setSku(String sku) {
  this.sku = sku;
 }
 public String getDescription() {
  return description;
 }
 public void setDescription(String description) {
  this.description = description;
 }
 public String getProductType() {
  return productType;
 }
 public void setProductType(String productType) {
  this.productType = productType;
 }
 public String getTrack() {
  return track;
 }
 public void setTrack(String track) {
  this.track = track;
 }
 public String getTitle() {
  return title;
 }
 public void setTitle(String title) {
  this.title = title;
 }
 public String getChapter() {
  return chapter;
 }
 public void setChapter(String chapter) {
  this.chapter = chapter;
 }

}
ProductSearchBean.java
package com.borislam.view;

import java.util.List;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Component;
import com.borislam.domain.Product;
import com.borislam.service.ProductService;

@Component
@Scope('session')
public class ProductSearchBean {

 private Product selectedProduct;

 private ProductSearchCriteria criteria = new ProductSearchCriteria();

 private List<product> productList;

 public Product getSelectedProduct() {
  return selectedProduct;
 }

 public void setSelectedProduct(Product selectedProduct) {
  this.selectedProduct = selectedProduct;
 }

 public List<product> getProductList() {
  return productList;
 }

 public void setProductList(List<product> productList) {
  this.productList = productList;
 }

 public ProductSearchCriteria getCriteria() {
  return criteria;
 }

 public void setCriteria(ProductSearchCriteria criteria) {
  this.criteria = criteria;
 }
 @Autowired
 private ProductService productService;

 public void doSearch(ActionEvent event){
  productList= productService.searchByCriteria(criteria);
 }
}
服务层:ProductService.java
package com.borislam.service;

import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.borislam.domain.Product;
import com.borislam.repository.ProductRepository;
import com.borislam.view.ProductSearchCriteria;

@Service
public class ProductService {

 @Autowired
 private ProductRepository productRepository;

 public List<product> searchByCriteria(ProductSearchCriteria criteria){
  return productRepository.searchByCriteria(criteria);
 }

 public Product getProduct(String sku) {
  return productRepository.findBySku(sku);
 }
}

使用Spring数据存储库创建,编辑和删除数据

在本教程的最后一部分,我们将向MongoShop产品目录应用程序添加创建,编辑和删除功能。 搜索页面已修改。 在实际删除产品之前,已添加模式确认对话框

更新了search.xhtml
<html xmlns='http://www.w3.org/1999/xhtml'
 xmlns:ui='http://java.sun.com/jsf/facelets'
 xmlns:h='http://java.sun.com/jsf/html'
 xmlns:f='http://java.sun.com/jsf/core'
 xmlns:p='http://primefaces.org/ui'>

 <ui:composition template='/template/common.xhtml'>

  <ui:define name='pageTitle'>
   <h:outputText value='Product Search' />
  </ui:define>

  <ui:define name='content'>
      <h:form id='searchForm'>
       <p:growl id='mainGrowl' sticky='true'  />
       <p:panelGrid style='width:1024px'>  
        <f:facet name='header'>
         <p:row>  
                <p:column colspan='4'>  
              Product Search
             </p:column>
            </p:row>
        </f:facet>  
       <p:row> 
        <p:column>
          <h:outputLabel for='sku' value='sku: ' />
         </p:column>
         <p:column>  
          <p:inputText id='sku' value='#{productSearchBean.criteria.sku}' />
         </p:column>  
         <p:column>  
          <h:outputLabel for='productType' value='Product Type: ' />
         </p:column>
            <p:column>  
          <p:selectOneMenu id='productType'   label='Type'   value='#{productSearchBean.criteria.productType}'  >  
                 <f:selectItem itemLabel='Select One' itemValue='' />  
                 <f:selectItem itemLabel='Audio Album' itemValue='Audio Album' />  
                 <f:selectItem itemLabel='Book' itemValue='Book' /> 
             </p:selectOneMenu>
         </p:column>
       </p:row>
       <p:row> 
        <p:column>
          <h:outputLabel for='title' value='Title: ' />
         </p:column>
         <p:column>  
          <p:inputText id='title' value='#{productSearchBean.criteria.title}' />
         </p:column>  
         <p:column>  
          <h:outputLabel for='description' value='Description: ' />
         </p:column>
            <p:column>  
          <p:inputText id='description' value='#{productSearchBean.criteria.description}' />
         </p:column>
       </p:row>      

       <p:row> 
        <p:column>
          <h:outputLabel for='track' value='Track: ' />
         </p:column>
         <p:column>  
          <p:inputText id='track' value='#{productSearchBean.criteria.track}' />
         </p:column>  
         <p:column>  
          <h:outputLabel for='chapter' value='Chapter: ' />
         </p:column>
            <p:column>  
          <p:inputText id='chapter' value='#{productSearchBean.criteria.chapter}' />
         </p:column>
       </p:row> 

     </p:panelGrid>
     <p:commandButton value='search' icon='ui-icon-search'  actionListener='#{productSearchBean.doSearch}' update='dataTable'/>
     <hr/>

     <p:dataTable id='dataTable' var='prod' value='#{productSearchBean.productList}'  
                  paginator='true' rows='10'>  

            <p:column>  
                <f:facet name='header'>  
                    <h:outputText value='Sku' />  
                </f:facet>  
                <h:outputText value='#{prod.sku}' />  
            </p:column>  

        <p:column>  
                <f:facet name='header'>  
                    <h:outputText value='Type' />  
                </f:facet>  
                <h:outputText value='#{prod.type}' />  
            </p:column> 

            <p:column>  
                <f:facet name='header'>  
                    <h:outputText value='Title' />  
                </f:facet>  
                <h:outputText value='#{prod.title}' />  
            </p:column>  

            <p:column>  
                <f:facet name='header'>  
                    <h:outputText value='Publisher' />  
                </f:facet>  
                <h:outputText value='#{prod.publisher}' />  
            </p:column>  

             <p:column>  
                <f:facet name='header'>  
                    <h:outputText value='Artist' />  
                </f:facet>  
                <h:outputText value='#{prod.details.artist}' />  
            </p:column>  

       <p:column>  
                <f:facet name='header'>  
                    <h:outputText value='Author' />  
                </f:facet>  
                <h:outputText value='#{prod.details.author}' />  
            </p:column>  

        <p:column>  
                <f:facet name='header'>  
                    <h:outputText value='Edit' />  
                </f:facet>  
                 <p:commandButton value='Edit'  action='#{productSearchBean.doEditDetail}' ajax='false'>
                  <f:setPropertyActionListener target='#{productSearchBean.selectedProduct}' value='#{prod}' />
                 </p:commandButton>
            </p:column>  

       <p:column>  
                <f:facet name='header'>  
                    <h:outputText value='Delete' />  
                </f:facet>

                <p:commandButton id='showDialogButton' value='Delete' oncomplete='confirmation.show()' ajax='true' update=':searchForm:confirmDialog'>  
                  <f:setPropertyActionListener target='#{productSearchBean.selectedProduct}' value='#{prod}' />
                </p:commandButton>

            </p:column>

        </p:dataTable>

      <p:confirmDialog id='confirmDialog' message='Are you sure to delete this product (#{productSearchBean.selectedProduct.sku})?'  
                    header='Delete Product' severity='alert' widgetVar='confirmation'>  

            <p:commandButton id='confirm' value='Yes' update='mainGrowl' oncomplete='confirmation.hide()'  
                        actionListener='#{productSearchBean.doDelete}' />  
            <p:commandButton id='decline' value='No' onclick='confirmation.hide()' type='button' />   

        </p:confirmDialog>

      </h:form>
  </ui:define>
 </ui:composition>
</html>
更新了ProductSearchBean.java
package com.borislam.view;

import java.util.List;

import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Component;
import com.borislam.domain.Product;
import com.borislam.service.ProductService;

@Component
@Scope('session')
public class ProductSearchBean {

 private Product selectedProduct;

 private ProductSearchCriteria criteria = new ProductSearchCriteria();

 private List<Product> productList;

 public Product getSelectedProduct() {
  return selectedProduct;
 }

 public void setSelectedProduct(Product selectedProduct) {
  this.selectedProduct = selectedProduct;
 }

 public List<Product> getProductList() {
  return productList;
 }

 public void setProductList(List<Product> productList) {
  this.productList = productList;
 }

 public ProductSearchCriteria getCriteria() {
  return criteria;
 }

 public void setCriteria(ProductSearchCriteria criteria) {
  this.criteria = criteria;
 }
 @Autowired
 private ProductService productService;

 public void doSearch(ActionEvent event){
  productList= productService.searchByCriteria(criteria);
 }

 public String doEditDetail() {
  (FacesContext.getCurrentInstance().getExternalContext().getFlash()).put('selected', selectedProduct);
  return 'detail.xhtml';
 }

 public void doDelete(ActionEvent event){
  try {   
   productService.deleteProduct(selectedProduct);

   FacesContext context = FacesContext.getCurrentInstance();  
         context.addMessage(null, new FacesMessage('Delete Successfully!'));
  }
  catch (DataAccessException e ) {
   FacesContext context = FacesContext.getCurrentInstance();  
         context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR,'Error when deleting product!',null));
  }

 }
}

添加了产品详细信息页面以查看产品详细信息。 产品的创建和版本在产品详细信息页面中完成。

detail.xhtml
<html xmlns='http://www.w3.org/1999/xhtml'
 xmlns:ui='http://java.sun.com/jsf/facelets'
 xmlns:h='http://java.sun.com/jsf/html'
 xmlns:f='http://java.sun.com/jsf/core'
 xmlns:p='http://primefaces.org/ui'>

 <ui:composition template='/template/common.xhtml'>

  <ui:define name='pageTitle'>
   <h:outputText value='Product Search' />
  </ui:define>

  <ui:define name='content'>
     <f:event listener='#{productDetailBean.initProduct}' type='preRenderView' />

      <h:form id='mainForm'>      
       <p:growl id='mainGrowl' sticky='true'  />
       <p:panelGrid style='width:1024px'>  
        <f:facet name='header'>
         <p:row>  
                <p:column colspan='2'>  
              Product Details
             </p:column>
            </p:row>
        </f:facet>  
       <p:row> 
        <p:column>
          <h:outputLabel for='sku' value='sku: *' />
         </p:column>
         <p:column>  
          <p:inputText id='sku' required='true' value='#{productDetailBean.product.sku}' label='Sku'  rendered='#{productDetailBean.newProduct}'/>
          <h:outputText  value='#{productDetailBean.product.sku}' label='Sku' rendered='#{not productDetailBean.newProduct}'/>
         </p:column>  
       </p:row>
       <p:row> 
        <p:column>
          <h:outputLabel for='type' value='Type *' />
         </p:column>
         <p:column>  
          <p:selectOneMenu id='type' required='true'  label='Type'  valueChangeListener='#{productDetailBean.clearDetails}' value='#{productDetailBean.product.type}'  >  
                 <f:selectItem itemLabel='Select One' itemValue='' />  
                 <f:selectItem itemLabel='Audio Album' itemValue='Audio Album' />  
                 <f:selectItem itemLabel='Book' itemValue='Book' /> 
                 <f:ajax  render='buttonPanel trackPanel chapterPanel'/>
             </p:selectOneMenu>
         </p:column>  
       </p:row> 
       <p:row> 
        <p:column>
          <h:outputLabel for='title' value='Title: *' />
         </p:column>
         <p:column>  
          <p:inputText id='title' required='true' value='#{productDetailBean.product.title}' label='Title' />
         </p:column>  
       </p:row> 
       <p:row> 
        <p:column>
          <h:outputLabel for='description' value='Description: *' />
         </p:column>
         <p:column>  
          <p:inputText id='description' required='true' value='#{productDetailBean.product.description}' label='Description' />
         </p:column>  
       </p:row> 
       <p:row> 
        <p:column>
          <h:outputLabel for='publisher' value='Publisher: *' />
         </p:column>
         <p:column>  
          <p:inputText id='publisher' required='true' value='#{productDetailBean.product.publisher}' label='Publisher' />
         </p:column>  
       </p:row> 

        <p:row> 
        <p:column>
          <h:outputLabel for='artist' value='Artist: ' />
         </p:column>
         <p:column>  
          <p:inputText id='artist'  value='#{productDetailBean.product.details.artist}' label='Artist' />
         </p:column>  
       </p:row>  

        <p:row> 
        <p:column>
          <h:outputLabel for='listPrice' value='List Price: ' />
         </p:column>
         <p:column>  
          <p:inputText id='listPrice'  required='true' value='#{productDetailBean.product.pricing.list}' label='List Price' />
         </p:column>  
       </p:row>  

         <p:row> 
        <p:column>
          <h:outputLabel for='retailPrice' value='Retail Price: ' />
         </p:column>
         <p:column>  
          <p:inputText id='retailPrice'  required='true' value='#{productDetailBean.product.pricing.retail}' label='REtail Price' />
         </p:column>  
       </p:row>  

        <p:row> 
        <p:column>
          <h:outputLabel for='author' value='Author: ' />
         </p:column>
         <p:column>  
          <p:inputText id='author'  value='#{productDetailBean.product.details.author}' label='Author' />
         </p:column>  
       </p:row> 

        <p:row> 
        <p:column>
          <h:outputLabel for='genre' value='Genre: *' />
         </p:column>
         <p:column>  
          <p:inputText id='genre' required='true' value='#{productDetailBean.product.details.genre}' label='Genre' />
         </p:column>  
       </p:row> 

      <p:row>  
            <p:column colspan='2' styleClass='ui-widget-header'>  
             <p:outputPanel id='buttonPanel'>            
                 <p:commandButton value='Add Tracks'   onclick='addTrackDlg.show();' type='button' rendered='#{productDetailBean.product.type == 'Audio Album'}'/>               
                 <p:commandButton value='Add Chapters'   onclick='addChapterDlg.show();' type='button' rendered='#{productDetailBean.product.type == 'Book'}'/>
                </p:outputPanel>
            </p:column>  
        </p:row>

        <p:row>  
            <p:column colspan='2' > 
             <p:outputPanel id='trackPanel' >
                 <p:dataList value='#{productDetailBean.product.details.tracks}' var='track' type='ordered' rendered='#{productDetailBean.product.details.tracks.size() > 0}'>  
            #{track} 
        </p:dataList> 
       </p:outputPanel>
       <p:outputPanel id='chapterPanel' >
        <p:dataList value='#{productDetailBean.product.details.chapters}' var='chapter' type='ordered' rendered='#{productDetailBean.product.details.chapters.size() > 0}'>  
            #{chapter} 
        </p:dataList> 
       </p:outputPanel> 

            </p:column>  
        </p:row> 

        <f:facet name='footer'> 
         <p:row>
          <p:column colspan='2'>  
           <p:commandButton value='Save' icon='ui-icon-disk'  actionListener='#{productDetailBean.doSave}' update='mainGrowl' />
           <p:button value='Back to Search' icon='ui-icon-back'  outcome='search.xhtml' />
          </p:column>
         </p:row>          
        </f:facet>  
    </p:panelGrid>   

   </h:form>

   <h:form>   
    <p:growl id='trackGrowl' sticky='true'  />
    <p:dialog id='addTrackDlg' header='Adding Tracks for the product' widgetVar='addTrackDlg' modal='true' height='100' width='450' resizable='false'>  
        <h:outputLabel for='track' value='Track: ' /> 
        <p:inputText id='track' required='true' value='#{productDetailBean.newTrack}' label='Track' /> 
        <p:commandButton value='Add' actionListener='#{productDetailBean.doAddTracks}' icon='ui-icon-check'  update='trackGrowl, :mainForm:trackPanel' oncomplete='addTrackDlg.hide()'/>
    </p:dialog> 
   </h:form> 

   <h:form>
    <p:growl id='chapterGrowl' sticky='true'  /> 
    <p:dialog id='addChapterDlg' header='Adding Chapters for the product' widgetVar='addChapterDlg' modal='true' height='100' width='450' resizable='false'>  
        <h:outputLabel for='chapter' value='Chapter: ' /> 
        <p:inputText id='chapter' required='true' value='#{productDetailBean.newChapter}' label='Chapter' /> 
        <p:commandButton value='Add' actionListener='#{productDetailBean.doAddChapters}' icon='ui-icon-check'  update='chapterGrowl, :mainForm:chapterPanel' oncomplete='addChapterDlg.hide()'/>

    </p:dialog> 
   </h:form> 
  </ui:define>
 </ui:composition>
</html>
ProductDetailsBean.java
package com.borislam.view;

import java.util.ArrayList;
import java.util.List;

import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.faces.event.ValueChangeEvent;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.dao.DataAccessException;

import com.borislam.domain.Detail;
import com.borislam.domain.Pricing;
import com.borislam.domain.Product;
import com.borislam.service.ProductService;

@Component
@Scope('session')
public class ProductDetailBean {

 @Autowired
 private ProductService productService;
 private boolean newProduct;
 private Product product;
 private String newTrack;
 private String newChapter;

 public boolean isNewProduct() {
  return newProduct;
 }

 public void setNewProduct(boolean newProduct) {
  this.newProduct = newProduct;
 }

 public Product getProduct() {
  return product;
 }

 public void setProduct(Product product) {
  this.product = product;
 }

 public String getNewTrack() {
  return newTrack;
 }

 public void setNewTrack(String newTrack) {
  this.newTrack = newTrack;
 }

 public String getNewChapter() {
  return newChapter;
 }

 public void setNewChapter(String newChapter) {
  this.newChapter = newChapter;
 }

 public void initProduct(){
  Object selectedProduct = (FacesContext.getCurrentInstance().getExternalContext().getFlash()).get('selected');

  if (selectedProduct==null &&  !FacesContext.getCurrentInstance().isPostback()) {
   product = new Product();
   product.setDetails(new Detail());
   product.setPricing(new Pricing(0,0));
   setNewProduct(true);
  }
  if (selectedProduct!=null) {
   product = (Product)selectedProduct;
   setNewProduct(false);
  }

 }

 public void  doSave(ActionEvent event) {

  try {
   productService.saveProduct(product);

   FacesContext context = FacesContext.getCurrentInstance();  
         context.addMessage(null, new FacesMessage('Save Successfully!'));
  }
  catch (DataAccessException e)
  { 
   e.printStackTrace();

   FacesContext context = FacesContext.getCurrentInstance();  
         context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR,'Error when saving product!',null));

  }

 }

 public void  doAddTracks(ActionEvent event) {
  List<String> tracks = product.getDetails().getTracks();
  if (CollectionUtils.isEmpty(tracks)) {
   product.getDetails().setTracks(new ArrayList<String>());
  }
  product.getDetails().getTracks().add(this.newTrack);

 }

 public void  doAddChapters(ActionEvent event) {
  List<String> tracks = product.getDetails().getChapters();
  if (CollectionUtils.isEmpty(tracks)) {
   product.getDetails().setChapters(new ArrayList<String>() );
  }
  product.getDetails().getChapters().add(this.newChapter);

 }

 public void clearDetails(ValueChangeEvent  event) {

  if ('Audio Album'.equalsIgnoreCase(event.getNewValue().toString()) ) {
   product.getDetails().setChapters(null);
  }
  if ('Book'.equalsIgnoreCase( event.getNewValue().toString())) {
   product.getDetails().setTracks(null);
  }
 }
}
更新了ProductService.java
package com.borislam.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.borislam.domain.Product;
import com.borislam.repository.ProductRepository;
import com.borislam.view.ProductSearchCriteria;

@Service
public class ProductService {

 @Autowired
 private ProductRepository productRepository;

 public List<Product> searchByCriteria(ProductSearchCriteria criteria){
  return productRepository.searchByCriteria(criteria);
 }

 public Product getProduct(String sku) {
  return productRepository.findBySku(sku);
 }

 public void saveProduct(Product p){  
  productRepository.save(p);
 }

 public void deleteProduct(Product p){  
  productRepository.delete(p);
 }

}

结论:

1. Spring Data Mongo DB提供了MongoTemplate,可让您轻松执行MongoDB操作。

2.借助Spring Data MongoDB,可以轻松将MongoDB JSON样式的文档映射到POJO

3. Spring数据的存储库抽象减少了访问MongoDB的样板代码。

4.您将自定义行为添加到spring数据存储库。

参考: 示例应用程序简介(MongoShop产品目录)MongoDB模式设计和数据准备JSF(PrimeFaces)和Spring数据MongoDB集成带有Spring数据存储库和mongotemplate的Enquriy数据创建,编辑和删除数据 (来自我们的JCG合作伙伴 Boris)在“ Programming Peaceally和平”博客上,Lam表示。

翻译自: https://www.javacodegeeks.com/2013/02/spring-data-mongodb-and-jsf-integration-tutorial.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值