mongodb官方的java driver不支持直接插入java bean,只能使用DbObject的Key,Value形式进行insert,update,(c# mongodb官方driver类似),所以我这里加入了一个利用反射快速操作的类,来支持bean操作。另因为java不支持扩展方法,所以只能用abstract class的类来替代,c#的话可以直接扩展官方driver,会更方便。
关于速度,反射(reflection)一般情况下要比直接(native)的方法要慢。先使用的是反射method赋值,平均要比native慢10%左右,所以第二次改用java 的field.set (如果是private,需先设置 field.setAccessible 为true)来进行操作,速度跟native不相上下,在模拟10万,100万数据操作的时候,有时候甚至比native还快。不过这样就舍去了一个功能是可能会在set方法中加入操作,如果需要改为的method的话(hibernate默认做法),只需要修改为method反射即可。
代码很简单,写出来小记一下。
package gsralex; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.net.UnknownHostException; import org.bson.types.ObjectId; import com.mongodb.BasicDBObject; import com.mongodb.DB; import com.mongodb.DBObject; import com.mongodb.Mongo; public abstract class Dao { private static final ThreadLocal<Mongo> threadLocal = new ThreadLocal<Mongo>(); private static final String connectAddress = "127.0.0.1"; private static final int connectPort = 27017; public static Mongo getMongo() { Mongo mongo = threadLocal.get(); if ( mongo == null ) { try { mongo = new Mongo( connectAddress, connectPort ); } catch ( UnknownHostException e ) { /* TODO Auto-generated catch block */ e.printStackTrace(); } threadLocal.set( mongo ); } return(mongo); } public static void close() { Mongo mongo = threadLocal.get(); if ( mongo != null ) { mongo.close(); threadLocal.set( null ); } } public static DB getDefaultDb() { return(getDb( "gsralex" ) ); } public static DB getDb( String dbName ) { Mongo mongo = getMongo(); if ( mongo != null ) { return(mongo.getDB( dbName ) ); } return(null); } public static int insert( Object bean ) { Class clazz = bean.getClass(); Field[] fields = clazz.getDeclaredFields(); MongoColumn column; DBObject dbObject = new BasicDBObject(); try { for ( Field field : fields ) { column = field.getAnnotation( MongoColumn.class ); if ( column == null ) { continue; } Object filedValue = field.get( bean ); dbObject.put( column.name(), filedValue ); } } catch ( Exception e ) { /* TODO Auto-generated catch block */ e.printStackTrace(); } MongoCollection collection = (MongoCollection) clazz .getAnnotation( MongoCollection.class ); return(getDefaultDb().getCollection( collection.name() ).insert( dbObject ) .getN() > 0 ? 0 : -1); } public static int update( Object obj, String collectionName ) { Class clazz = obj.getClass(); Field[] fields = clazz.getDeclaredFields(); MongoColumn column; DBObject dbObject = new BasicDBObject(); try { for ( Field field : fields ) { column = field.getAnnotation( MongoColumn.class ); if ( column == null ) { continue; } Object filedValue = field.get( obj ); dbObject.put( column.name(), filedValue ); } } catch ( Exception e ) { /* TODO Auto-generated catch block */ e.printStackTrace(); } ObjectId _id = getObjectId( obj, clazz ); return(getDefaultDb().getCollection( collectionName ).update( new BasicDBObject( "_id", _id ), dbObject ).getN() > 0 ? 0 : -1); } private static ObjectId getObjectId( Object obj, Class clazz ) { ObjectId _id = null; try { _id = (ObjectId) clazz.getField( "_id" ).get( obj ); } catch ( Exception e ) { /* TODO Auto-generated catch block */ e.printStackTrace(); } return(_id); } public static Object getBean( DBObject dbObject, Class clazz ) { if ( dbObject == null ) { return(null); } Object obj = null; try { obj = clazz.newInstance(); Field[] fields = clazz.getDeclaredFields(); MongoColumn column; for ( Field field : fields ) { column = field.getAnnotation( MongoColumn.class ); if ( column == null ) continue; field.setAccessible( true ); Object filedValue = dbObject.get( column.name() ); field.set( obj, filedValue ); } } catch ( Exception e ) { e.printStackTrace(); } return(obj); } }
需要增加两个注解:
package gsralex; import java.lang.annotation.ElementType; import java.lang.annotation.Target; @Target( { ElementType.TYPE } ) public @interface MongoCollection { public String name() default ""; } package gsralex; import java.lang.annotation.ElementType; import java.lang.annotation.Target; @Target( { ElementType.FIELD, ElementType.METHOD } ) public @interface MongoColumn { public String name() default ""; }
郑州 6月23日 晴