java操作mongodb,泛型封裝增刪查改、條件查詢等操作
本文實現一個通用泛型封裝實現類,需要給定一個集合物件,類似mysql中與java對應的表;思想就是把給定的物件解析出所有非空欄位,儲存到一個BasicDBObject中,這裡一定要保證java物件與mongodb中的文件欄位名字一樣,因為程式碼為了實現通用,是預設以java物件的欄位為BasicDBObject的查詢欄位。
核心程式碼1:這是將java物件轉換為查詢條件。
/** * 通過反射獲取非空欄位資訊 * @param record * @param <Q> * @return */ private <Q> BasicDBObject getCondition(Q record) { BasicDBObject cond = new BasicDBObject(); Class clazz = record.getClass(); Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { try { field.setAccessible(true); Object value = field.get(record); if (value != null) cond.put(field.getName(), value); } catch (IllegalAccessException e) { e.printStackTrace(); } } return cond; }
核心程式碼2:這是將查詢到的文件轉換為java物件,這裡也是預設java物件的欄位和資料庫文件欄位一樣,也是利用java的反射動態獲取使用者自定義物件的所有欄位,然後進行賦值,我在賦值過程中單獨判斷了int和long型,因為插入mongodb的時候一般是以double存的,這樣就會造成轉型錯誤。
/** * 將結果轉化為自定義物件 * @param document * @param target * @param <Q> * @return */ private <Q> Q parseToObject(Document document, Class<Q> target) { try { Q result = target.newInstance(); Field[] fields = target.getDeclaredFields(); for (Field f : fields) { f.setAccessible(true); Object value = document.get(f.getName()); if (value == null) continue; else if (f.getType() == Integer.class) f.set(result, ((Number) value).intValue()); else if (f.getType() == Long.class) f.set(result, ((Number) value).longValue()); else f.set(result, document.get(f.getName(), f.getType())); } return result; } catch (IllegalAccessException e) { e.printStackTrace(); return null; } catch (InstantiationException e) { e.printStackTrace(); return null; } }
呼叫方法:先轉換查詢引數,查詢的時候是以id來判斷正序倒序,所以預設資料庫中一定要有id的標識欄位。
public <Q> List<Q> queryByCondition(BaseQuery<Q> query,boolean up) { Q record = query.getQuery(); BasicDBObject cond = getCondition(record); FindIterable<Document> findIterable; if (query.getStart() != null && query.getRows() != null) findIterable = thisCollection().find(cond) .sort(new BasicDBObject("id", up ? 1 : -1)) .skip((query.getStart() - 1) * query.getRows()) .limit(query.getRows()); else findIterable = thisCollection().find(cond) .sort(new BasicDBObject("id", up ? 1 : -1)); MongoCursor<Document> iterator = findIterable.iterator(); List<Q> result = new ArrayList<>(); while (iterator.hasNext()) { Document document = iterator.next(); result.add((Q) parseToObject(document, record.getClass())); } iterator.close(); return result; }
這裡傳入的BaseQuery如下:裡面的query就是個需要查詢的java物件,start&rows是為了用來分頁的。這裡是用到了lombok的外掛,這樣簡化很多的gettter&setter等程式碼。
@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Data
@Accessors(chain = true)
public class BaseQuery<Q> {
private Integer start;
private Integer rows;
private Q query;
public BaseQuery(Class clazz) {
try {
this.query = (Q) clazz.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
測試條件查詢方法:這裡用到的實體如下:
@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
public class User_info {
private Integer id;
private String name;
private Integer age;
private Integer role;
}
public static void main(String[] args) {
User_info record = new User_info();
BaseQuery<User_info> query = new BaseQuery<>();
query.setQuery(record);
BaseMongoDao dao = new BaseMongoDao("test");
List<User_info> result = dao.queryByCondition(query, true);
for (User_info user : result) {
System.out.println(user);
}
}
因為這裡用到的查詢條件為空,所有會匹配資料庫的所有項:
現在測試一下設定許可權為1的資料:
public static void main(String[] args) {
User_info record = new User_info();
record.setRole(1);
BaseQuery<User_info> query = new BaseQuery<>();
query.setQuery(record);
BaseMongoDao dao = new BaseMongoDao("test");
List<User_info> result = dao.queryByCondition(query, true);
for (User_info user : result) {
System.out.println(user);
}
}
輸出:
這個條件查詢方法是一個例子,其他的刪除,增加,修改都是這個原理,下面帶有:
1.public <Q> List<Q> queryByCondition(BaseQuery<Q> query,boolean up)
2.public <Q> Integer queryCoditionCount(BaseQuery<Q> query)
3.public <Q> boolean insertOne(Q record)
4.public <Q> boolean insertList(List<Q> records)
5.public boolean deleteById(Integer id)
6.public boolean deleteByIds(List<Integer> ids)
7.public <Q> void updateById(Q record)
放上所有程式碼:
package cn.wzy.dao;
import com.mongodb.*;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;
import org.cn.wzy.query.BaseQuery;
import org.cn.wzy.util.PropertiesUtil;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
/**
* Create by Wzy
* on 2018/7/28 18:15
* 不短不長八字剛好
*/
public class BaseMongoDao {
private static final MongoClient mongoClient;
private static final MongoDatabase mongo;
static {
MongoClientOptions options = MongoClientOptions.builder()
.connectionsPerHost(150)
.maxWaitTime(2000)
.socketTimeout(2000)
.maxConnectionLifeTime(5000)
.connectTimeout(5000).build();
ServerAddress serverAddress = new ServerAddress(PropertiesUtil.StringValue("mongo.host"),
PropertiesUtil.IntegerValue("mongo.port"));
List<ServerAddress> addrs = new ArrayList<>();
addrs.add(serverAddress);
MongoCredential credential = MongoCredential.createScramSha1Credential(
PropertiesUtil.StringValue("mongo.user")
, PropertiesUtil.StringValue("mongo.db")
, PropertiesUtil.StringValue("mongo.pwd").toCharArray());
mongoClient = new MongoClient(addrs, credential, options);
mongo = mongoClient.getDatabase(PropertiesUtil.StringValue("mongo.db"));
}
public BaseMongoDao(String colName) {
this.colName = colName;
}
private String colName;
private MongoCollection<Document> thisCollection() {
return mongo.getCollection(colName);
}
public <Q> List<Q> queryByCondition(BaseQuery<Q> query,boolean up) {
Q record = query.getQuery();
BasicDBObject cond = getCondition(record);
FindIterable<Document> findIterable;
if (query.getStart() != null && query.getRows() != null)
findIterable = thisCollection().find(cond)
.sort(new BasicDBObject("id", up ? 1 : -1))
.skip((query.getStart() - 1) * query.getRows())
.limit(query.getRows());
else
findIterable = thisCollection().find(cond)
.sort(new BasicDBObject("id", up ? 1 : -1));
MongoCursor<Document> iterator = findIterable.iterator();
List<Q> result = new ArrayList<>();
while (iterator.hasNext()) {
Document document = iterator.next();
result.add((Q) parseToObject(document, record.getClass()));
}
iterator.close();
return result;
}
public <Q> Integer queryCoditionCount(BaseQuery<Q> query) {
Q record = query.getQuery();
BasicDBObject cond = getCondition(record);
return (int) thisCollection().countDocuments(cond);
}
public <Q> boolean insertOne(Q record) {
BasicDBObject cond = getCondition(record);
try {
int top = getTop();
cond.put("id",++top);
thisCollection().insertOne(new Document(cond));
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
public <Q> boolean insertList(List<Q> records) {
try {
List<Document> list = new ArrayList<>(records.size());
if (!changeIds(records))
return false;
for (Q record : records) {
list.add(new Document(getCondition(record)));
}
thisCollection().insertMany(list);
return true;
}catch (Exception e) {
e.printStackTrace();
return false;
}
}
public boolean deleteById(Integer id) {
try {
if (id == null)
return false;
thisCollection().deleteOne(new BasicDBObject("id",id));
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
public boolean deleteByIds(List<Integer> ids) {
BasicDBObject cond = new BasicDBObject("id",new BasicDBObject("$in",ids.toArray()));
try {
thisCollection().deleteMany(cond);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 只通過id更改,查詢就只是搜尋id
* @param record
* @param <Q>
*/
public <Q> void updateById(Q record) {
BasicDBObject cond = getCondition(record);
BasicDBObject update = new BasicDBObject("$set",cond);
BasicDBObject query = new BasicDBObject("id",cond.get("id"));
thisCollection().updateOne(query,update);
}
/**
* 通過反射獲取非空欄位資訊
* @param record
* @param <Q>
* @return
*/
private <Q> BasicDBObject getCondition(Q record) {
BasicDBObject cond = new BasicDBObject();
Class clazz = record.getClass();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
try {
field.setAccessible(true);
Object value = field.get(record);
if (value != null)
cond.put(field.getName(), value);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return cond;
}
/**
* 將結果轉化為自定義物件
* @param document
* @param target
* @param <Q>
* @return
*/
private <Q> Q parseToObject(Document document, Class<Q> target) {
try {
Q result = target.newInstance();
Field[] fields = target.getDeclaredFields();
for (Field f : fields) {
f.setAccessible(true);
Object value = document.get(f.getName());
if (value == null)
continue;
else if (f.getType() == Integer.class)
f.set(result, ((Number) value).intValue());
else if (f.getType() == Long.class)
f.set(result, ((Number) value).longValue());
else
f.set(result, document.get(f.getName(), f.getType()));
}
return result;
} catch (IllegalAccessException e) {
e.printStackTrace();
return null;
} catch (InstantiationException e) {
e.printStackTrace();
return null;
}
}
/**
* 使id自增
* @param records
* @param <Q>
* @return
*/
private <Q> boolean changeIds(List<Q> records) {
if (records == null || records.size() == 0)
return false;
Class clazz = records.get(0).getClass();
try {
Field id = clazz.getDeclaredField("id");
id.setAccessible(true);
int top = getTop();
for (Q record: records) {
id.set(record,++top);
}
} catch (NoSuchFieldException e) {
e.printStackTrace();
return false;
} catch (IllegalAccessException e) {
e.printStackTrace();
return false;
}
return true;
}
/**
* 查詢頂針
* @return
*/
private int getTop() {
return ((Number) thisCollection().find().sort(new BasicDBObject("id",-1)).first().get("id")).intValue();
}
}