- spring-boot 2.x
- mongogb-3.6
配置信息
依赖信息
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
配置信息
spring:
data:
mongodb:
host: 192.168.129.44
port: 27017
database: cmdb
# 自动将字段转换为驼峰标识存储到mongo中.
# 如 notifyNo 存储到mongodb中自动转换为: notify_no
field-naming-strategy: org.springframework.data.mapping.model.SnakeCaseFieldNamingStrategy
java-beans
类图
BasicPojo
定义通用的基础字段:如创建人/时间,修改人/时间,删除标识等。
public class BasicPojo<T> implements Serializable {
private static final long serialVersionUID = -8985545025018238754L;
//删除标识: 0:有效, 1:无效
//已设置了驼峰自动标识,无需使用@Field指定;
// @Field("del_flag")
@Getter @Setter
int delFlag;
@Getter @Setter
String createStaff;
@Getter @Setter
Date createTime;
@Getter @Setter
String updateStaff;
@Getter @Setter
Date updateTime;
}
NotifyMsg
测试实体NotifyMsg
,继承自BasicPojo
@Document(collection = "notify_msg")//集合名
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class NotifyMsg extends BasicPojo<String> {
@Id
String id;
/**
* 消息类型
*/
@Indexed
String notifyType;
/**
* 消息单号
*/
@Indexed(unique = true)
String notifyNo;
/**
* 消息通知日期
*/
String notifyDate;
/**
* 消息体
* 可指定存储时的字段名
*/
String notifyMsg;
}
索引
通过在属性上使用注解@Index
来创建索引;
@Index
:索引@Indexed(unique = true)
创建唯一索引
联合索引
通过在类上添加注解,来创建索引:
@Document(collection = XXX集合)
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
//复合索引: type 升序, code升序;
@CompoundIndexes({
@CompoundIndex(name = "type_code_unique_inx", def = "{'type': 1, 'code': 1}",unique = true)
})
public class XXX类 implements Serializable {
String type;
String code;
}
SpringDataPageable
mongodb请求分页参数bean:
public class SpringDataPageable implements Serializable, Pageable {
private static final long serialVersionUID = 1;
// 当前页
private Integer pagenumber = 1;
// 当前页面条数
private Integer pagesize = 10;
// 排序条件
private Sort sort;
// 当前页面
@Override
public int getPageNumber() {
return getPagenumber();
}
// 每一页显示的条数
@Override
public int getPageSize() {
return getPagesize();
}
// 第二页所需要增加的数量
@Override
public long getOffset() {
return (getPagenumber() - 1) * getPagesize();
}
//略....
}
SimplePageInfo(非必须)
由于springt框架返回的分页信息太多,自定义分页response-bean,只传递简要的分页信息即可(非必须)。
public class SimplePageInfo<T> implements Serializable {
private static final long serialVersionUID = 1L;
//总记录数
protected long total;
//结果集
protected List<T> list;
public SimplePageInfo() {
}
public SimplePageInfo(List<T> list) {
this.list = list;
if(list instanceof Page){
this.total = ((Page)list).getTotal();
}
}
public SimplePageInfo(List<T> list, long total) {
this.list = list;
this.total = total;
}
//略....
}
MongoTemplate
NotifyMsgServiceImpl 方法总览
@Service
public class NotifyMsgServiceImpl implements NotifyMsgService {
@Autowired
MongoTemplate mongoTemplate;
//增删改查method
}
新增-saveNotifyMsg()
@Override
public NotifyMsg saveNotifyMsg(NotifyMsg entity) {
//设置创建人信息,删除标识
entity.setCreateStaff("TEST");
entity.setCreateTime(new Date());
entity.setDelFlag( 0);
mongoTemplate.save(entity);
return entity;
}
使用 save和insert都可以进行插入
,区别:当存在"_id"时
- insert 插入已经存在的id时 会异常
- save 则会进行更新 (
"不存在的_id"就是insert操作, 存在就是update操作)
更新–updateNotifyMsg()
public NotifyMsg updateNotifyMsg(NotifyMsg entity) {
//业务要求,只允许修改 notifyMsg和notifyType两个字段的信息
if (entity.getNotifyMsg() != null || entity.getNotifyType() != null) {
Update update = new Update();
Optional.ofNullable(entity.getNotifyMsg()).ifPresent(msg -> {
update.set("notify_msg", msg);
});
Optional.ofNullable(entity.getNotifyType()).ifPresent(type -> {
update.set("notify_type", type);
});
//设置修改人信息
update.set("update_time", new Date());
update.set("update_staff", getCurrentStaff());
//设置查询条件: 主键为id 且删除位有效的数据
Query query = new Query(Criteria.where("id").is(new ObjectId(entity.getId())).and("del_flag").is(0));
//修改满足指定查询条件的第一条记录.
mongoTemplate.updateFirst(query, update, NotifyMsg.class);
}
return entity;
}
mongoTemplate.updateXXX
众多更新方法:
mongoTemplate.updateFirst
修改符合条件第一条记录mongoTemplate.updateMulti
: 修改符合条件的所有mongoTemplate.Upsert
: 修改符合条件时如果不存在则添加
逻辑删除-delNotifyMsgById()
@Override
public long delNotifyMsgById(String id) {
Query where = new Query(Criteria.where("id").is(new ObjectId(id)).and("del_flag").is(0));
//设置修改人信息
Update update = new Update();
update.set("update_time", new Date());
update.set("update_staff", getCurrentStaff());
update.set("del_flag", 1);
return mongoTemplate.updateFirst(where, update, NotifyMsg.class).getModifiedCount();
}
单个获取-findNotifyMsgByNo()
public NotifyMsg findNotifyMsgByNo(String notifyNo) {
//根据Criteria 改造查询条件
Query query = new Query(Criteria.where("notify_no").is(notifyNo).and("del_flag").is(0));
return mongoTemplate.findOne(query, NotifyMsg.class);
}
分页查询-qry()
public SimplePageInfo<NotifyMsg> qry(NotifyMsg param, int pageNum, int pageSize) {
SpringDataPageable pageable = new SpringDataPageable();
//排序
List<Sort.Order> orders = new ArrayList<>();
orders.add(new Sort.Order(Sort.Direction.DESC, "notify_no"));
Sort sort = Sort.by(orders);
// 开始页
pageable.setPagenumber(pageNum);
// 每页条数
pageable.setPagesize(pageSize);
// 排序
pageable.setSort(sort);
//查询条件...
Query query = new Query(Criteria.where("del_flag").is(0));
Field fields = query.fields();
// fields.exclude("_id"); //-- 排除_id字段
Optional.ofNullable(param).ifPresent(entity -> {
Criteria criteria = new Criteria();
Optional.ofNullable(entity.getId()).ifPresent(id -> {
criteria.and("id").is(new ObjectId(id));
});
Optional.ofNullable(entity.getNotifyNo()).ifPresent(notifyNo -> {
criteria.and("notify_no").is(notifyNo);
});
Optional.ofNullable(entity.getNotifyMsg()).ifPresent(notifyMsg -> {
//等价于: {"notifyMsg": /apple/}
//类似于sql: notifyMsg like '%apple%'
criteria.and("notify_msg").regex(notifyMsg);
});
Optional.ofNullable(entity.getNotifyType()).ifPresent(notifyType -> {
criteria.and("notify_type").in(notifyType);
});
query.addCriteria(criteria);
});
// 查询出一共的条数
Long count = mongoTemplate.count(query, NotifyMsg.class);
// 查询
List<NotifyMsg> list = mongoTemplate.find(query.with(pageable), NotifyMsg.class);
// 将集合与分页结果封装
SimplePageInfo<NotifyMsg> pagelist = new SimplePageInfo<NotifyMsg>(list, count);
return pagelist;
}
MongoTemplate特点
- 所有的更新操作都要指定创建人,修改人等信息–比较繁琐
- 最为常用的的查询方法,也需要通过手写实现。
JPA — MongoRepository
@CreatedBy,@CreatedDate,@LastModifiedBy,@LastModifiedDate
通过如上的注解,来实现在创建或修改
时自动设置创建人/时间,修改人/时间
等信息。
修改BasicPojo
,为其添加注解:
public class BasicPojo<T> implements Serializable {
private static final long serialVersionUID = -8985545025018238754L;
//已设置了驼峰自动标识,无需使用@Field指定;
// @Field("del_flag")
@Getter @Setter
int delFlag;
@CreatedBy
@Getter @Setter
String createStaff;
@CreatedDate
@Getter @Setter
Date createTime;
@LastModifiedBy
@Getter @Setter
String updateStaff;
@LastModifiedDate
@Getter @Setter
Date updateTime;
}
审计人信息自动注入类—AuditorAware
上文中的@CreatedDate,@LastModifiedDate
我们可以通过系统时间来自动注入。
但是@CreatedBy,@LastModifiedBy
人信息该如何设置呢,答案就是AuditorAware
.
@Configuration
public class UserAcctAuditorBean implements AuditorAware<String> {
private static final String ANONYMOUS = "Anonymous";
@Override
public Optional<String> getCurrentAuditor() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication != null && authentication.isAuthenticated() && !(authentication instanceof AnonymousAuthenticationToken)) {
OauthUserDetails oauthUserDetails = (OauthUserDetails) authentication.getPrincipal();
return Optional.of(oauthUserDetails.getLoginAcct());
} else {
return Optional.of(ANONYMOUS+ LocalDateTime.now().getSecond());
}
}
}
NotifyMsgRepository
public interface NotifyMsgRepository extends MongoRepository<NotifyMsg, String> {
/**
* @description 根据模块id + del_flag 获取bean, 并指定输出字段
* - ?0 是函数的参数。
* - fields 指定需要输出的字段
* @author trump
* @param id 主键
* @return
* @throws
*/
@Query(value = "{'id':?0, 'del_flag':0}" /*,fields="{ 'id' : 1, 'notify_type' : 1, 'notify_no' : 1, 'notify_msg' : 1}"*/)
Optional<NotifyMsg> getById2(String id);
/**
* 使用jpa方法: notifyNo + delFlag删除
* @param notifyNo 编码
* @param delFlag 删除位
* @return
*/
Optional<NotifyMsg> getNotifyMsgByNotifyNoAndDelFlag(String notifyNo,int delFlag);
default Optional<NotifyMsg> getNotifyMsgByNotify2(String notifyNo){
return getNotifyMsgByNotifyNoAndDelFlag(notifyNo, Constant.DEL_FLAG_EFFECTIVE);
}
}
NotifyMsgServiceImpl
public class NotifyMsgServiceImpl2 implements NotifyMsgService {
private Logger logger = LoggerFactory.getLogger(NotifyMsgServiceImpl2.class);
@Autowired
NotifyMsgRepository repository;
@Override
public NotifyMsg saveNotifyMsg(NotifyMsg entity) {
//使用 save和insert都可以进行插入
//区别:当存在"_id"时
//insert 插入已经存在的id时 会异常
//save 则会进行更新
//简单来说 save 就是不存在插入 存在更新
// mongoTemplate.insert(msg);
return repository.save(entity);
}
@Override
public NotifyMsg updateNotifyMsg(NotifyMsg param) {
repository.getById2(param.getId()).ifPresent(dbEntity -> {
if (dbEntity.getDelFlag() == Constant.DEL_FLAG_EFFECTIVE) {
//只允许修改notifyMsg 和 notifyType
Optional.ofNullable(param.getNotifyMsg()).ifPresent(newNotifyMsg -> {
dbEntity.setNotifyMsg(newNotifyMsg);
});
Optional.ofNullable(param.getNotifyType()).ifPresent(newNotifyType -> {
dbEntity.setNotifyType(newNotifyType);
});
dbEntity.setNotifyMsg(param.getNotifyMsg());
//save更新会将未传入的属性全部设置为null,所以需要将db中历史数据取出,然后更新指定字段
// db.xx.update({title:"xx"},{rank:99}) 及不带有$set形式的更新
// db.xx.update({title:"xx"},{$set:{rank: 10}})
repository.save(dbEntity);
}
});
return null;
}
@Override
public NotifyMsg findNotifyMsgByNo(String notifyNo) {
return repository.getNotifyMsgByNotify2(notifyNo).get();
}
@Override
public long delNotifyMsgById(String id) {
repository.getById2(id).ifPresent(dbEntity -> {
dbEntity.setDelFlag(Constant.DEL_FLAG_INVALID);
repository.save(dbEntity);
});
return 1;
}
@Override
public SimplePageInfo<NotifyMsg> qry(NotifyMsg param, int pageNum, int pageSize) {
SpringDataPageable pageable = new SpringDataPageable();
//排序
List<Sort.Order> orders = new ArrayList<>();
orders.add(new Sort.Order(Sort.Direction.DESC, "notify_no"));
Sort sort = Sort.by(orders);
// 开始页
pageable.setPagenumber(pageNum);
// 每页条数
pageable.setPagesize(pageSize);
// 排序
pageable.setSort(sort);
Page<NotifyMsg> page = repository.findAll(Example.of(param), pageable);
return new SimplePageInfo<>(page.getContent(), page.getTotalElements());
}
}