支持 列表,哈希,数组和基本类型
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.TypeVariable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.bson.Document;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.annotation.Transient;
public class BsonUtil {
private static Logger logger = LoggerFactory.getLogger(BsonUtil.class);
public static <T> List<T> toBeans(List<Document> documents, Class<T> clazz){
List<T> list = new ArrayList<T>();
for (int i = 0; null != documents && i < documents.size(); i++) {
list.add(toBean(documents.get(i), clazz));
}
return list;
}
@SuppressWarnings({ "rawtypes", "unused", "unchecked" })
public static <T> T toBean(Document document,Class<T> clazz) {
T entity = null;
try {
entity = (T)clazz.newInstance();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
if(Modifier.isStatic(field.getModifiers())) {
continue;//静态成员不转换
}
field.setAccessible(true);
Class fieldClazz = field.getType();
String key = field.getName();
if("id".equals(key)) {
key = "_id";
}
Object value = null;
try {
value = field.get(entity);
} catch (Exception e) {
e.printStackTrace();
}
Object val = document.get(key);
if(val == null) {
continue;
}
if(isPrimitive(fieldClazz) || fieldClazz == String.class) {
if(field!=null) field.set(entity, val);
continue;
}
//数组
if(fieldClazz.isArray()) {
String itemClazzName = fieldClazz.getTypeName().substring(0, fieldClazz.getTypeName().length()-2);
Class itemClazz = null;
try {
itemClazz = Class.forName(itemClazzName);
} catch (ClassNotFoundException e) {
//此时为基本类型
itemClazz = toPrimitiveClass(itemClazzName);
}
Object array = toArray(document.get(key),itemClazz);
if(field!=null) field.set(entity, array);
continue;
}
//列表
if (List.class.isAssignableFrom(fieldClazz)) {
ParameterizedType fc = (ParameterizedType)field.getGenericType();
TypeVariable[] types = fieldClazz.getTypeParameters();
List list = (List)value;
if(value == null) {
list = new ArrayList<>();
if(field!=null) field.set(entity, list);
}
toList(document.get(key), list, (Class)fc.getActualTypeArguments()[0]);
continue;
}
//哈希表
if(Map.class.isAssignableFrom(fieldClazz)) {
ParameterizedType fc = (ParameterizedType)field.getGenericType();
Map map = (Map) value;
if(value == null) {
map = new HashMap<>();
if(field!=null) field.set(entity, map);
}
toMap(document.get(key), map, (Class)fc.getActualTypeArguments()[0],(Class)fc.getActualTypeArguments()[1]);
continue;
}
document.put(key, toBean((Document)val, fieldClazz));
}
} catch (Exception e) {
logger.error("toBean() error , clazz:"+clazz.getName(), e);
}
return entity;
}
/**
* 转换成适合update语句的Document对象
* @param entity
* @return
*/
public static Document toDocumentForUpdate(Object entity) {
Document document = new Document();
document.put("$set", toDocument(entity));
return document;
}
/**
* 转换成Document
* @param entity
* @return
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
public static Document toDocument(Object entity) {
if(entity == null) {
return null;
}
Document document = new Document();
Class clazz = entity.getClass();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
if(Modifier.isStatic(field.getModifiers())) {
continue;//静态成员不转换
}
field.setAccessible(true);
Class fieldClazz = field.getType();
if(fieldClazz.getAnnotationsByType(Transient.class).length>0) {
//@Transient 标识的属性不进行转换
continue;
}
String key = field.getName();
if("id".equals(key)) {
key = "_id";
}
Object value = null;
try {
value = field.get(entity);
} catch (Exception e) {
e.printStackTrace();
}
if(value == null) {
continue;
}
try {
if(isPrimitive(fieldClazz) || fieldClazz == String.class) {
document.put(key, value);
continue;
}
if(fieldClazz.isArray()) { //数组
String itemClazzName = fieldClazz.getTypeName().substring(0, fieldClazz.getTypeName().length()-2);
Class itemClazz = null;
try {
itemClazz = Class.forName(itemClazzName);
} catch (ClassNotFoundException e) {
//此时为基本类型
itemClazz = toPrimitiveClass(itemClazzName);
}
int len = Array.getLength(value);
if(isPrimitive(itemClazz) || itemClazz == String.class) {
List values = new ArrayList<>();
for(int i=0;i<len;i++) {
Object object = Array.get(value, i);
values.add(object);
}
document.put(key, values);
}else {
List<Document> listDocument = new ArrayList<>();
document.put(key, listDocument);
for(int i=0;i<len;i++) {
Object object = Array.get(value, i);
listDocument.add(toDocument(object));
}
}
continue;
}
//列表
if (List.class.isAssignableFrom(fieldClazz)) {
List list = (List)value;
ParameterizedType fc = (ParameterizedType)field.getGenericType();
Class itemClazz = (Class)fc.getActualTypeArguments()[0];
if(isPrimitive(itemClazz) || itemClazz == String.class) {
List values = new ArrayList<>();
for (Object object : list) {
values.add(object);
}
document.put(key, values);
}else {
List<Document> listDocument = new ArrayList<>();
document.put(key, listDocument);
for (Object object : list) {
listDocument.add(toDocument(object));
}
}
continue;
}
//哈希表
if (Map.class.isAssignableFrom(fieldClazz)) {
Map map = (Map)field.get(entity);
Set<Map.Entry> entries = map.entrySet();
Map mpperMap = new HashMap<>();
document.put(key, mpperMap);
ParameterizedType fc = (ParameterizedType)field.getGenericType();
Class keyClazz = (Class)fc.getActualTypeArguments()[0];
if(keyClazz != String.class && !isPrimitive(keyClazz)) {
throw new RuntimeException("不支持的Map,转换成document的key只能为基本类型或字符串");
}
Class itemClazz = (Class)fc.getActualTypeArguments()[1];
if(itemClazz == String.class || isPrimitive(itemClazz)) {
for (Map.Entry entry : entries) {
mpperMap.put(entry.getKey().toString(), entry.getValue());
}
}else {
for (Map.Entry entry : entries) {
mpperMap.put(entry.getKey().toString(), toDocument(entry.getValue()));
}
}
// Document mapDocument = new Document();
// document.put(key, mapDocument);
//
// for (Map.Entry entry : entries) {
// Object object = entry.getValue();
// if(isPrimitive(object.getClass()) || object.getClass() == String.class) {
// mapDocument.put(entry.getKey().toString(), object);
// }else {
// mapDocument.put(entry.getKey().toString(), toDocument(object));
// }
// }
continue;
}
document.put(key, toDocument(value));
}catch (Exception e) {
logger.error("toDocument() , error clazz="+entity.getClass().getName(),e);
}
}
return document;
}
@SuppressWarnings("rawtypes")
private static boolean isPrimitive(Class clazz) {
if(clazz.isPrimitive()) {
return true;
}
if(Long.class == clazz || Integer.class == clazz || Double.class == clazz || Float.class == clazz || Short.class == clazz || Boolean.class == clazz) {
return true;
}
return false;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private static Object toArray(Object value, Class itemClazz) {
List list = (List)value;
Object array = Array.newInstance(itemClazz, list.size());
int i = 0;
for (Object object : list) {
if(object instanceof Document) {
Array.set(array, i++, toBean((Document)object,itemClazz));
}else {
Array.set(array, i++, object);
}
}
return array;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private static void toMap(Object value , Map map,Class keyClazz,Class itemClazz) throws InstantiationException, IllegalAccessException {
Set<Map.Entry> entries = ((Map)value).entrySet();
for (Map.Entry entry : entries) {
Object keyV = entry.getKey().getClass() == String.class ? entry.getKey() : toPrimitive(entry.getKey().toString(), keyClazz);
Object itemV = entry.getValue();
if(itemV instanceof Document) {
map.put(keyV, toBean((Document)itemV,itemClazz));
}else {
map.put(keyV,itemV);
}
}
// Document document = (Document) value;
// for (Map.Entry entry : document.entrySet()) {
// Object keyV = toPrimitive(entry.getKey().toString(), keyClazz);
// Object itemV = document.get(entry.getKey());
//
// if(itemV instanceof Document) {
// map.put(keyV, toBean((Document)itemV,itemClazz));
// }else {
// map.put(keyV,itemV);
// }
//
// }
}
@SuppressWarnings("rawtypes")
private static Object toPrimitive(String value,Class clazz) {
if(int.class == clazz || Integer.class == clazz) {
return Integer.valueOf(value);
}else if(long.class == clazz || Long.class == clazz) {
return Long.valueOf(value);
}else if(short.class == clazz || Short.class == clazz) {
return Short.valueOf(value);
}else if(double.class == clazz || Double.class == clazz) {
return Double.valueOf(value);
}else if(float.class == clazz || Float.class == clazz) {
return Float.valueOf(value);
}else if(boolean.class == clazz || Boolean.class == clazz) {
return Boolean.valueOf(value);
}else {
throw new RuntimeException("Map key nonsupport !!!");
}
}
@SuppressWarnings("rawtypes")
private static Class toPrimitiveClass(String primitiveClazzName) {
Class itemClazz = null;
//此时为基本类型
if("long".equals(primitiveClazzName)) {
itemClazz = long.class;
}else if("int".equals(primitiveClazzName)) {
itemClazz = int.class;
}else if("short".equals(primitiveClazzName)) {
itemClazz = short.class;
}else if("double".equals(primitiveClazzName)) {
itemClazz = double.class;
}else if("float".equals(primitiveClazzName)) {
itemClazz = float.class;
}else if("boolean".equals(primitiveClazzName)) {
itemClazz = boolean.class;
}else {
throw new RuntimeException("nonsupport type !!!");
}
return itemClazz;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private static void toList(Object value , List list,Class itemClazz) throws InstantiationException, IllegalAccessException {
if(value.getClass() == Document[].class) {
Document[] documents = (Document[])value;
for (Document document : documents) {
list.add(toBean(document, itemClazz));
}
}else {
List vals = (List)value;
for (Object object : vals) {
list.add(object);
}
}
}
}
测试类
public class A{
private int int1;
private Long long1;
private String str1;
private boolean bool1;
private short short1;
private double double1;
private float float1;
private B[] bs;
private long[] longArr;
private Double[] doubleArr;
private List<B> bList = new ArrayList<>();
private Map<Integer, B> bMap = new HashMap<>();
private List<Integer> ints = new ArrayList<>();
private Map<Integer, Integer> intMap = new HashMap<>();
private List<String> strings = new ArrayList<>();
private List<Long> longs = new ArrayList<>();
private Date date = new Date();
public int getInt1() {
return int1;
}
public void setInt1(int int1) {
this.int1 = int1;
}
public Long getLong1() {
return long1;
}
public void setLong1(Long long1) {
this.long1 = long1;
}
public String getStr1() {
return str1;
}
public void setStr1(String str1) {
this.str1 = str1;
}
public boolean isBool1() {
return bool1;
}
public void setBool1(boolean bool1) {
this.bool1 = bool1;
}
public short getShort1() {
return short1;
}
public void setShort1(short short1) {
this.short1 = short1;
}
public double getDouble1() {
return double1;
}
public void setDouble1(double double1) {
this.double1 = double1;
}
public float getFloat1() {
return float1;
}
public void setFloat1(float float1) {
this.float1 = float1;
}
public B[] getBs() {
return bs;
}
public void setBs(B[] bs) {
this.bs = bs;
}
public List<B> getbList() {
return bList;
}
public void setbList(List<B> bList) {
this.bList = bList;
}
public Map<Integer, B> getbMap() {
return bMap;
}
public void setbMap(Map<Integer, B> bMap) {
this.bMap = bMap;
}
public List<Integer> getInts() {
return ints;
}
public void setInts(List<Integer> ints) {
this.ints = ints;
}
public Map<Integer, Integer> getIntMap() {
return intMap;
}
public void setIntMap(Map<Integer, Integer> intMap) {
this.intMap = intMap;
}
public List<String> getStrings() {
return strings;
}
public void setStrings(List<String> strings) {
this.strings = strings;
}
public List<Long> getLongs() {
return longs;
}
public void setLongs(List<Long> longs) {
this.longs = longs;
}
public long[] getLongArr() {
return longArr;
}
public void setLongArr(long[] longArr) {
this.longArr = longArr;
}
public Double[] getDoubleArr() {
return doubleArr;
}
public void setDoubleArr(Double[] doubleArr) {
this.doubleArr = doubleArr;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
@Override
public String toString() {
return "A [int1=" + int1 + ", long1=" + long1 + ", str1=" + str1 + ", bool1=" + bool1 + ", short1=" + short1
+ ", double1=" + double1 + ", float1=" + float1 + ", bs=" + Arrays.toString(bs) + ", longArr="
+ Arrays.toString(longArr) + ", doubleArr=" + Arrays.toString(doubleArr) + ", bList=" + bList
+ ", bMap=" + bMap + ", ints=" + ints + ", intMap=" + intMap + ", strings=" + strings + ", longs="
+ longs + ", date=" + date + "]";
}
}
public class B {
Integer intB;
Long longB;
String strB;
public Integer getIntB() {
return intB;
}
public void setIntB(Integer intB) {
this.intB = intB;
}
public Long getLongB() {
return longB;
}
public void setLongB(Long longB) {
this.longB = longB;
}
public String getStrB() {
return strB;
}
public void setStrB(String strB) {
this.strB = strB;
}
@Override
public String toString() {
return "B [intB=" + intB + ", longB=" + longB + ", strB=" + strB + "]";
}
}
测试用例
public class BsonUseCase {
@Test
public void testMongodbInsert() {
MongoClient mongoClient = new MongoClient("localhost");
MongoDatabase database = mongoClient.getDatabase("test");
MongoCollection<Document> collection = database.getCollection("test_a");
Document document = BsonUtil.toDocument(getA());
System.out.println(document);
collection.insertOne(document);
}
@Test
public void testMongodbQuery() {
String id = "5cb21a21e2713f598f57ccb2"; //根据插入的主键修改
MongoClient mongoClient = new MongoClient("localhost");
MongoDatabase database = mongoClient.getDatabase("test");
MongoCollection<Document> collection = database.getCollection("test_a");
FindIterable<Document> findIterable = collection.find(Filters.eq("_id", new ObjectId(id)));
Document document = findIterable.first();
System.out.println(document);
System.out.println("对比");
System.out.println(BsonUtil.toDocument(getA()));
}
@Test
public void testToBean() {
A a = getA();
Document document = BsonUtil.toDocument(a);
System.out.println(document);
System.out.println("before:");
System.out.println(a);
System.out.println("After:");
A aa = BsonUtil.toBean(document, A.class);
System.out.println(aa);
}
@Test
public void testToDocument() {
Document document = BsonUtil.toDocument(getA());
System.out.println(document);
}
private A getA() {
A a = new A();
a.setInt1(11);
a.setBool1(true);
a.setDouble1(12323.4434D);
a.setFloat1(323.23f);
a.setLong1(12443344444L);
a.setShort1((short)323);
a.setStr1("Hello,BSON");
B b = new B();
b.setIntB(2001);
b.setLongB(2000000001L);
b.setStrB("2BBBBBBBBBBBBBBBBBBBBBB1");
B b2 = new B();
b2.setIntB(2003);
b2.setLongB(2000000003L);
b2.setStrB("2BBBBBBBBBBBBBBBBBBBBBB2");
a.setBs(new B[] {b,b2});
long[] longArr = new long[] {1332L,3444L,5677L};
a.setLongArr(longArr);
Double[] doubleArr = new Double[] {33.32D,4345.3D};
a.setDoubleArr(doubleArr);
List<B> bList = new ArrayList<>();
bList.add(b);
bList.add(b2);
a.setbList(bList);
a.getbMap().put(b.getIntB(), b);
a.getbMap().put(b2.getIntB(), b2);
a.getInts().add(11);
a.getInts().add(22);
a.getInts().add(33);
a.getIntMap().put(111, 111);
a.getIntMap().put(222, 222);
a.getIntMap().put(333, 333);
a.getIntMap().put(444, 444);
a.getStrings().add("eweew");
a.getStrings().add("eeeeee");
a.getLongs().add(2334444L);
a.getLongs().add(2334445L);
a.getLongs().add(2334446L);
a.getLongs().add(2334447L);
return a;
}
}
测试结果
对比测试用例输出结果,一切正常 !!