1、maven配置
<dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-solr</artifactId> <version>4.0.10.RELEASE</version> </dependency> <dependency> <groupId>org.apache.solr</groupId> <artifactId>solr-solrj</artifactId> <version>7.7.2</version> </dependency>
2、application-solr.xml配置
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:solr="http://www.springframework.org/schema/data/solr" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/data/solr https://www.springframework.org/schema/data/solr/spring-solr.xsd"> <solr:solr-client id="solrClient" url="${solr.url}" /> <solr:repositories base-package="com.zhi.demo.**.repository" /> <bean name="solrTemplate" class="org.springframework.data.solr.core.SolrTemplate"> <constructor-arg name="solrClient" ref="solrClient" /> <!-- 根据Indexed注解创建不存在的字段 --> <property name="schemaCreationFeatures"> <list> <value>CREATE_MISSING_FIELDS</value> </list> </property> </bean> </beans>
注意schemaCreationFeatures选择,如果有CREATE_MISSING_FIELDS选择,Spring会在启动时根据Indexed注解在solr中创建没定义的field。关键代码:
3、创建Bean
Dept.java
package com.zhi.demo.dept.model; import java.util.Date; import org.springframework.data.annotation.Id; import org.springframework.data.solr.core.mapping.Indexed; import org.springframework.data.solr.core.mapping.SolrDocument; /** * 部门信息,collection为对应的core名称,Indexed注解会自动在solr添加对应的field * * @author zhi * @time 2016年12月22日09:55:08 * */ @SolrDocument(collection = "dept") public class Dept { /** * 部门ID */ @Id @Indexed private String id; /** * 部门名称 */ @Indexed(type = "text_ik") private String name; /** * 创建时间 */ @Indexed(name = "createTime", type = "pdate") private Date createTime; /** * 备注 */ @Indexed(type = "text_ik") private String remark; public Dept() { super(); } public Dept(String id, String name, Date createTime, String remark) { super(); this.id = id; this.name = name; this.createTime = createTime; this.remark = remark; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Date getCreateTime() { return createTime; } public void setCreateTime(Date createTime) { this.createTime = createTime; } public String getRemark() { return remark; } public void setRemark(String remark) { this.remark = remark; } }
Person.java
package com.zhi.demo.person.model; import java.io.Serializable; import java.util.Date; import org.springframework.data.annotation.Id; import org.springframework.data.solr.core.mapping.Indexed; /** * 人员信息 * * @author 张远志 * @time 2016年12月22日09:55:42 * */ @SuppressWarnings("serial") public class Person implements Serializable { /** * 主键 */ @Id @Indexed private String id; /** * 人员名称 */ @Indexed private String name; /** * 地址 */ @Indexed private String addr; /** * 年龄 */ private Integer age; /** * 部门ID */ private String deptId; /** * 是否可用 */ private boolean usable; /** * 创建时间 */ private Date createTime; /** * 备注 */ private String remark; public Person() { super(); } public Person(String id, String name, String addr, Integer age, String deptId, boolean usable, Date createTime, String remark) { super(); this.id = id; this.name = name; this.addr = addr; this.age = age; this.deptId = deptId; this.usable = usable; this.createTime = createTime; this.remark = remark; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAddr() { return addr; } public void setAddr(String addr) { this.addr = addr; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getDeptId() { return deptId; } public void setDeptId(String deptId) { this.deptId = deptId; } public boolean isUsable() { return usable; } public void setUsable(boolean usable) { this.usable = usable; } public Date getCreateTime() { return createTime; } public void setCreateTime(Date createTime) { this.createTime = createTime; } public String getRemark() { return remark; } public void setRemark(String remark) { this.remark = remark; } }
4、使用Repository方式进行CRUD操作
创建DeptRepository.java
package com.zhi.demo.dept.repository; import java.util.List; import org.springframework.data.solr.repository.Query; import org.springframework.data.solr.repository.SolrCrudRepository; import com.zhi.demo.dept.model.Dept; /** * 部门增删改查操作 * * @author zhi * @since 2019年9月27日14:05:15 * */ public interface DeptRepository extends SolrCrudRepository<Dept, String> { @Query("name:?0 OR remark:?0") List<Dept> findList(String text); }
定义Dept操作接口和实现
package com.zhi.demo.dept.service; import java.util.List; import com.zhi.demo.dept.model.Dept; /** * 部门操作接口 * * @author zhi * @since 2019年9月27日13:12:26 * */ public interface IDeptService { /** * 保存 * * @param model * @return */ Dept save(Dept model); /** * 批量保存 * * @param models * @return */ List<Dept> saveBatch(List<Dept> models); Dept findById(String id); List<Dept> list(String text); }
package com.zhi.demo.dept.service.impl; import java.util.List; import java.util.Optional; import org.apache.commons.collections4.IteratorUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.zhi.demo.dept.model.Dept; import com.zhi.demo.dept.repository.DeptRepository; import com.zhi.demo.dept.service.IDeptService; /** * 部门操作接口实现 * * @author zhi * @since 2019年9月27日13:12:26 * */ @Service public class DeptServiceImpl implements IDeptService { @Autowired private DeptRepository deptRepository; @Override public Dept save(Dept model) { deptRepository.save(model); return model; } @Override public List<Dept> saveBatch(List<Dept> models) { deptRepository.saveAll(models); return models; } @Override public Dept findById(String id) { Optional<Dept> optional = deptRepository.findById(id); if (optional.isPresent()) { return optional.get(); } return null; } @Override public List<Dept> list(String text) { if (StringUtils.isEmpty(text)) { return IteratorUtils.toList(deptRepository.findAll().iterator()); } else { return deptRepository.findList(text); } } }
Junit测试
package com.zhi.test; import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.zhi.demo.dept.model.Dept; import com.zhi.demo.dept.service.IDeptService; /** * Solr部门测试 * * @author zhi * @since 2019年9月29日15:06:06 * */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = { "classpath:application.xml", "classpath*:application-*.xml" }) public class DeptTest { private Logger logger = LogManager.getLogger(this.getClass()); @Autowired private IDeptService deptService; @Test public void saveBatch() { try { deptService.saveBatch(ModelData.getDeptData()); logger.info("保存成功"); } catch (Exception e) { logger.error("保存出错", e); } } @Test public void findOne() { try { Dept dept = deptService.findById("01"); if (dept == null) { logger.info("根据ID未查询到记录"); } else { logger.info("查询结果:id={},name={},remark{}", dept.getId(), dept.getName(), dept.getRemark()); } } catch (Exception e) { logger.error("查询出错", e); } } @Test public void list() { try { List<Dept> list = deptService.list("公司"); logger.info("查询到的数据长度:{}", list.size()); for (Dept dept : list) { logger.info("id={},name={},remark{}", dept.getId(), dept.getName(), dept.getRemark()); } } catch (Exception e) { logger.error("查询出错", e); } } }
5、使用SolrTemplate进行CRUD删除
定义接口和实现
package com.zhi.demo.person.service; import java.util.List; import com.zhi.demo.person.model.Person; /** * 人员操作接口 * * @author zhi * @since 2019年9月27日11:33:31 * */ public interface IPersonService { /** * 保存人员, * * @param model * @return */ Person save(Person model); /** * 批量保存人员 * * @param models * @return */ List<Person> saveBatch(List<Person> models); /** * 根据ID查询人员信息 * * @param id * @return */ Person findById(String id); /** * 根据关键字查询人员列表 * * @param text 与name和addr字段匹配 * @return 列表长度由solr默认分页长度决定 */ List<Person> list(String text); /** * 根据可用状态查找人员列表 * * @param usable 与usable字段匹配 * @return 列表长度由solr默认分页长度决定 */ List<Person> usable(Boolean usable); }
package com.zhi.demo.person.service.impl; import java.time.Duration; import java.util.List; import java.util.Optional; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.solr.core.SolrTemplate; import org.springframework.data.solr.core.query.Criteria; import org.springframework.data.solr.core.query.SimpleQuery; import org.springframework.data.solr.core.query.SimpleStringCriteria; import org.springframework.stereotype.Service; import com.zhi.demo.person.model.Person; import com.zhi.demo.person.service.IPersonService; /** * 人员操作接口实现 * * @author zhi * @since 2019年9月27日11:33:31 * */ @Service public class PersonServiceImpl implements IPersonService { @Autowired private SolrTemplate solrTemplate; @Override public Person save(Person model) { solrTemplate.saveBean("person", model); solrTemplate.commit("person"); // 手工提交数据 return model; } @Override public List<Person> saveBatch(List<Person> models) { solrTemplate.saveBeans("person", models, Duration.ofSeconds(2)); // 自动提交 return models; } public Person findById(String id) { Criteria criteria = new Criteria("id"); criteria.is(id); Optional<Person> optional = solrTemplate.queryForObject("person", new SimpleQuery(criteria), Person.class); return optional.isPresent() ? optional.get() : null; } @Override public List<Person> list(String text) { SimpleQuery query = new SimpleQuery(); if (!StringUtils.isEmpty(text)) { Criteria criteria = new SimpleStringCriteria("name:" + text + " OR addr:" + text); query.addCriteria(criteria); } Page<Person> page = solrTemplate.query("person", query, Person.class); return page.getContent(); } @Override public List<Person> usable(Boolean usable) { SimpleQuery query = new SimpleQuery(); if (usable != null) { Criteria criteria = new Criteria("usable"); criteria.is(usable); query.addCriteria(criteria); } Page<Person> page = solrTemplate.query("person", query, Person.class); return page.getContent(); } }
Junit测试
package com.zhi.test; import java.util.Date; import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.zhi.demo.person.model.Person; import com.zhi.demo.person.service.IPersonService; import com.zhi.demo.utils.TimerUtil; /** * Solr人员操作测试 * * @author 张远志 * @since 2019年9月29日15:34:55 * */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = { "classpath:application.xml", "classpath*:application-*.xml" }) public class PersonTest { private Logger logger = LogManager.getLogger(this.getClass()); @Autowired private IPersonService personService; @Test public void saveBatch() { try { personService.saveBatch(ModelData.getPersonData()); logger.info("保存成功"); } catch (Exception e) { logger.error("保存出错", e); } } @Test public void findOne() { try { Person model = personService.findById("01"); if (model == null) { logger.info("根据ID未查询到记录"); } else { logger.info("查询结果:id={},name={},addr={}", model.getId(), model.getName(), model.getAddr()); } } catch (Exception e) { logger.error("查询出错", e); } } @Test public void list() { try { List<Person> list = personService.list("武汉"); logger.info("查询到的数据长度:{}", list.size()); for (Person item : list) { logger.info("id={},name={},addr={}", item.getId(), item.getName(), item.getAddr()); } } catch (Exception e) { logger.error("查询出错", e); } } @Test public void usable() { try { List<Person> list = personService.usable(false); logger.info("查询到的数据长度:{}", list.size()); for (Person item : list) { logger.info("id={},name={},addr={}", item.getId(), item.getName(), item.getAddr()); } } catch (Exception e) { logger.error("查询出错", e); } } @Test public void pressure() { Date start = new Date(); for (int i = 0; i < 10000; i++) { personService.list("武汉"); } logger.info(TimerUtil.format(start)); } }