背景:与AJAX跨域问题的产生一样,系统里新增的即时聊天模块,关于聊天内容,是要保存历史记录的。因为即时聊天的特性,数据的保存和获取,需要即时的显示,采用传统关系型数据库,在用户过多的情况下可能就有性能问题了。所以转而考虑非关系型数据库。
在了解了NoSql的类型和特点后。研究的重点放在了MongoDB和Redis这两种数据库上。在易用性上,MongoDB会好一些。MongoDB提供了比较好的查询功能。比较适合聊天模块的应用。所以最终采用的方式是MongoDB。
对应传统关系型数据库。DB-->TABLE-->COLOUM。MongoDB中的层级结构是DB-->COLLECTION-->JSON数据(其实就是KEY--VALUE)
JAVA应用MongoDB:管理类
import java.net.UnknownHostException;
import com.mongodb.DB;
import com.mongodb.Mongo;
import com.mongodb.MongoException;
import com.mongodb.MongoOptions;
import com.troila.core.utils.PropertiesUtils;
public class MongoManager {
private final static String HOST = "xx.xx.xx.xx";// IP
private final static int PORT = 27017;// 端口
private final static int POOLSIZE = 1000;// 连接数量
private final static int BLOCKSIZE = 1000; // 等待队列长度
private static Mongo mongo = null;
private MongoManager() { }
static {
initDBPrompties();
}
public static DB getDB(String dbName) {
return mongo.getDB(dbName);
}
/**
* 初始化连接池
*/
private static void initDBPrompties() {
// 其他参数根据实际情况进行添加
try {
mongo = new Mongo(HOST, PORT);
MongoOptions opt = mongo.getMongoOptions();
opt.connectionsPerHost = POOLSIZE;
opt.threadsAllowedToBlockForConnectionMultiplier = BLOCKSIZE;
opt.maxWaitTime = 5000;
opt.autoConnectRetry = true;
opt.socketKeepAlive=true;
opt.socketTimeout = 2000;
opt.connectTimeout = 15000;
} catch (UnknownHostException e) {
} catch (MongoException e) {
}
}
}
插入举例
public void insertOneChat(String from_uid, String to_uid, String text,
String sendTime) {
DB db = MongoManager.getDB(DB_NAME);
DBCollection chatTable = db.getCollection(CHAT_TABLE);
db.requestStart();
// 事务开始
try {
// 写信息
DBObject newChat = new BasicDBObject();
HashMap mp = new HashMap();
mp.put(FROM_UID, from_uid);
mp.put(TO_UID, to_uid);
mp.put(CONTENT, text);
mp.put(SEND_TIME, sendTime);
System.out.println(mp);
newChat.put(FROM_UID, from_uid);
newChat.put(TO_UID, to_uid);
newChat.put(CONTENT, text);
newChat.put(SEND_TIME, sendTime);
System.out.println(newChat);
chatTable.insert(newChat);
// 写未读标记
// if(!this.hasNewMessage(to_uid, from_uid)){
saveUnreadInfo(from_uid,to_uid);
// }
} catch (Exception e) {
e.printStackTrace();
} finally {
// 事务结束
db.requestDone();
}
}
查询举例
public List queryChatMessageOneOnOne(String from_uid ,String to_uid) {
DB db = MongoManager.getDB(DB_NAME);
DBCollection table = db.getCollection(CHAT_TABLE);
// 更新为已读(清理提醒表中与自己相关的信息)
removeUnreadTable(from_uid ,to_uid);
// 查询已读
DBObject in_data = new BasicDBObject("$in",new Object[] { to_uid, from_uid });
DBObject query = new BasicDBObject();
query.put(FROM_UID, in_data);
query.put(TO_UID, in_data);
DBCursor cur = table.find(query);
List<Map> list = new ArrayList<Map>();
try {
while (cur.hasNext()) {
DBObject obj = cur.next();
Map map = new HashMap();
map.put("from_uid", obj.get(FROM_UID));
map.put("to_uid", obj.get(TO_UID));
map.put("content", obj.get(CONTENT));
map.put("send_time", obj.get(SEND_TIME));
map.put("msg_type", "1");
list.add(map);
}
} finally {
cur.close();
}
return list;
}
删除举例
public void removeUnreadTable(String from_uid, String to_uid) {
DB db = MongoManager.getDB(DB_NAME);
DBCollection table = db.getCollection(REMIND_TABLE);
DBObject deleteQuery = new BasicDBObject();
deleteQuery.put(FROM_UID, from_uid);
deleteQuery.put(TO_UID, to_uid);
table.remove(deleteQuery);
}
修改举例
@Override
public void updateUnread(DBObject mongoObj) {
// TODO Auto-generated method stub
DB db = MongoManager.getDB(DB_NAME);
DBCollection invite = db.getCollection(INVITE_TABLE);
db.requestStart();
try {
DBObject uptObj = mongoObj;
DBObject oldObj = invite.findOne(mongoObj);
uptObj.removeField(IS_READED);
uptObj.put(IS_READED, "1");
invite.update(oldObj, uptObj);
}catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
db.requestDone();
}
}
除了增删改查之外。
值得一提的是upsert:是一种先查询如果查到记录就更新,查不到记录就增加的记录的数据处理方式。
另外一个要说的是修改操作的时候除了修改某个KEY的VALUE之外,这个KEY也是可以修改的。