代码拉取完成,页面将自动刷新
一套对于mongoDB操作的半彻底封装
1.下载地址:http://www.mongodb.org/downloads (我下载的版本是mongodb-linux-x86_64-4.0.11) 2.安装如下:
//进入到指定的安装目录(我一般安装在/usr/local下),上传,解压,重命名
rz mongodb-linux-x86_64-4.0.11.tgz
tar -zxvf mongodb-linux-x86_64-4.0.11.tgz
mv mongodb-linux-x86_64-4.0.11 mongodb
//配置环境变量
vim /etc/profile
export PATH=/usr/local/mongodb/bin:$PATH
//保存退出,重新加载
source /etc/profile
//创建MongoDB数据存放文件夹和日志记录文件夹,为后面的配置文件使用:
mkdir -pv /usr/local/mongodb_file/data
mkdir -pv /usr/local/mongodb_file/logs
//创建配置文件,进入到MongoDB的bin目录下
vim mongodb.conf(直接是new file)
//编辑输入
dbpath = /usr/local/mongodb_file/data #数据文件存放目录
logpath = /usr/local/mongodb_file/logs/mongodb.log #日志文件存放目录
port = 27017 #端口,强烈建议更改
fork = true#以守护程序的方式启用,即在后台运行
auth=true #需要认证。如果放开注释,就必须创建MongoDB的账号,使用账号与密码才可远程访问,第一次安装建议注释,后面放开
bind_ip=127.0.0.1 #允许远程访问(0.0.0.0),或者直接注释掉,127.0.0.1是只允许本地访问
//启动MongoDB服务,进入bin目录下
./mongod -f mongodb.conf
//连接mongo,进入bin目录下
mongo
//如果这里改了端口,则连接为:
mongo localhost:port
//关闭mongo,查出pid,使用kill杀死对应的pid
ps -aux|grep mongo
kill -9 pid
3.用户密码权限的配置 如果你的应用部署在线上,切记一定要重视网络安全管理,改端口,添加用户密码,权限分配,再严谨一点就设置ip白名单。
//连接mongo
mongo localhost:****//如果没改端口,直接mongo,如果改了端口就指定端口连接
use admin
db.createUser({ user: "user", pwd: "password", roles: [{ role: "userAdminAnyDatabase",db: "admin" }] })
//userAdminAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的userAdmin权限
//验证权限
db.auth("user","password")
//修改权限
db.updateUser("user",{roles: [ "role","readWriteAnyDatabase",db: "admin"]})
//readWriteAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的读写权限
//其他的权限请自行百度或查询官方文档,我这里为方便,直接用readWriteAnyDatabase
这里采用hutool将mongoDB相关的业务操作做了一次比较彻底的封装,接入几乎无需做什么调整,直接传入DBName和tableName即可。
我新增了用户密码的设定和权限分配 hutool其实也封装的不是很完整,它采用连接池的方式来提供mongoClie1. nt,并未有具体的增删改查,而且相关文档也给的很简洁,需要我们自己进去阅读源码才能看懂代码贡献者的思路,然后在此基础上补充
maven项目,分两个模块,一个是base,一个是测试
模块名称 | 作用 |
---|---|
wangjc-mongo-base | 对于mongoDB的封装,config,实体的基类,service的基类(提供了很多方法),util………… |
wangjc-mongo-web-test | 测试,基本的增删改查 |
/**
* mongoDB的配置
* @author wangjc
* @title: MongoConfig
* @projectName wangjc-mongo
* @description: TODO
*/
public class MongoConfig {
private static final Log logger = LogFactory.get(MongoConfig.class);
/**
* MongoDB实例连接列表
*/
private static MongoDS DS;
/** 初始化MongoDS */
static {
try {
/** 配置文件的各个配置项 */
Setting setting = new Setting(MongoDS.MONGO_CONFIG_PATH);
GroupedMap groupsMap = setting.getGroupedMap();
List<String> groups = new ArrayList<String>();
Set<Map.Entry<String, LinkedHashMap<String, String>>> set = groupsMap.entrySet();
for(Map.Entry<String,LinkedHashMap<String,String>> entry:set){
if(entry.getKey() == null || entry.getKey() == ""){
continue;
}
String host = entry.getValue().get(MongoDBConstant.HOST);
if(host == null || host == ""){
continue;
}
logger.info("MongoDB初始化数据源[{}]信息",entry.getKey());
logger.info("MongoDB初始化数据源host[{}]信息",host);
groups.add(entry.getKey());
}
if(groups.size() > 0){
DS = MongoFactory.getDS(groups);
}else{
DS = MongoFactory.getDS(MongoDBConstant.DS_GROUP);
}
}catch (Exception e){
e.printStackTrace();
}
}
/**
* 获取实例连接
* @return
*/
public static MongoDS getMongoDS(){
return DS;
}
}
/**
* @author wangjc
* @title: MongoBaseEntity
* @projectName wangjc-mongo
* @description: TODO
*/
public class MongoBaseEntity implements Serializable {
private static final long serialVersionUID = 7923869056556509811L;
/**
* 在MongoDB中,存储于集合中的每一个文档都需要一个唯一的 _id 字段作为 primary_key。如果一个插入文档操作遗漏了``_id``
* 字段,MongoDB驱动会自动为``_id``字段生成一个 ObjectId,
*/
private ObjectId mongoId;
public ObjectId getMongoId() {
return mongoId;
}
public void setMongoId(ObjectId mongoId) {
this.mongoId = mongoId;
}
}
/**
* @author wangjc
* @title: MongoBaseService
* @projectName wangjc-mongo
* @description: TODO
*/
public abstract class MongoBaseService<T extends MongoBaseEntity> {
private static final Log logger = LogFactory.get(MongoBaseService.class);
/**
* 数据库名称
* @return
*/
public abstract String getDbName();
/**
* 表(集合)名称
* @return
*/
public abstract String getTableName();
/**
* 对应实体
* @return
*/
public abstract Class<T> getClazz();
/**
* 获取连接
* @return
*/
protected MongoCollection<Document> getCollection(){
return MongoConfig.getMongoDS().getCollection(getDbName(),getTableName());
}
/**
* 根据mongoId查询出对应的bean
* @param mongoId
* @return
*/
public T selectByMongoId(String mongoId){
MongoCollection<Document> table = getCollection();
Document query = getIdQuery(mongoId);
Document document = table.find(query).first();
if(document == null){
return null;
}else{
return documentToEntity(document);
}
}
/**
* 根据mongoId查询
* @param mongoId
* @return
*/
public T selectByMongoId(ObjectId mongoId){
return selectByMongoId(mongoId.toHexString());
}
/**
* 根据实体对象字段值,获取单条
* @param entity
* @return
*/
public T selectOne(T entity){
List<T> list = listByEntity(entity);
if(list.size() > 0){
return list.get(0);
}else {
return null;
}
}
/**
* 根据实体对象字段查询
* @param entity:为空时查全部,
* @return
*/
public List<T> listByEntity(T entity){
return listByEntity(entity,null);
}
/**
* 根据实体对象字段查询,并排序
* @param entity:为null时,默认查询全部
* @param sort 为null时默认不排序,设置排序字段为1升序,-1降序
* @return
*/
public List<T> listByEntity(T entity,T sort){
try {
MongoCollection<Document> table = getCollection();
Document query = getDocumentByEntity(entity);
logger.info("==============================listByEntity get query document is:[{}]",query.toJson().toString());
final List<T> ret = new ArrayList<T>();
Block<Document> processBlock = new Block<Document>() {
public void apply(final Document document) {
ret.add(documentToEntity(document));
}
};
if(sort == null){
table.find(query).forEach(processBlock);
}else{
Document document = getDocumentByEntity(sort);
table.find(query).sort(document).forEach(processBlock);
}
return ret;
}catch (Exception e){
logger.error("listByEntity error:[{}]",e.getMessage());
}
return new ArrayList<T>();
}
/**
* 查询所有
* @return
*/
public List<T> listAll(){
return listAll(null);
}
/**
* 查询所有并排序
* @param sort
* @return
*/
public List<T> listAll(T sort){
return listByEntity(null,sort);
}
/**
* 插入单条记录
* @param one
* @return:返回mongoId
*/
public String insertOne(T one){
if(one == null){
return null;
}
MongoCollection<Document> table = getCollection();
Document docine = Document.parse(JSON.toJSONString(one));//转为json格式
docine.remove(MongoDBConstant.MongoId);
docine.put(MongoDBConstant.MongoId,new ObjectId());
table.insertOne(docine);
return docine.get(MongoDBConstant.MongoId).toString();
}
/**
* 更新数据,多余的字段,会在集合的这条记录上追加
* @param one
* @return
*/
public Long updateOne(T one){
Long num = 0L;
try {
MongoCollection<Document> table = getCollection();
Document updateSet = getUpdateSet(one);
logger.info("=======================updateOne mongoId is :[{}],get update set document is :[{}]",one.getMongoId().toString(),updateSet.toJson().toString());
UpdateResult result = table.updateMany(getIdQuery(one.getMongoId()), updateSet);
num = result.getModifiedCount();
logger.info("updateOne:[{}]",num);
}catch (Exception e){
logger.info("updateOne error [{}]",e.getMessage());
}
return num;
}
/**
* 批量更新
* @param query:用于查询条件的实体对象(字段)
* @param upset:用于更新的实体对象(字段)
* @return
*/
public Long updateBatch(T query,T upset){
Long num = 0L;
try {
Document qfilter = getDocumentByEntity(query);
logger.info("=======================updateBatch get query document is :[{}]",qfilter.toJson().toString());
Document updateSet = getUpdateSet(upset);
logger.info("=======================updateBatch get update set document is :[{}]",updateSet.toJson().toString());
UpdateResult result = getCollection().updateMany(qfilter, updateSet);
num = result.getModifiedCount();
logger.info("updateBatch ModifiedCount;[{}]",num);
}catch (Exception e){
logger.info("updateBatch error [{}]",e.getMessage());
}
return num;
}
/**
* 删除,根据mongoId
* @param mongoId
* @return
*/
public Long deleteOne(ObjectId mongoId){
return deleteOne(mongoId.toHexString());
}
/**
* 删除,根据mongoId
* @param mongoId
* @return
*/
public Long deleteOne(String mongoId){
Document query = getIdQuery(mongoId);
MongoCollection<Document> table = getCollection();
DeleteResult result = table.deleteOne(query);
return result.getDeletedCount();
}
/**
* 批量删除,根据实体类的字段值
* @param entity
* @return
*/
public Long deleteByEntity(T entity){
if(entity == null){
logger.info("deleteByEntity error: update entity is null");
return null;
}
try {
Document document = getDocumentByEntity(entity);
logger.info("===========================deleteByEntity get query document is : [{}]",document.toJson().toString());
if(document.size() <= 0){
logger.error("deleteByEntity error:entity doesn't have any properties");
}
DeleteResult result = getCollection().deleteMany(document);
return result.getDeletedCount();
}catch (Exception e){
logger.info("deleteByEntity error [{}] class:[{}]",e.getMessage(),entity.getClass().getName());
return null;
}
}
/**
* 根据实体来获取Document
* @param entity
* @return
* @throws IllegalAccessException
* @throws InvocationTargetException
*/
private Document getDocumentByEntity(T entity) throws IllegalAccessException,InvocationTargetException{
Document query = new Document();
if(entity == null){
return query;
}
Field[] fields = MongoUtil.getFields(getClazz());
for(Field f:fields){
if(MongoDBConstant.SerialVersionUID.equals(f.getName())){//过滤掉序列化id
continue;
}
f.setAccessible(true);
Object obj = f.get(entity);
if(obj == null){
continue;
}
query.append(f.getName(),obj);
}
return query;
}
/**
* 根据Document获取实体
* @param document
* @return
*/
private T documentToEntity(Document document){
try {
T t = getClazz().newInstance();
Field[] fields = MongoUtil.getFields(getClazz());
for (Field f:fields){
if(document.get(f.getName()) == null){
continue;
}
Object value = document.get(f.getName());
if(value == null){
continue;
}
if(f.getName().equals(MongoDBConstant.MongoId)){
value = new ObjectId(String.valueOf(value));
}
setFieldValue(t,f,value);
}
return t;
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
/**
* 给字段设置值
* @param t
* @param field
* @param value
*/
private void setFieldValue(T t,Field field,Object value){
try {
field.setAccessible(true);//设置可见
field.set(t,value);
} catch (IllegalAccessException e) {
logger.error("IllegalAccess异常 [{}],[{}]",t.getClass(),field.getName());
e.printStackTrace();
}
}
/**
* 获取更新后的document
* @param entity
* @return
*/
private Document getUpdateSet(T entity){
Document set = null;
try {
set = getDocumentByEntity(entity);
set.remove(MongoDBConstant.MongoId);
set = new Document("$set",set);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return set;
}
/**
* 通过id获取document
* @param mongoId
* @return
*/
private Document getIdQuery(String mongoId){
return getIdQuery(new ObjectId(mongoId));
}
private Document getIdQuery(Object id){
Document query = new Document();
query.append(MongoDBConstant.MongoId,id);
return query;
}
}
/**
* mongo的工具类
* @author wangjc
* @title: MongoUtil
* @projectName wangjc-mongo
* @description: TODO
*/
public class MongoUtil {
/**
* 线程安全的map
*/
private static final Map<String, Field[]> FIELDS_CACHE = new ConcurrentHashMap<String, Field[]>();
public static Field[] getFields(Class clazz){
Field[] fields = FIELDS_CACHE.get(clazz.toString());
if(null != fields){
return fields;
}else{
fields = getFieldsDirectly(true,clazz);
FIELDS_CACHE.put(clazz.toString(),fields);
return fields;
}
}
/**
* 获取类的字段数组
* @param withSuperClassFields:(是否直接带有父类)
* @param claz
* @return
*/
public static Field[] getFieldsDirectly(boolean withSuperClassFields,Class<?> claz){
Field[] allFields = null;
Class<?> searchType = claz;
Field[] declaredFields;
while (searchType != null){
declaredFields = searchType.getDeclaredFields();
if(allFields == null){
allFields = declaredFields;
}else{
allFields = append(allFields,declaredFields);
}
searchType = withSuperClassFields ? searchType.getSuperclass():null;
}
return allFields;
}
/**
* 追加字段
* @param buffer
* @param newElements
* @return
*/
private static Field[] append(Field[] buffer,Field... newElements){
if(isEmpty(buffer)){
return newElements;
}else{
return insert(buffer,buffer.length,newElements);
}
}
/**
* 字段添加
* @param array
* @param index
* @param newFieldlements
* @return
*/
private static Field[] insert(Field[] array,int index,Field... newFieldlements){
if(isEmpty(newFieldlements)){
return array;
}
if(isEmpty(array)){
return newFieldlements;
}
final int len = length(array);
if(index < 0){
index = (index % len) + len;
}
Field[] result = newArray(array.getClass().getComponentType(),Math.max(len,index)+newFieldlements.length);
System.arraycopy(array,0,result,0,Math.min(len,index));
System.arraycopy(newFieldlements,0,result,index,newFieldlements.length);
if(index < len){
System.arraycopy(array,index,result,index+newFieldlements.length,len - index);
}
return result;
}
/**
* 获取新的字段数组
* @param componentType
* @param newSize
* @return
*/
private static Field[] newArray(Class<?> componentType,int newSize){
return (Field[]) Array.newInstance(componentType,newSize);
}
/**
* 判断类的字段非空
* @param array
* @return
*/
private static boolean isEmpty(Field... array){
return array == null || array.length == 0;
}
/**
* 获取指定数组类长度,私有
* @param array
* @return
*/
private static int length(Object array) throws IllegalArgumentException{
if(null == array){
return 0;
}else {
return Array.getLength(array);
}
}
}
/**
* 测试实体
* @author wangjc
* @title: MongText
* @projectName wangjc-mongo
* @description: TODO
*/
public class MongoTextInfo extends MongoBaseEntity{
private static final long serialVersionUID = 3742429841077146407L;
/**
* 内容
*/
private String content;
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
/**
* 这里的dbName,tableName建议以枚举或者常量的方式统一存放,以便全局更改,
* 此处是为了方便快捷省事
* @author wangjc
* @title: MongoText
* @projectName wangjc-mongo
* @description: TODO
*/
@Component
public class MongoTextService extends MongoBaseService<MongoTextInfo> {
@Override
public String getDbName() {
return "text";
}
@Override
public String getTableName() {
return "text_info";
}
@Override
public Class<MongoTextInfo> getClazz() {
return MongoTextInfo.class;
}
}
/**
* @author wangjc
* @title: TestController
* @projectName wangjc-mongo
* @description: TODO
*/
@RestController
public class TestController {
@Autowired
private MongoTextService mongoTextService;
/**
* 新增
* @return
*/
@RequestMapping(value = "/insert")
public String insert(){
String info = "这是一段长达250KB的富文本信息";
MongoTextInfo textInfo = new MongoTextInfo(){{
setContent(info);
}};
String mongoId = mongoTextService.insertOne(textInfo);
return "存储成功,mongoId:"+mongoId;
}
/**
* 修改
* @param mongoId
* @return
*/
@RequestMapping(value = "/update",method = {RequestMethod.GET,RequestMethod.POST})
public String update(String mongoId){
MongoTextInfo textInfo = new MongoTextInfo(){{
setContent("我也可以用来存储任何长文本信息,减轻关系型数据库的读写压力");
setMongoId(new ObjectId(mongoId));
}};
Long update = mongoTextService.updateOne(textInfo);
return "修改成功,更新条目:"+update;
}
/**
* 删除
* @param mongoId
* @return
*/
@RequestMapping(value = "/delete",method = {RequestMethod.GET,RequestMethod.POST})
public String delete(String mongoId){
Long delete = mongoTextService.deleteOne(mongoId);
return "删除成功,删除条目:"+delete;
}
/**
* 查询全部,你也可以条件查询,排序查询,具体看MongoBaseService中封装的方法
* @return
*/
@RequestMapping(value = "/selectAll")
public List<MongoTextInfo> selectAll(){
List<MongoTextInfo> list = mongoTextService.listAll();
return list;
}
}
启动wangjc-mongo-web-test,然后分别测试给定的增删改查接口, 注意:因为这里是自定义的封装,需要摒弃spring Boot自带的mongoDB组件,不然会启动报错
@SpringBootApplication(exclude = {MongoAutoConfiguration.class, MongoDataAutoConfiguration.class})
public class WangjcMongoWebTestApplication {
public static void main(String[] args) {
SpringApplication.run(WangjcMongoWebTestApplication.class, args);
}
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。