`

MongoDb应用

阅读更多

//mongoDB ,创建一个自动增长的ID
public abstract class AbstractIdEntity{
	@Id Long _id;
	
	@Transient protected Datastore ds;
	
	public AbstractIdEntity(){
		
	}
	
	public void setDs(Datastore ds) {
		this.ds = ds;
	}
	
	@PrePersist void prePersist(){
		if (_id == null) {
			String collName = ds.getCollection(getClass()).getName();
		    Query<StoredSeqence> q = ds.find(StoredSeqence.class, "_id", collName);
		    UpdateOperations<StoredSeqence> uOps = ds.createUpdateOperations(StoredSeqence.class).inc("value");
		    StoredSeqence newId = ds.findAndModify(q, uOps);
		    if (newId == null) {
		       newId = new StoredSeqence(collName);
		       ds.save(newId);
		    }
		    
		    _id = newId.value;
		}
	}

	public Long geId() {
		return _id;
	}
	

}

@Entity(value="book_score_mongo", noClassnameStored=true)
public class BookScoreMongo extends AbstractIdEntity {
	/**书的ID*/
	private Long bookId;
	/**书的类型(1为原创,2为藏书)*/
	private Integer bookType;
	/**用户的userId*/
	private Integer userId;
	/**评分的分数*/
	private Long score;
	
	
	public Long getBookId() {
		return bookId;
	}
	public void setBookId(Long bookId) {
		this.bookId = bookId;
	}
	public Integer getBookType() {
		return bookType;
	}
	public void setBookType(Integer bookType) {
		this.bookType = bookType;
	}
	public Integer getUserId() {
		return userId;
	}
	public void setUserId(Integer userId) {
		this.userId = userId;
	}
	public Long getScore() {
		return score;
	}
	public void setScore(Long score) {
		this.score = score;
	}
	
	
}

public interface IDAO {
	/**
	 * 查询mongo数据库集合中的所有记录数
	 * 
	 * @param clazz 通过cls配置的MongoCollect注解找到集合名
	 * @return 返回集合的所有记录数
	 */
	public <T> long count(Class<T> clazz);
	
	
	public <T> long count(Class<T> clazz, Map<String, Object> conditions);
	
	/**
	 * 保存对象,返回主键值
	 * 
	 * @param entity 需要保存的对象
	 * @return 主键值
	 */
	<T> Object saveRtnKey(T entity);
	
	
	<T> void delete(Class<T> clazz, Map<String, Object> conditions);
	
	/**
	 * 根据主键值,将指定的字段更新为相应的值
	 * 
	 * @param clazz 
	 * @param id 主键id
	 * @param updateFieldsMap updateFieldsMap中的key为字段名,value为字段值
	 * @return 返回更新的行数
	 */
	<T, V> int update(Class<T> clazz, V id, Map<String, Object> updateFieldsMap);
	
	
	/**
	 * 根据主键值,查询数据库,查询结果转换为指定类的实例对象,没有结果,返回null。
	 * 
	 * @param clazz 查询结果转换为该类
	 * @param id 主键值,作为查询条件
	 * @return 返回指定类cls的实例对象
	 */
	<T,V> T queryForObjectById(Class<T> clazz, V id);
	
	/**
	 * 查询所有记录,查询结果转换为指定类的实例对象列表,没有结果,返回空的List对象。
	 * 
	 * @param cls 查询结果转换为该类
	 * @return    返回指定类的实例对象列表
	 */
	<T> List<T> queryForList(Class<T> clazz);
	
	/**
	 * 查询所有记录,并根据字段进行排序,查询结果转换为指定类的实例对象列表,没有结果,返回空的List对象。
	 * 排序字段示例:
	 * ("age") 
	 * ("-age") age字段降序排序
	 * ("age,date") 
	 * ("age,-date") age字段升序,date字段降序排序
	 * 
	 * @param cls 查询结果转换为该类
	 * @param orderFields 排序字段列表 
	 * @return  返回指定类的实例对象列表
	 */
	<T> List<T> queryForListWithOrder(Class<T> clazz, String orderFields);

	/**
	 * 查询所有符合条件的记录,查询结果转换为指定类的实例对象列表,没有结果,返回空的List对象。
	 * 属性名必须是"属性名 操作符"("age >")
	 * 属性中,可以使用的有效操作符 ["=", "==","!=", "<>", ">", "<", ">=", "<=", "in", "nin", "all", "size", "exists"] 
	 * 例如:
	 * 
	 * ("yearsOfOperation >", 5)  
	 * ("rooms.maxBeds >=", 2)
	 * ("rooms.bathrooms exists", 1)
	 * ("stars in", new Long[]{3,4}) //3 and 4 stars (midrange?)}
	 * ("age >=", age)
	 * ("age =", age)
	 * ("age", age)如果不写操作符,默认为=号
	 * ("age !=", age)
	 * ("age in", ageList)
	 * ("customers.loyaltyYears in", yearsList)
	 * 
	 * @param clazz 查询结果转换为该类
	 * @param property
	 * @param value
	 * @return 返回指定类的实例对象列表
	 */
	<T, V> List<T> queryForListByConExpr(Class<T> clazz, String property, V value);
	
	/**
	 * 查询所有符合条件的记录,查询结果转换为指定类的实例对象列表,没有结果,返回空的List对象,
	 * 多个查询条件之间的关系是与关系
	 * 
	 * @param cls 查询结果转换为该类
	 * @param conditions key为property,可参考queryForListByConExpr方法说明
	 * @return 返回指定类的实例对象列表
	 */
	<T> List<T> queryForListByConExprMap(Class<T> cls, Map<String, Object> conditions);
	
	<T> List<T> queryForListByConExprMapWithOrder(Class<T> cls, Map<String, Object> conditions, String orderFields);
	
	<T> List<T> queryForListByConExprMapWithOrderLimit(Class<T> clazz, Map<String, Object> conditions, String orderFields, int rtnNum);
	
	<T> List<T> queryForListByConExprMapWithOrderSkipLimit(Class<T> cls, Map<String, Object> conditions,String orderFields, int skipNum, int rtnNum);
}




public class MongoServiceDAO implements IDAO{
	public static final String MONGO_ID_KEY="_id";
	private Datastore ds;
	private static MongoServiceDAO instance = new MongoServiceDAO();
	
	static{
		init();
	}	
	
	private MongoServiceDAO(){}
	
	public static MongoServiceDAO getInstance(){
		return instance;
	}
	
	private static void init(){
		InputStream in=null;
		try {
			in = MongoServiceDAO.class.getClassLoader().getResourceAsStream("mongodb.properties");
			Properties prop = new Properties(); 
			prop.load(in);
			
			String host = prop.getProperty("host").trim();
			int port = Integer.valueOf(prop.getProperty("port").trim());
			String dbName = prop.getProperty("dbName").trim();
			String userName = prop.getProperty("userName").trim();
			String password = prop.getProperty("password").trim();
			
			Morphia morphia = new Morphia();
			Mongo mongo = new Mongo(host, port);
			instance.ds = morphia.createDatastore(mongo,dbName);
			if (isMongoSecure(userName, password)){
				boolean bauth = instance.ds.getDB().authenticate(userName, password.toCharArray());
				if (!bauth) {
					throw new Exception("auth fail.");
				}	
			}
		} catch(Exception e){
			SysLogger.error(e.getMessage());
			throw new RuntimeException(e.getMessage());
		}finally{
			if (in!=null){
				try {
					in.close();
				} catch (IOException e) {
					SysLogger.error(e.getMessage());
				}	
			}
		}
	}
	
    private static boolean isMongoSecure(String mongoUsername, String mongoPassword) {
        if (mongoUsername == null
            || "".equals(mongoUsername)
            || mongoPassword == null
            || "".equals(mongoPassword))
            return false;
        return true;
    }		
    
    @Override
    public <T> long count(Class<T> clazz){
    	return this.ds.getCount(clazz);
    }
    
    @Override
    public <T> long count(Class<T> clazz, Map<String, Object> conditions){
    	if (conditions==null) return this.count(clazz);
    	
		Set<Entry<String, Object>> set = conditions.entrySet();
		Query<T> q = this.ds.createQuery(clazz);
		//加入过滤条件
		for(Entry<String,Object> entry : set){
			q.filter(entry.getKey(), entry.getValue());
		}
		return this.ds.getCount(q);
    }
    
	@Override
	public <T> Object saveRtnKey(T entity) {
		if (AbstractIdEntity.class.isAssignableFrom(entity.getClass())){
			((AbstractIdEntity)entity).setDs(this.ds);
		}
		Key<T> key = this.ds.save(entity);
		return key.getId();
	}
	
	@Override
	public <T> void delete(Class<T> clazz, Map<String, Object> conditions){
		
		Query<T> q = this.ds.createQuery(clazz);
		if (conditions != null){
			Set<Entry<String, Object>> set = conditions.entrySet();
			//加入过滤条件
			for(Entry<String,Object> entry : set){
				q.filter(entry.getKey(), entry.getValue());
			}
		}
		this.ds.delete(q);
	}
	
	@Override
	public <T, V> int update(Class<T> clazz, V id, Map<String, Object> updateFieldsMap){
		Query<T> q = this.ds.find(clazz, "_id =", id);
		UpdateOperations<T> ops = this.ds.createUpdateOperations(clazz);
		for (Map.Entry<String, Object> entry : updateFieldsMap.entrySet()){
			ops.set(entry.getKey(), entry.getValue());	
		}
		UpdateResults<T> updateResult = this.ds.update(q, ops);
		return updateResult.getUpdatedCount();
	}
	
	

	@Override
	public <T, V> T queryForObjectById(Class<T> clazz, V id) {
		return this.ds.get(clazz, id);
	}

	@Override
	public <T> List<T> queryForList(Class<T> clazz) {
		List<T> rtnList = new ArrayList<T>();
		Query<T> q = this.ds.find(clazz);
		Iterator<T> itor = q.fetch().iterator();
		while (itor.hasNext()){
			rtnList.add(itor.next());
		}
		
		return rtnList;
	}

	@Override
	public <T> List<T> queryForListWithOrder(Class<T> clazz, String orderFields) {
		List<T> rtnList = new ArrayList<T>();
		Query<T> q = this.ds.find(clazz);

		
		//排序
		q.order(orderFields);

		//返回结果
		Iterator<T> itor = q.fetch().iterator();
		while (itor.hasNext()){
			rtnList.add(itor.next());
		}
		
		return rtnList;
	}

	@Override
	public <T, V> List<T> queryForListByConExpr(Class<T> clazz, String property, V value) {
		List<T> rtnList = new ArrayList<T>();
		Query<T> q = this.ds.find(clazz, property, value);
		
		Iterator<T> itor = q.fetch().iterator();
		while (itor.hasNext()){
			rtnList.add(itor.next());
		}
		
		return rtnList;
	}

	@Override
	public <T> List<T> queryForListByConExprMap(Class<T> clazz, Map<String, Object> conditions) {
		List<T> rtnList = new ArrayList<T>();
		
		Set<Entry<String, Object>> set = conditions.entrySet();
		Query<T> q = this.ds.createQuery(clazz);
		//过滤
		for(Entry<String,Object> entry : set){
			q.filter(entry.getKey(), entry.getValue());
		}
		//返回结果
		Iterator<T> itor = q.fetch().iterator();
		while (itor.hasNext()){
			rtnList.add(itor.next());
		}
		
		return rtnList;
	}

	@Override
	public <T> List<T> queryForListByConExprMapWithOrder(Class<T> clazz, Map<String, Object> conditions,
			String orderFields) {
		List<T> rtnList = new ArrayList<T>();
		
		Set<Entry<String, Object>> set = conditions.entrySet();
		Query<T> q = this.ds.createQuery(clazz);
		//过滤
		for(Entry<String,Object> entry : set){
			q.filter(entry.getKey(), entry.getValue());
		}
		//排序
		q.order(orderFields);
		//返回结果
		Iterator<T> itor = q.fetch().iterator();
		while (itor.hasNext()){
			rtnList.add(itor.next());
		}
		
		return rtnList;
	}

	@Override
	public <T> List<T> queryForListByConExprMapWithOrderLimit(Class<T> clazz, Map<String, Object> conditions, String orderFields, int rtnNum) {
		List<T> rtnList = new ArrayList<T>();
		
		Set<Entry<String, Object>> set = conditions.entrySet();
		Query<T> q = this.ds.createQuery(clazz);
		//过滤
		for(Entry<String,Object> entry : set){
			q.filter(entry.getKey(), entry.getValue());
		}
		//排序
		q.order(orderFields);
		
		//取查询结果顶部rtnNum条记录
		q.limit(rtnNum);
		//返回结果
		Iterator<T> itor = q.fetch().iterator();
		while (itor.hasNext()){
			rtnList.add(itor.next());
		}
		
		return rtnList;
	}

	@Override
	public <T> List<T> queryForListByConExprMapWithOrderSkipLimit(Class<T> clazz, Map<String, Object> conditions,String orderFields, int skipNum, int rtnNum) {
		List<T> rtnList = new ArrayList<T>();
		
		Set<Entry<String, Object>> set = conditions.entrySet();
		Query<T> q = this.ds.createQuery(clazz);
		//过滤
		for(Entry<String,Object> entry : set){
			q.filter(entry.getKey(), entry.getValue());
		}
		//排序
		q.order(orderFields);
		
		//查询结果指针偏移数
		q.offset(skipNum);
		//取查询结果指针位置后的rtnNum记录
		q.limit(rtnNum);
		//返回结果
		Iterator<T> itor = q.fetch().iterator();
		while (itor.hasNext()){
			rtnList.add(itor.next());
		}
		
		return rtnList;
	}
	
	/**
	 * 对传入的key通过分割符/进行层次分解,
	 * 例如key为a/b/c/d,分解之后的层次为a, a/b, a/b/c, a/b/c/d四层,
	 * 对每层中的给定的所有字段值加1
	 * 例如:addFieldsValueFromLeafkey2Rootkey("a/b/c","field1","field2")
	 * 将执行:
	 * _id     field1            field2
	 * ------------------------------------------
	 * a/b/c   field1.value+1    field2.value+1
	 * a/b     field1.value+1    field2.value+1
	 * a       field1.value+1    field2.value+1
	 * 
	 * @param leafkey 叶层次的key值
	 * @param fieldNames 需要字段值加1的字段
	 */
	public void incFieldsValueFromLeafkey2Rootkey(Class clazz,String leafkey, String...fieldNames){
		this.addFieldsValueFromLeafkey2Rootkey(clazz, leafkey, 1, fieldNames);
	}
	
	public void addFieldsValueFromLeafkey2Rootkey(Class clazz, String leafkey, int value, String...fieldNames){
		DBCollection coll = this.ds.getCollection(clazz);
		for (String fieldName:fieldNames){
			recurseAddVisitCount(coll, leafkey, value, fieldName);	
		}
	}
	
	public void incFieldsValue(Class clazz, Object primaryKeyValue, String...fieldNames){
		this.addFieldsValue(clazz, primaryKeyValue, 1, fieldNames);
	}
	
	public void addFieldsValue(Class clazz, Object primaryKeyValue, int value, String...fieldNames){
		DBCollection coll = this.ds.getCollection(clazz);
		for (String fieldName:fieldNames){
			addFieldValue(coll, primaryKeyValue, value, fieldName);	
		}
	}
	
	private void addFieldValue(DBCollection coll, Object primaryKeyValue, int value, String fieldName){
		if (primaryKeyValue==null) return;
		BasicDBObject conditionDBObject = new BasicDBObject();
		conditionDBObject.put(MONGO_ID_KEY, primaryKeyValue);
		
		BasicDBObject valDBObject = new BasicDBObject();
		valDBObject.put(fieldName, value);
		
		BasicDBObject updateDBObject = new BasicDBObject();
		updateDBObject.put("$inc", valDBObject);
		
		coll.update(conditionDBObject, updateDBObject, true, false);
	}
	
	private static final String KEY_SEPERATOR = "/";
	 //db.c.update({_id:10},{$inc:{count:value}})
	private void recurseAddVisitCount(DBCollection coll, String key, int value, String fieldName){
		if (key==null || key.trim().equals("")) return;
		if(key.startsWith(KEY_SEPERATOR) || key.endsWith(KEY_SEPERATOR))
			throw new RuntimeException("key can't start or end with "+KEY_SEPERATOR+",because it is key seperator.");
		
		BasicDBObject conditionDBObject = new BasicDBObject();
		conditionDBObject.put(MONGO_ID_KEY, key);
		
		BasicDBObject valDBObject = new BasicDBObject();
		valDBObject.put(fieldName, value);
		
		BasicDBObject updateDBObject = new BasicDBObject();
		updateDBObject.put("$inc", valDBObject);
		
		coll.update(conditionDBObject, updateDBObject, true, false);
		
		int pos = key.lastIndexOf(KEY_SEPERATOR);
		if (pos>0){
			String newKey = key.substring(0,pos);	
			recurseAddVisitCount(coll, newKey, value, fieldName);
		}
	}		
}
//业务层具体实现增,删,改,查,



/**
 * 评分
 */

@Service
public class BookScoreMongoManager{
	
	@Autowired
	private OriginalBookManager originalBookManager;
	
	@Autowired
	private PaperBookManager paperBookManager;

	/**
	 * 插入评分mongo表
	 * @param bookScoreMongo
	 * @return
	 */
	public Long insertBookScoreMongo(BookScoreMongo bookScoreMongo){
		return (Long)MongoServiceDAO.getInstance().saveRtnKey(bookScoreMongo);
	}
	
	/**
	 * 通过ID获取评分mongo数据
	 * @param id
	 * @return
	 */
	public BookScoreMongo getBookScoreMongoById(Long id){
		return MongoServiceDAO.getInstance().queryForObjectById(BookScoreMongo.class, id);
	}

	/**
	 * 修改个人对书的评分分数
	 * @param bookScoreMongo
	 * @param score
	 */
	private void updateBookScoreMongoById(BookScoreMongo bookScoreMongo ,Long score){
		if(score!=null && score>0 ){
			Map<String, Object> updateFieldsMap = new HashMap<String, Object>();
			updateFieldsMap.put("score", score);
			MongoServiceDAO.getInstance().update(BookScoreMongo.class,bookScoreMongo.geId(),updateFieldsMap);
		}
	}

	
	/**
	 * 通过书籍ID,书籍类型和用户ID取评分mongo
	 * @param bookid
	 * @param userid
	 * @param booktype 
	 * @return
	 */
    public BookScoreMongo getScoreById(Long bookId,Integer userid,Integer booktype){
     	Map<String,Object>  maps = new HashMap<String,Object>();
        maps.put("bookId",bookId);
        maps.put("userId",userid);
        maps.put("bookType",booktype);
        List<BookScoreMongo> list = MongoServiceDAO.getInstance().queryForListByConExprMapWithOrderLimit(BookScoreMongo.class,maps,"",1);
        if(list != null && list.size() > 0){
        	return list.get(0);
        }else{
        	return null;
        }
    }
	public BookScoreMongo getScoreByBookidUserId(Long bookid,Integer userid,Integer booktype){
		Map<String, Object> conditions = new HashMap<String, Object>();
		conditions.put("bookId", bookid);
		conditions.put("userId", userid);
		conditions.put("bookType", booktype);
		
		List<BookScoreMongo> list = MongoServiceDAO.getInstance().queryForListByConExprMapWithOrderLimit(BookScoreMongo.class,conditions,"",1);
		if(list != null && list.size() >0){
			return list.get(0);
		}else{
			return null;
		}
	}
	
   public void updateByBookUserId(Long bookId,Integer userid,Long score,Integer booktype){
	   if(score != null && score > 0){
		   
	   }
   }
	/**
	 * 插入或者修改个人评分分数
	 * @param bookid
	 * @param userid
	 * @param score
	 * @param booktype(1为原创,2为藏书)
	 */
	public void updateByBookidUserId(Long bookid,Integer userid,Long score,Integer booktype){
		
		if(score != null && score >0){
			BookScoreMongo bookScoreMongo = getScoreByBookidUserId(bookid,userid,booktype);
			if(bookScoreMongo != null){
				if(score != bookScoreMongo.getScore()){
					updateBookScoreMongoById(bookScoreMongo,score);
					//修改总分数
					if(booktype.equals(1)){
						originalBookManager.changScore(bookid,score,bookScoreMongo.getScore());
					}else if(booktype.equals(2)){
						paperBookManager.changScore(bookid,score,bookScoreMongo.getScore());
					}
				}
			}else{
				bookScoreMongo = new BookScoreMongo();
				bookScoreMongo.setBookId(bookid);
				bookScoreMongo.setUserId(userid);
				bookScoreMongo.setScore(score);
				bookScoreMongo.setBookType(booktype);
				insertBookScoreMongo(bookScoreMongo);
				//修改总分数和评分总人数
				if(booktype.equals(1)){
					originalBookManager.addScoreSun(bookid,score);
				}else if(booktype.equals(2)){
					paperBookManager.addScoreSun(bookid,score);
				}
			}
		}
		
	}
}


@SuppressWarnings("serial")
public class BookScoreAction extends ActionSupport{
	/**书籍ID*/
	private int bookId;
	/**分数*/
	private int score;
	/**类型 (如1是原创,2是藏书)*/
	private int type;
	
	private int userId;
	
	/**
	 * ids
	 */
	private String ids;
	
	@Autowired
	private BookScoreMongoManager bookScoreMongoManager;
	
	@Autowired
	private PaperBookManager paperBookManager;
	
	@Autowired
	private OriginalBookManager originalBookManager;
	public String getIds() {
		return ids;
	}
	public int getUserId() {
		return userId;
	}



	public void setUserId(int userId) {
		this.userId = userId;
	}


	public void setIds(String ids) {
		this.ids = ids;
	}
	protected final ObjectMapper mapper = new ObjectMapper();
	
	/**
	 * 对书进行评分Action
	 */
	public void insertScore() throws Exception{
		if(userId != 0){
			BookUserUtil.scored(userId,bookId,type,score);
		}else{
			BookUserUtil.scored(RequestContext.getCurrUser().getId().intValue(),bookId,type,score);
		}
		Map<String, Object> scoreMap = new HashMap<String, Object>();
		bookScoreMongoManager.updateByBookidUserId((long) bookId,
				RequestContext.getCurrUser().getId().intValue(), (long) score,
				type);
		BookScoreMongo bookScoreMongo = bookScoreMongoManager.getScoreByBookidUserId((long)bookId, RequestContext.getCurrUser().getId().intValue(), type);
		scoreMap.put("bookScoreMongo", bookScoreMongo);
		// 藏书
		if (type == 2) {
			PaperBookMongo paperBookMongo = paperBookManager
					.getMongoBookById((long) bookId);
			scoreMap.put("paperBookMongo", paperBookMongo);
		} else if (type == 1) {
			OriginalBookMongo originalBookMongo = originalBookManager
					.getMongoBookById((long) bookId);
			scoreMap.put("originalBookMongo", originalBookMongo);
		}
		String result =mapper.writeValueAsString(scoreMap);
		Struts2Utils.renderJson(result);

	}


	
	/**
	 * 根据登入userId获取用户对 原创/藏书的评分
	 */
	public void getScoreByUser(){
		Struts2Utils.renderJson(bookScoreMongoManager.getScoreByBookidUserId((long)bookId,RequestContext.getCurrUser().getId().intValue(),type));
	}
	/**
	 * 根据传入userId获取用户对 原创/藏书的评分
	 */
	public void getScoreByOtherUser(){
		Struts2Utils.renderJson(bookScoreMongoManager.getScoreByBookidUserId((long)bookId,userId,type));
	}
	
	/**
	 * 批量获取评分统计
	 */
//	public void getStatisticList(){
//	
//		List<Integer> params=null;
//		
//		if (ids != null && !"".equals(ids)) {
//			params = new ArrayList<Integer>();
//			String[] idArr = ids.split(",");
//			for (int i = 0; i < idArr.length; i++) {
//				params.add(Integer.parseInt(idArr[i]));
//			}
//		}
//		//evaluationManager.get
//		Struts2Utils.renderJson(scoreManager.getScoreStatisticals(params, type));
//	}
	
	public int getBookId() {
		return bookId;
	}
	public void setBookId(int bookId) {
		this.bookId = bookId;
	}
	public int getType() {
		return type;
	}
	public void setType(int type) {
		this.type = type;
	}
	public int getScore() {
		return score;
	}
	public void setScore(int score) {
		this.score = score;
	}
}

分享到:
评论
3 楼 xiaoxin5230 2011-01-10  
请问你们mongodb有用到replset和master-slave模式吗?另外你们这个morphia的通用类可以参考morphia自带的dao
2 楼 yangjuanjava 2011-01-06  
xiaoxin5230 写道
请问博主,这个mongodb你们有用到项目中吗?

当然有用到的!
1 楼 xiaoxin5230 2011-01-04  
请问博主,这个mongodb你们有用到项目中吗?

相关推荐

Global site tag (gtag.js) - Google Analytics