elasticSearch版本6.8.12 springboot版本2.2.7 springdataelasticSearch版本3.2.7
使用
ElasticsearchRepository 向elasticSearch 中添加 時間類型為LocaldateTime 的記錄
entity
package com.aila.elasticSearch.POJO; import com.alibaba.fastjson.annotation.JSONField; import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.experimental.Accessors; import org.springframework.data.annotation.Id; import org.springframework.data.elasticsearch.annotations.*; import org.springframework.format.annotation.DateTimeFormat; import java.io.Serializable; import java.time.LocalDateTime; /** * <p> * 艾拉項目 音樂表 * </p> * * @author chenzhichao * @since 2020-12-08 */ @Data @EqualsAndHashCode(callSuper = false) @Accessors(chain = true) @Document(indexName = "music",shards=5,replicas = 2) public class MusicElasticEntity implements Serializable{ @ApiModelProperty(value = "音樂表主鍵id") @Field(index = true, store = true, type = FieldType.Keyword) @Id private Long id; @ApiModelProperty(value = "音樂名稱") @Field(index = true, store = true, type = FieldType.Text, analyzer = "ik_smart") private String name; @ApiModelProperty(value = "歌手名稱") @Field(index = true, store = true, type = FieldType.Text) private String singer; @ApiModelProperty(value = "歌曲鏈接地址") @Field(index = false, store = true, type = FieldType.Text) private String linkUrl; @ApiModelProperty(value = "專輯名稱") @Field(index = true, store = true, type = FieldType.Text) private String albumName; @ApiModelProperty(value = "mv鏈接地址") @Field(index = false, store = true, type = FieldType.Text) private String mvUrl; @ApiModelProperty(value = "封面Url") @Field(index = false, store = true, type = FieldType.Text) private String cover; @ApiModelProperty(value = "狀態 1 上架狀態 0下架狀態 ") @Field(index = true, store = true, type = FieldType.Integer) private Integer status; @ApiModelProperty(value = "刪除標志 1刪除 0未刪除") @Field(index = true, store = true, type = FieldType.Integer) private Integer deleteFlag; @ApiModelProperty(value = "歌詞鏈接Url") @Field(index = false, store = true, type = FieldType.Text) private String lyricLinkUrl; @ApiModelProperty(value = "歌曲時長") @Field(index = false, store = true, type = FieldType.Date,format = DateFormat.custom, pattern = "yyyy-MM-dd HH:mm:ss") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") //@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") //@JSONField(format = "yyyy-MM-dd HH:mm:ss") private LocalDateTime duration; @ApiModelProperty(value = "發行商") @Field(index = true, store = true, type = FieldType.Text) private String publisher; @ApiModelProperty(value = "發行時間") @Field(index = false, store = true, type = FieldType.Date) private LocalDateTime issueTime; @ApiModelProperty(value = "一級分類") @Field(index = true, store = true, type = FieldType.Integer) private Integer musicTypeId; @ApiModelProperty(value = "二級分類") @Field(index = true, store = true, type = FieldType.Integer) private Integer parentMusicTypeId; @ApiModelProperty(value = "三級分類") @Field(index = true, store = true, type = FieldType.Integer) private Integer grandpaMusicTypeId; @ApiModelProperty(value = "創建時間") private LocalDateTime createdTime; @ApiModelProperty(value = "更新時間") private LocalDateTime updateTime; @ApiModelProperty(value = "更新人 userId") private Long updateBy; @ApiModelProperty(value = "創建人 userId") private Long createdBy; }
test類
package com.aila.elasticSearch.service.impl; import com.aila.elasticSearch.POJO.MusicElasticEntity; import com.aila.elasticSearch.service.IMusicService; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import javax.annotation.Resource; import java.time.LocalDateTime; /** * @author chenzhichao * @date 2020/12/8 16:38 * 使用es版本 6-8-12 ik分詞器版本6-8-12 */ @RunWith(SpringRunner.class) @AutoConfigureMockMvc @SpringBootTest public class MusicServiceImplTest { @Resource private IMusicService iMusicService; @Test public void add() { MusicElasticEntity entity = new MusicElasticEntity(); entity.setId(16L).setName("親情式的愛情").setSinger("許嵩") .setAlbumName("夢游計").setStatus(1).setDeleteFlag(0).setMusicTypeId(3) .setParentMusicTypeId(4).setGrandpaMusicTypeId(5) //時間這塊沒有解決 .setDuration(LocalDateTime.of(2020,12,8,0,4,44)); //.setDuration(new Date()); //.setDuration("2020-12-08 00:04:44"); iMusicService.add(entity); } @Test public void findByEntityId() { //MusicElasticEntity entity = iMusicService.findByEntityId(13L); MusicElasticEntity entity = iMusicService.findByEntityId(15L); System.out.println(entity); } @Test public void deleteMappingAndIndex() { iMusicService.deleteMappingAndIndex("com.aila.elasticSearch.POJO.MusicElasticEntity"); } @Test public void createMappingAndIndex() { iMusicService.createMappingAndIndex("com.aila.elasticSearch.POJO.MusicElasticEntity"); } }
serviceImpl
package com.aila.elasticSearch.service.impl; import com.aila.elasticSearch.POJO.MusicElasticEntity; import com.aila.elasticSearch.entity.Music; import com.aila.elasticSearch.mapper.MusicElasticMapper; import com.aila.elasticSearch.mapper.MusicMapper; import com.aila.elasticSearch.service.IMusicService; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.google.gson.Gson; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.elasticsearch.core.ElasticsearchTemplate; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import org.springframework.util.Assert; import javax.annotation.Resource; import java.util.Optional; /** * <p> * 艾拉項目 音樂表 服務實現類 * </p> * * @author chenzhichao * @since 2020-12-08 */ @Service @Slf4j public class MusicServiceImpl extends ServiceImpl<MusicMapper, Music> implements IMusicService { @Autowired private MusicElasticMapper musicElasticMapper; @Resource private ElasticsearchTemplate elasticsearchTemplate; @Autowired private Gson gson; @Override public void createMappingAndIndex(String className) { Class<?> targetClass = null; try { targetClass = Class.forName(className); } catch (ClassNotFoundException e) { e.printStackTrace(); } Assert.notNull(targetClass,"創建class對象失敗"); elasticsearchTemplate.createIndex(targetClass); elasticsearchTemplate.putMapping(targetClass); } @Override public void deleteMappingAndIndex(String className) { Class<?> targetClass = null; try { targetClass = Class.forName(className); } catch (ClassNotFoundException e) { e.printStackTrace(); } Assert.notNull(targetClass,"創建class對象失敗"); elasticsearchTemplate.deleteIndex(targetClass); } @Override public void add(MusicElasticEntity entity) { log.error("開始添加"+gson.toJson(entity)); musicElasticMapper.save(entity); log.error("結束"); } @Override public MusicElasticEntity findByEntityId(Long id) { Optional<MusicElasticEntity> optional = musicElasticMapper.findById(id); MusicElasticEntity elasticEntity=null; if (optional.isPresent()) { elasticEntity = optional.get(); } return elasticEntity; } }
配置類
package com.aila.elasticSearch.config; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import org.elasticsearch.client.Client; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.elasticsearch.core.ElasticsearchTemplate; import org.springframework.data.elasticsearch.core.EntityMapper; import org.springframework.data.elasticsearch.core.geo.CustomGeoModule; import org.springframework.data.mapping.MappingException; import java.io.IOException; import java.util.HashMap; import java.util.Map; /** * @author chenzhichao * @date 2020/12/14 11:15 */ @Configuration public class ElasticSearchConfiguration { @Bean public ElasticsearchTemplate elasticsearchTemplate(Client client) { return new ElasticsearchTemplate(client, new CustomEntityMapper()); } public static class CustomEntityMapper implements EntityMapper { private final ObjectMapper objectMapper; public CustomEntityMapper() { objectMapper = new ObjectMapper(); objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true); objectMapper.registerModule(new CustomGeoModule()); objectMapper.registerModule(new JavaTimeModule()); } @Override public String mapToString(Object object) throws IOException { return objectMapper.writeValueAsString(object); } @Override public <T> T mapToObject(String source, Class<T> clazz) throws IOException { return objectMapper.readValue(source, clazz); } @Override public Map<String, Object> mapObject(Object source) { try { return objectMapper.readValue(mapToString(source), HashMap.class); } catch (IOException e) { throw new MappingException(e.getMessage(), e); } } @Override public <T> T readObject(Map<String, Object> source, Class<T> targetType) { try { return mapToObject(mapToString(source), targetType); } catch (IOException e) { throw new MappingException(e.getMessage(), e); } } } }
如果沒有這個配置類 LocaldateTime 會被轉成
一個類似下面的json 串 而elasticSearch 序列化不了這個json
"creationDate": { "dayOfYear": 123, "dayOfWeek": "FRIDAY", "month": "MAY", "dayOfMonth": 3, "year": 2019, "monthValue": 5, "hour": 11, "minute": 54, "second": 12, "nano": 238000000, "chronology": { "id": "ISO", "calendarType": "iso8601" } },
所以需要自定義entityMapper的對象使用jackson 來轉化 對應的localdateTIme來實現