说起Java操作数据库自然会想到Sun的知名品牌JDBC,对于MongoDB这样的NoSQL数据库,暂时没有像JDBC这样的标准。
这篇文章中对目前的形势做了分析和憧憬http://www.csdn.net/article/2012-06-21/2806842
回到正题记录下熟悉MongoDB为Java语言提供的操作接口mongo-java-driver.jar
1.基本的根基不变,连接数据库
2.基本的数据库操作不变,CRUD
3.变化的是提供的接口,实现类名,操作对象大不相同
4.变化的是没有标准的Java操作MongoDB的标准API
MongoDB提供的Java操作API可以说是对Mongo数据库命令的Java翻译,熟悉Mongo命令,熟悉Java操作数据库的基本思路,很容易掌握基本操作。
数据库连接
package com.im; public final class SystemConstant { public static final class Configure { public static final String HOST = "127.0.0.1"; public static final int PORT = 27017; public static final String USERNAME = ""; public static final String PASSWORD = ""; public static final String DATABASE = "im"; } }
package com.im; import java.net.UnknownHostException; import com.mongodb.Mongo; import com.mongodb.MongoException; public class MongoFactory { private static MongoFactory mongoFactory; private MongoFactory() { } public static MongoFactory getInstance() { if (mongoFactory == null) { mongoFactory = new MongoFactory(); } return mongoFactory; } public Mongo getMongo() { Mongo mongo = null; try { mongo = new Mongo(SystemConstant.Configure.HOST, SystemConstant.Configure.PORT); } catch (UnknownHostException e) { e.printStackTrace(); } catch (MongoException e) { e.printStackTrace(); } return mongo; } }
数据库链接少不了的主机名,端口号,数据库名称。上面代码中的Mongo对象就相当与Connection对象。
数据库的操作
下面的每个方法代表一个方面的测试
测试类初始化方法:
private static BaseDao dao; @BeforeClass public static void start() { dao = new BaseDao("users","uf"); }
关于BaseDao是对Mongo操作数据库的基本常用的方法做了封装的一个DAO对象,代码会在本文末尾附上。
// 添加一条记录 public void test1() { BasicDBObject jo = new BasicDBObject(); jo.put("_id", "00001"); jo.put("name", "Tomcat"); jo.put("age", 22); jo.put("interest", new String[] { "swimming", "Taiji", "football" }); int actual = dao.insert(jo); System.out.println(actual); Assert.assertEquals(1, actual); }
// 添加多条记录 public void test2() { int actual = 0; int size = 0; for (int i = 2; i < 11; i++) { BasicDBObject jo = new BasicDBObject(); jo.put("_id", "0000" + i); jo.put("name", "Tomcat_" + i); jo.put("age", i * 2); jo.put("interest", new String[] { "swimming", "Taiji" }); actual += dao.insert(jo); size++; } Assert.assertEquals(size, actual); }
BasicDBObject对象是Mongo的BSONObject的基本实现类,而BSONObject对象正是Key-Value的形式的Map保存到数据库中。
// 查询指定编号的记录 public void test3() { BasicDBObject query = new BasicDBObject(); query.put("_id", "00001"); List<DBObject> dboList = dao.query(query); System.out.println(dboList.get(0).toString()); Assert.assertEquals(1, dboList.size()); } // 模糊查询,统计记录结果数量 public void test4() { BasicDBObject query = new BasicDBObject(); query.put("interest", new String[] { "swimming", "Taiji" }); long count = dao.getCount(query); Assert.assertEquals(9, count); } // 模块查询,查询结果集合 public void test5() { BasicDBObject query = new BasicDBObject(); query.put("interest", new String[] { "swimming", "Taiji" }); List<DBObject> dboList = dao.query(query); for (DBObject jo : dboList) { System.out.println(jo.toString()); } Assert.assertEquals(9, dboList.size()); }
下面是插入数据后的数据库的数据情况,图中数据是各种测试后的数据,不完全对于每个方法的操作后数据库情况。
Mongo更新操作要准备两个BasicDBObject对象,一个是要更新的对象,另一个是更新后的对象。
// 更新指定记录的信息 public void test6() { BasicDBObject query = new BasicDBObject(); query.put("_id", "00001"); BasicDBObject jo = new BasicDBObject(); jo.put("_id", "00001"); jo.put("name", "Jackson"); jo.put("interest", new String[] { "Song", "Taiji", "Running" }); jo.put("firends", new BasicDBObject[] { (BasicDBObject) dao.query( new BasicDBObject("_id", "00002")).get(0), (BasicDBObject) dao.query( new BasicDBObject("_id", "00002")).get(0) }); int actual = dao.update(query, jo); Assert.assertEquals(1, actual); }
// 删除指定记录 public void test7() { BasicDBObject query = new BasicDBObject(); query.put("_id", "000010"); dao.delete(query); List<DBObject> dboList = dao.query(query); Assert.assertEquals(0, dboList.size()); }
Mongo删除比较容易,指定一个BasicDBObject作为匹配条件,将删除匹配的所有记录(文档对象)。
在数据库的CRUD操作中查询操作更加多样化和频繁,Mongo的Java驱动程序中对Mongo数据自身的各种条件查询做了封装,提供一个QueryBuilder的类,将Mongo中的查询操作对象化,用此类来创建出要查询的条件,然后在进行基本查询。
// 指定多条件的查询 public void test8() { BasicDBObject query = new BasicDBObject(); BasicDBObject condition = new BasicDBObject(); condition.put(QueryOperators.GTE, 10); query.put("age", condition); List<DBObject> dboList = dao.query(query); for (DBObject jo : dboList) { System.out.println(jo.toString()); } Assert.assertEquals(5, dboList.size()); } public void test9() { BasicDBObject query = new BasicDBObject(); BasicDBObject condition = new BasicDBObject(); condition.put(QueryOperators.GTE, 10); condition.put(QueryOperators.LTE, 16); query.put("age", condition); List<DBObject> dboList = dao.query(query); for (DBObject jo : dboList) { System.out.println(jo.toString()); } Assert.assertEquals(4, dboList.size()); } public void test10() { QueryBuilder qb = new QueryBuilder(); BasicDBObject query = (BasicDBObject) qb.and("age") .greaterThanEquals(10).lessThanEquals(14).and("interest") .in(new String[] { "swimming", "Taiji","football" }).get(); List<DBObject> dboList = dao.query(query); for (DBObject jo : dboList) { System.out.println(jo.toString()); } }
在test8方法中的查询条件是通过创建BasicDBObject来实现,如果条件更多这样操作会写很多代码而且不易将各个条件关联起来,后面的test9和test10方法则使用QueryBuilder来实现。
上述对Mongo数据的操作侧重于准备查询条件,插入对象,删除条件,更新条件等,主要原因是Mongo数据库操作再不是我们以前SQL那样具有高度标准化的操作,相反更多的注意力集中到如何在程序语言中翻译Mongo命令操作,原因很简单没有统一的标准实现。
至于数据库的基本操作Mongo的Java驱动自然要提供最基本的操作功能。
附上BaseDao代码:
package com.im.dao; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import com.im.MongoFactory; import com.im.SystemConstant; import com.mongodb.BasicDBObject; import com.mongodb.DB; import com.mongodb.DBCollection; import com.mongodb.DBCursor; import com.mongodb.DBObject; import com.mongodb.WriteResult; import com.mongodb.gridfs.GridFS; import com.mongodb.gridfs.GridFSDBFile; import com.mongodb.gridfs.GridFSInputFile; public class BaseDao { /** * 数据库对象 */ private DB db; /** * 数据库文档对象(相当于RDBMS中的表) */ private DBCollection dbCollection; /** * 数据库文件存在集合 */ private GridFS fs; public BaseDao(String docBucket, String fileBucket) { db = MongoFactory.getInstance().getMongo() .getDB(SystemConstant.Configure.DATABASE); this.dbCollection = db.getCollection(docBucket); if (fileBucket.endsWith("") || fileBucket == null) { fileBucket = "fs"; } this.setFs(new GridFS(db, fileBucket)); } /** * 插入文档 * * @param jo * @return */ public int insert(DBObject jo) { WriteResult wr = dbCollection.save(jo); return wr.getN(); } /** * 删除文档 * * @param jo * 删除的匹配文档 */ public void delete(DBObject jo) { dbCollection.remove(jo); } /** * 更新文档 * * @param query * 指定更新的文档 * @param jo * 更新后的文档 * @return */ public int update(DBObject query, DBObject jo) { WriteResult wr = dbCollection.update(query, jo); return wr.getN(); } /** * 查询文档 * * @param query * 查询的匹配文档 * @return */ public List<DBObject> query(DBObject query) { DBCursor dbc = dbCollection.find(query); List<DBObject> joList = new ArrayList<DBObject>(); while (dbc.hasNext()) { DBObject jo = dbc.next(); joList.add(jo); } return joList; } /** * 存储文件 * * @param file */ public void saveFile(File file) { try { GridFSInputFile gif = fs.createFile(file); gif.save(); } catch (IOException e) { e.printStackTrace(); } } /** * 存储输入流,并指定的一些描述信息 * * @param in * @param id * @param filename * 文件名 * @param contentType * 文件内容类型 */ public void saveFile(InputStream in, Object id, String filename, Object contentType) { DBObject query = (DBObject) new BasicDBObject("_id", id); GridFSDBFile gff = fs.findOne(query); if (gff == null) { GridFSInputFile gif = fs.createFile(in); gif.setFilename(filename); gif.put("_id", id); gif.put("contentType", contentType); gif.save(); } } /** * 查询指定ID的文件 * * @param id * @return */ public GridFSDBFile queryFile(Object id) { DBObject query = (DBObject) new BasicDBObject("_id", id); return fs.findOne(query); } /** * 查询指定文件名的文件 * * @param filename * @return */ public GridFSDBFile queryFile(String filename) { DBObject query = (DBObject) new BasicDBObject("filename", filename); return fs.findOne(query); } /** * 查询文件 * * @param query * 查询的匹配文件 * @return */ public List<GridFSDBFile> queryFile(DBObject query) { return fs.find(query); } /** * 统计查询结果数 * * @param query * 查询匹配的文档 * @return */ public long getCount(DBObject query) { return dbCollection.getCount(query); } public GridFS getFs() { return fs; } public void setFs(GridFS fs) { this.fs = fs; } public DBCollection getDbCollection() { return dbCollection; } public void setDbCollection(DBCollection dbCollection) { this.dbCollection = dbCollection; } }