博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
springCloud整合Elasticsearch 之 Springboot整合ES
阅读量:2169 次
发布时间:2019-05-01

本文共 24373 字,大约阅读时间需要 81 分钟。

引入依赖

maven
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
        </dependency>

温馨提示:springboot版本中内嵌了es版本 ,如果与服务器版本不一致,需强制改动其依赖版本

maven 更改方法

properties 中指定版本号

    <properties>

        <elasticsearch.version>es服务版本</elasticsearch.version>
    </properties>

可能有人问,为什么要这么定义es版本号前后缀?

因为 springboot父工程就是这样定义版本号的,所以我们平时在引入依赖时无需显示申明版本号

 

在我们学习ES的时候,就已经讲过 ,初学期间,我们直接把 indexs 当做数据库,

type当做表 document当做一行数据

在操作mysql数据库的时候啊,我们通常会定义pojo实体类,一个类呢,对应着一个表,然后使用jpa /mybatis 对这个类做操作,然后保存到我们的数据库即可。

那么ES是否可以定义一个实体类,然后操作到ES服务器上呢?ES 在springboot中如何使用呢?

咱们进入今天的正题:springboot整合es

springboot 整合es

配置链接信息
springboot中 连接es很简单

uris 表明其需要连接的集群 (我这里只有一个,es ,一个节点也是集群)

spring:

  elasticsearch:
    rest:
      uris: localhost:9200
 

 

如果是Linux服务器上安装的话 ,可能还需要配置连接es的账户和密码

spring:  elasticsearch:    rest:      uris: localhost:9200      password: xxx      username: xxx

定义实体类

es 在springboot中使用,同样可定义实体类 ,使其绑定到索引库以及type上,并能根据字段类型设置mapping映射.

@Document 注解注意引用的是import org.springframework.data.elasticsearch.annotations.Document下

在项目使用了Mongodb的时候,格外要注意这点!

indexName指定了 索引库名

我这里是没有写_type的, 虽然哈,一直说 将type作为表来理解,但是es 与mysql终究是不一样的,后续es 8.x会去除type操作 _type ,我这里没写,因为其默认了,

shards 指定分片

replicas 指定副本集 此二者无特殊场景,默认即可

@Document(indexName = "pms", type = "product",shards = 1,replicas = 0)public class EsProduct implements Serializable {    private static final long serialVersionUID = -1L;    @Id    private Long id;    @Field(type = FieldType.Keyword)    private String productSn;    private Long brandId;    @Field(type = FieldType.Keyword)    private String brandName;    private Long productCategoryId;    @Field(type = FieldType.Keyword)    private String productCategoryName;    private String pic;    @Field(analyzer = "ik_max_word",type = FieldType.Text)    private String name;    @Field(analyzer = "ik_max_word",type = FieldType.Text)    private String subTitle;    @Field(analyzer = "ik_max_word",type = FieldType.Text)    private String keywords;    private BigDecimal price;    private Integer sale;    private Integer newStatus;    private Integer recommandStatus;    private Integer stock;    private Integer promotionType;    private Integer sort;    @Field(type =FieldType.Nested)    private List
attrValueList; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getProductSn() { return productSn; } public void setProductSn(String productSn) { this.productSn = productSn; } public Long getBrandId() { return brandId; } public void setBrandId(Long brandId) { this.brandId = brandId; } public String getBrandName() { return brandName; } public void setBrandName(String brandName) { this.brandName = brandName; } public Long getProductCategoryId() { return productCategoryId; } public void setProductCategoryId(Long productCategoryId) { this.productCategoryId = productCategoryId; } public String getProductCategoryName() { return productCategoryName; } public void setProductCategoryName(String productCategoryName) { this.productCategoryName = productCategoryName; } public String getPic() { return pic; } public void setPic(String pic) { this.pic = pic; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSubTitle() { return subTitle; } public void setSubTitle(String subTitle) { this.subTitle = subTitle; } public BigDecimal getPrice() { return price; } public void setPrice(BigDecimal price) { this.price = price; } public Integer getSale() { return sale; } public void setSale(Integer sale) { this.sale = sale; } public Integer getNewStatus() { return newStatus; } public void setNewStatus(Integer newStatus) { this.newStatus = newStatus; } public Integer getRecommandStatus() { return recommandStatus; } public void setRecommandStatus(Integer recommandStatus) { this.recommandStatus = recommandStatus; } public Integer getStock() { return stock; } public void setStock(Integer stock) { this.stock = stock; } public Integer getPromotionType() { return promotionType; } public void setPromotionType(Integer promotionType) { this.promotionType = promotionType; } public Integer getSort() { return sort; } public void setSort(Integer sort) { this.sort = sort; } public List
getAttrValueList() { return attrValueList; } public void setAttrValueList(List
attrValueList) { this.attrValueList = attrValueList; } public String getKeywords() { return keywords; } public void setKeywords(String keywords) { this.keywords = keywords; }}

@Id 注意 引入的是 import org.springframework.data.annotation.Id包下的

@Field 可指定字段类型,与es中mapping设定需要规约的类型一致,并且可选择分词器(前面已经安装了IK)

 

import java.util.List;public class EsProductRelatedInfo {    private List
brandNames; private List
productCategoryNames; private List
productAttrs; public List
getBrandNames() { return brandNames; } public void setBrandNames(List
brandNames) { this.brandNames = brandNames; } public List
getProductCategoryNames() { return productCategoryNames; } public void setProductCategoryNames(List
productCategoryNames) { this.productCategoryNames = productCategoryNames; } public List
getProductAttrs() { return productAttrs; } public void setProductAttrs(List
productAttrs) { this.productAttrs = productAttrs; } public static class ProductAttr{ private Long attrId; private String attrName; private List
attrValues; public Long getAttrId() { return attrId; } public void setAttrId(Long attrId) { this.attrId = attrId; } public List
getAttrValues() { return attrValues; } public void setAttrValues(List
attrValues) { this.attrValues = attrValues; } public String getAttrName() { return attrName; } public void setAttrName(String attrName) { this.attrName = attrName; } }}
public class EsProductAttributeValue implements Serializable {    private static final long serialVersionUID = 1L;    private Long id;    private Long productAttributeId;    //属性值    @Field(type = FieldType.Keyword)    private String value;    //属性参数:0->规格;1->参数    private Integer type;    //属性名称    @Field(type=FieldType.Keyword)    private String name;    public Long getId() {        return id;    }    public void setId(Long id) {        this.id = id;    }    public Long getProductAttributeId() {        return productAttributeId;    }    public void setProductAttributeId(Long productAttributeId) {        this.productAttributeId = productAttributeId;    }    public String getValue() {        return value;    }    public void setValue(String value) {        this.value = value;    }    public Integer getType() {        return type;    }    public void setType(Integer type) {        this.type = type;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }}

 

定义dao 接口继承ElasticsearchRepository

 

public interface EsProductRepository extends ElasticsearchRepository
{ /** * 搜索查询 * * @param name 商品名称 * @param subTitle 商品标题 * @param keywords 商品关键字 * @param page 分页信息 * @return */ Page
findByNameOrSubTitleOrKeywords(String name, String subTitle, String keywords, Pageable page);}

 继承了此接口 ,基础文档CRUD 接口即做好了

定义一个controller控制器,操作

import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.domain.Page;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.*;import java.util.List;/** * 搜索商品管理Controller */@Controller@Api(tags = "EsProductController", description = "搜索商品管理")@RequestMapping("/esProduct")public class EsProductController {    @Autowired    private EsProductService esProductService;    @ApiOperation(value = "导入所有数据库中商品到ES")    @RequestMapping(value = "/importAll", method = RequestMethod.POST)    @ResponseBody    public CommonResult
importAllList() { int count = esProductService.importAll(); return CommonResult.success(count); } @ApiOperation(value = "根据id删除商品") @RequestMapping(value = "/delete/{id}", method = RequestMethod.GET) @ResponseBody public CommonResult
delete(@PathVariable Long id) { esProductService.delete(id); return CommonResult.success(null); } @ApiOperation(value = "根据id批量删除商品") @RequestMapping(value = "/delete/batch", method = RequestMethod.POST) @ResponseBody public CommonResult delete(@RequestParam("ids") List
ids) { esProductService.delete(ids); return CommonResult.success(null); } @ApiOperation(value = "根据id创建商品") @RequestMapping(value = "/create/{id}", method = RequestMethod.POST) @ResponseBody public CommonResult
create(@PathVariable Long id) { EsProduct esProduct = esProductService.create(id); if (esProduct != null) { return CommonResult.success(esProduct); } else { return CommonResult.failed(); } } @ApiOperation(value = "简单搜索") @RequestMapping(value = "/search/simple", method = RequestMethod.GET) @ResponseBody public CommonResult
> search(@RequestParam(required = false) String keyword, @RequestParam(required = false, defaultValue = "0") Integer pageNum, @RequestParam(required = false, defaultValue = "5") Integer pageSize) { Page
esProductPage = esProductService.search(keyword, pageNum, pageSize); return CommonResult.success(CommonPage.restPage(esProductPage)); } @ApiOperation(value = "综合搜索、筛选、排序") @ApiImplicitParam(name = "sort", value = "排序字段:0->按相关度;1->按新品;2->按销量;3->价格从低到高;4->价格从高到低", defaultValue = "0", allowableValues = "0,1,2,3,4", paramType = "query", dataType = "integer") @RequestMapping(value = "/search", method = RequestMethod.GET) @ResponseBody public CommonResult
> search(@RequestParam(required = false) String keyword, @RequestParam(required = false) Long brandId, @RequestParam(required = false) Long productCategoryId, @RequestParam(required = false, defaultValue = "0") Integer pageNum, @RequestParam(required = false, defaultValue = "5") Integer pageSize, @RequestParam(required = false, defaultValue = "0") Integer sort) { Page
esProductPage = esProductService.search(keyword, brandId, productCategoryId, pageNum, pageSize, sort); return CommonResult.success(CommonPage.restPage(esProductPage)); } @ApiOperation(value = "根据商品id推荐商品") @RequestMapping(value = "/recommend/{id}", method = RequestMethod.GET) @ResponseBody public CommonResult
> recommend(@PathVariable Long id, @RequestParam(required = false, defaultValue = "0") Integer pageNum, @RequestParam(required = false, defaultValue = "5") Integer pageSize) { Page
esProductPage = esProductService.recommend(id, pageNum, pageSize); return CommonResult.success(CommonPage.restPage(esProductPage)); } @ApiOperation(value = "获取搜索的相关品牌、分类及筛选属性") @RequestMapping(value = "/search/relate", method = RequestMethod.GET) @ResponseBody public CommonResult
searchRelatedInfo(@RequestParam(required = false) String keyword) { EsProductRelatedInfo productRelatedInfo = esProductService.searchRelatedInfo(keyword); return CommonResult.success(productRelatedInfo); }}

 

service层

package com.macro.mall.tiny.service;import com.macro.mall.tiny.domain.EsProductRelatedInfo;import com.macro.mall.tiny.nosql.elasticsearch.document.EsProduct;import org.springframework.data.domain.Page;import java.util.List;/** * 商品搜索管理Service */public interface EsProductService {    /**     * 从数据库中导入所有商品到ES     */    int importAll();    /**     * 根据id删除商品     */    void delete(Long id);    /**     * 根据id创建商品     */    EsProduct create(Long id);    /**     * 批量删除商品     */    void delete(List
ids); /** * 根据关键字搜索名称或者副标题 */ Page
search(String keyword, Integer pageNum, Integer pageSize); /** * 根据关键字搜索名称或者副标题复合查询 */ Page
search(String keyword, Long brandId, Long productCategoryId, Integer pageNum, Integer pageSize,Integer sort); /** * 根据商品id推荐相关商品 */ Page
recommend(Long id, Integer pageNum, Integer pageSize); /** * 获取搜索词相关品牌、分类、属性 */ EsProductRelatedInfo searchRelatedInfo(String keyword);}

 

import org.elasticsearch.common.lucene.search.function.FunctionScoreQuery;import org.elasticsearch.index.query.BoolQueryBuilder;import org.elasticsearch.index.query.QueryBuilders;import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder;import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders;import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;import org.elasticsearch.search.aggregations.Aggregation;import org.elasticsearch.search.aggregations.AggregationBuilders;import org.elasticsearch.search.aggregations.bucket.filter.InternalFilter;import org.elasticsearch.search.aggregations.bucket.filter.ParsedFilter;import org.elasticsearch.search.aggregations.bucket.nested.InternalNested;import org.elasticsearch.search.aggregations.bucket.nested.ParsedNested;import org.elasticsearch.search.aggregations.bucket.terms.*;import org.elasticsearch.search.sort.SortBuilders;import org.elasticsearch.search.sort.SortOrder;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.domain.Page;import org.springframework.data.domain.PageImpl;import org.springframework.data.domain.PageRequest;import org.springframework.data.domain.Pageable;import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;import org.springframework.data.elasticsearch.core.SearchHits;import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;import org.springframework.stereotype.Service;import org.springframework.util.CollectionUtils;import org.springframework.util.StringUtils;import java.util.ArrayList;import java.util.Iterator;import java.util.List;import java.util.Map;/** * 商品搜索管理Service实现类 */@Servicepublic class EsProductServiceImpl implements EsProductService {    private static final Logger LOGGER = LoggerFactory.getLogger(EsProductServiceImpl.class);    @Autowired    private EsProductDao productDao;    @Autowired    private EsProductRepository productRepository;    @Autowired    private ElasticsearchRestTemplate elasticsearchRestTemplate;    @Override    public int importAll() {        List
esProductList = productDao.getAllEsProductList(null); Iterable
esProductIterable = productRepository.saveAll(esProductList); Iterator
iterator = esProductIterable.iterator(); int result = 0; while (iterator.hasNext()) { result++; iterator.next(); } return result; } @Override public void delete(Long id) { productRepository.deleteById(id); } @Override public EsProduct create(Long id) { EsProduct result = null; List
esProductList = productDao.getAllEsProductList(id); if (esProductList.size() > 0) { EsProduct esProduct = esProductList.get(0); result = productRepository.save(esProduct); } return result; } @Override public void delete(List
ids) { if (!CollectionUtils.isEmpty(ids)) { List
esProductList = new ArrayList<>(); for (Long id : ids) { EsProduct esProduct = new EsProduct(); esProduct.setId(id); esProductList.add(esProduct); } productRepository.deleteAll(esProductList); } } @Override public Page
search(String keyword, Integer pageNum, Integer pageSize) { Pageable pageable = PageRequest.of(pageNum, pageSize); return productRepository.findByNameOrSubTitleOrKeywords(keyword, keyword, keyword, pageable); } @Override public Page
search(String keyword, Long brandId, Long productCategoryId, Integer pageNum, Integer pageSize,Integer sort) { Pageable pageable = PageRequest.of(pageNum, pageSize); NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder(); //分页 nativeSearchQueryBuilder.withPageable(pageable); //过滤 if (brandId != null || productCategoryId != null) { BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery(); if (brandId != null) { boolQueryBuilder.must(QueryBuilders.termQuery("brandId", brandId)); } if (productCategoryId != null) { boolQueryBuilder.must(QueryBuilders.termQuery("productCategoryId", productCategoryId)); } nativeSearchQueryBuilder.withFilter(boolQueryBuilder); } //搜索 if (StringUtils.isEmpty(keyword)) { nativeSearchQueryBuilder.withQuery(QueryBuilders.matchAllQuery()); } else { List
filterFunctionBuilders = new ArrayList<>(); filterFunctionBuilders.add(new FunctionScoreQueryBuilder.FilterFunctionBuilder(QueryBuilders.matchQuery("name", keyword), ScoreFunctionBuilders.weightFactorFunction(10))); filterFunctionBuilders.add(new FunctionScoreQueryBuilder.FilterFunctionBuilder(QueryBuilders.matchQuery("subTitle", keyword), ScoreFunctionBuilders.weightFactorFunction(5))); filterFunctionBuilders.add(new FunctionScoreQueryBuilder.FilterFunctionBuilder(QueryBuilders.matchQuery("keywords", keyword), ScoreFunctionBuilders.weightFactorFunction(2))); FunctionScoreQueryBuilder.FilterFunctionBuilder[] builders = new FunctionScoreQueryBuilder.FilterFunctionBuilder[filterFunctionBuilders.size()]; filterFunctionBuilders.toArray(builders); FunctionScoreQueryBuilder functionScoreQueryBuilder = QueryBuilders.functionScoreQuery(builders) .scoreMode(FunctionScoreQuery.ScoreMode.SUM) .setMinScore(2); nativeSearchQueryBuilder.withQuery(functionScoreQueryBuilder); } //排序 if(sort==1){ //按新品从新到旧 nativeSearchQueryBuilder.withSort(SortBuilders.fieldSort("id").order(SortOrder.DESC)); }else if(sort==2){ //按销量从高到低 nativeSearchQueryBuilder.withSort(SortBuilders.fieldSort("sale").order(SortOrder.DESC)); }else if(sort==3){ //按价格从低到高 nativeSearchQueryBuilder.withSort(SortBuilders.fieldSort("price").order(SortOrder.ASC)); }else if(sort==4){ //按价格从高到低 nativeSearchQueryBuilder.withSort(SortBuilders.fieldSort("price").order(SortOrder.DESC)); }else{ //按相关度 nativeSearchQueryBuilder.withSort(SortBuilders.scoreSort().order(SortOrder.DESC)); } nativeSearchQueryBuilder.withSort(SortBuilders.scoreSort().order(SortOrder.DESC)); NativeSearchQuery searchQuery = nativeSearchQueryBuilder.build(); LOGGER.info("DSL:{}", searchQuery.getQuery().toString()); return productRepository.search(searchQuery); } @Override public Page
recommend(Long id, Integer pageNum, Integer pageSize) { Pageable pageable = PageRequest.of(pageNum, pageSize); List
esProductList = productDao.getAllEsProductList(id); if (esProductList.size() > 0) { EsProduct esProduct = esProductList.get(0); String keyword = esProduct.getName(); Long brandId = esProduct.getBrandId(); Long productCategoryId = esProduct.getProductCategoryId(); //根据商品标题、品牌、分类进行搜索 List
filterFunctionBuilders = new ArrayList<>(); filterFunctionBuilders.add(new FunctionScoreQueryBuilder.FilterFunctionBuilder(QueryBuilders.matchQuery("name", keyword), ScoreFunctionBuilders.weightFactorFunction(8))); filterFunctionBuilders.add(new FunctionScoreQueryBuilder.FilterFunctionBuilder(QueryBuilders.matchQuery("subTitle", keyword), ScoreFunctionBuilders.weightFactorFunction(2))); filterFunctionBuilders.add(new FunctionScoreQueryBuilder.FilterFunctionBuilder(QueryBuilders.matchQuery("keywords", keyword), ScoreFunctionBuilders.weightFactorFunction(2))); filterFunctionBuilders.add(new FunctionScoreQueryBuilder.FilterFunctionBuilder(QueryBuilders.matchQuery("brandId", brandId), ScoreFunctionBuilders.weightFactorFunction(5))); filterFunctionBuilders.add(new FunctionScoreQueryBuilder.FilterFunctionBuilder(QueryBuilders.matchQuery("productCategoryId", productCategoryId), ScoreFunctionBuilders.weightFactorFunction(3))); FunctionScoreQueryBuilder.FilterFunctionBuilder[] builders = new FunctionScoreQueryBuilder.FilterFunctionBuilder[filterFunctionBuilders.size()]; filterFunctionBuilders.toArray(builders); FunctionScoreQueryBuilder functionScoreQueryBuilder = QueryBuilders.functionScoreQuery(builders) .scoreMode(FunctionScoreQuery.ScoreMode.SUM) .setMinScore(2); //用于过滤掉相同的商品 BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder(); boolQueryBuilder.mustNot(QueryBuilders.termQuery("id",id)); //构建查询条件 NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder(); builder.withQuery(functionScoreQueryBuilder); builder.withFilter(boolQueryBuilder); builder.withPageable(pageable); NativeSearchQuery searchQuery = builder.build(); LOGGER.info("DSL:{}", searchQuery.getQuery().toString()); return productRepository.search(searchQuery); } return new PageImpl<>(null); } @Override public EsProductRelatedInfo searchRelatedInfo(String keyword) { NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder(); //搜索条件 if(StringUtils.isEmpty(keyword)){ builder.withQuery(QueryBuilders.matchAllQuery()); }else{ builder.withQuery(QueryBuilders.multiMatchQuery(keyword,"name","subTitle","keywords")); } //聚合搜索品牌名称 builder.addAggregation(AggregationBuilders.terms("brandNames").field("brandName")); //集合搜索分类名称 builder.addAggregation(AggregationBuilders.terms("productCategoryNames").field("productCategoryName")); //聚合搜索商品属性,去除type=1的属性 AbstractAggregationBuilder aggregationBuilder = AggregationBuilders.nested("allAttrValues","attrValueList") .subAggregation(AggregationBuilders.filter("productAttrs",QueryBuilders.termQuery("attrValueList.type",1)) .subAggregation(AggregationBuilders.terms("attrIds") .field("attrValueList.productAttributeId") .subAggregation(AggregationBuilders.terms("attrValues") .field("attrValueList.value")) .subAggregation(AggregationBuilders.terms("attrNames") .field("attrValueList.name")))); builder.addAggregation(aggregationBuilder); NativeSearchQuery searchQuery = builder.build(); SearchHits
searchHits = elasticsearchRestTemplate.search(searchQuery, EsProduct.class); return convertProductRelatedInfo(searchHits); } /** * 将返回结果转换为对象 */ private EsProductRelatedInfo convertProductRelatedInfo(SearchHits
response) { EsProductRelatedInfo productRelatedInfo = new EsProductRelatedInfo(); Map
aggregationMap = response.getAggregations().getAsMap(); //设置品牌 Aggregation brandNames = aggregationMap.get("brandNames"); List
brandNameList = new ArrayList<>(); for(int i = 0; i<((Terms) brandNames).getBuckets().size(); i++){ brandNameList.add(((Terms) brandNames).getBuckets().get(i).getKeyAsString()); } productRelatedInfo.setBrandNames(brandNameList); //设置分类 Aggregation productCategoryNames = aggregationMap.get("productCategoryNames"); List
productCategoryNameList = new ArrayList<>(); for(int i=0;i<((Terms) productCategoryNames).getBuckets().size();i++){ productCategoryNameList.add(((Terms) productCategoryNames).getBuckets().get(i).getKeyAsString()); } productRelatedInfo.setProductCategoryNames(productCategoryNameList); //设置参数 Aggregation productAttrs = aggregationMap.get("allAttrValues"); List
attrIds = ((ParsedLongTerms) ((ParsedFilter) ((ParsedNested) productAttrs).getAggregations().get("productAttrs")).getAggregations().get("attrIds")).getBuckets(); List
attrList = new ArrayList<>(); for (Terms.Bucket attrId : attrIds) { EsProductRelatedInfo.ProductAttr attr = new EsProductRelatedInfo.ProductAttr(); attr.setAttrId((Long) attrId.getKey()); List
attrValueList = new ArrayList<>(); List
attrValues = ((ParsedStringTerms) attrId.getAggregations().get("attrValues")).getBuckets(); List
attrNames = ((ParsedStringTerms) attrId.getAggregations().get("attrNames")).getBuckets(); for (Terms.Bucket attrValue : attrValues) { attrValueList.add(attrValue.getKeyAsString()); } attr.setAttrValues(attrValueList); if(!CollectionUtils.isEmpty(attrNames)){ String attrName = attrNames.get(0).getKeyAsString(); attr.setAttrName(attrName); } attrList.add(attr); } productRelatedInfo.setProductAttrs(attrList); return productRelatedInfo; }}

 

 mapper,dao类此处由于篇幅问题不再黏贴了,理解操作流程。

转载地址:http://bhxzb.baihongyu.com/

你可能感兴趣的文章
composer install或composer update 或 composer require phpoffice/phpexcel 失败解决办法
查看>>
TP5.1项目从windows的Apache服务迁移到linux的Nginx服务需要注意几点。
查看>>
win10安装软件 打开时报错 找不到 msvcp120.dll
查看>>
PHPunit+Xdebug代码覆盖率以及遇到的问题汇总
查看>>
PHPUnit安装及使用
查看>>
PHP项目用xhprof性能分析(安装及应用实例)
查看>>
composer安装YII
查看>>
Sublime text3快捷键演示
查看>>
sublime text3 快捷键修改
查看>>
关于PHP几点建议
查看>>
硬盘的接口、协议
查看>>
VLAN与子网划分区别
查看>>
Cisco Packet Tracer教程
查看>>
02. 交换机的基本配置和管理
查看>>
03. 交换机的Telnet远程登陆配置
查看>>
微信小程序-调用-腾讯视频-解决方案
查看>>
phpStudy安装yaf扩展
查看>>
密码 加密 加盐 常用操作记录
查看>>
TP 分页后,调用指定页。
查看>>
Oracle数据库中的(+)连接
查看>>