読者です 読者をやめる 読者になる 読者になる

SpringMVC、MongoDBを使ってみたその1

SpringMVC、MongoDBを使って簡単なWebアプリを作ってます。
まだ全部作ってはないけど、最初にハマったところをメモ。

下のようなサイトを参考にさせて頂きました。
http://journal.mycom.co.jp/articles/2010/04/09/spring5/index.html
http://d.hatena.ne.jp/fits/20110205/1296888257
あと、ソースはGitHubへUP
https://github.com/hachi7/spring-mvc-sample

前提条件(プラグインとかDBとか)は以下のとおり

作るものを決める

今回はCRUDをできればいいかなと思い、サーバ情報(IPアドレスとか、OSとか)を管理するアプリを作成。

データアクセス周りを作る

実データの作成

データは以下のような構造を想定。コレクション名はserversとしました。

{name:'server1',
ips:['127.0.0.1', '192.168.0.1'],
os:'redhat',
soft:[ {apache:'2.2'},{java: 'update21'},{MySQL: '5.5'} ],
created: new Date(), updated:new Date()
}
{name:'server2',
ips:['127.0.0.1', '192.168.0.2'],
os:'redhat',
soft:[{apache:'2.2'} ],
created: new Date(),
updated:new Date()
}
{name:'server3',
ips:['127.0.0.1', '192.168.0.3'],
os:'Windows',
soft:[{IIS:'6.0'},{SQLServer:'2008'}],
created: new Date(),
updated:new Date()
}

DBアクセスの共通クラスを作成

以下のようなクラスを作成しました。(import文などは除く)
ポイントは以下の3つです。このようにすることで起動時にgetDataSource処理が実行されます。

@Configuration
このクラスをBeanに定義
@Value
#{db.host}でプロパティファイルから読み込み。
@Bean
@Autowiredした結果を設定(後述)

プロパティを読み込むようにWEB-INF/springにxmlを記述

<util:properties id="db" location="classpath:db.properties" />

DB情報を取得するクラス(クラス名はこれでいいのだろうか??)

@Configuration
public class DataSource {
	private static final Logger logger = LoggerFactory.getLogger(DataSource.class);
	private static final Marker marker = MarkerFactory.getMarker(DataSource.class.getName());
	
	private @Value("#{db.host}") String host;
	private @Value("#{db.port}") String port;
	private @Value("#{db.dbname}") String dbName;
	private @Value("#{db.user}") String user;
	private @Value("#{db.password}") String password;
	
	@Bean
	public DB getDataSource(){
		try {
			Mongo m = new Mongo(host, Integer.parseInt(port));
			DB db = m.getDB(dbName);
			boolean isAuth = db.authenticate(user, password.toCharArray());
			if(!isAuth){
				logger.error("can't auth mongodb");
				return null;
			}else{
				logger.debug("can auth mongodb");
			}
			return db;
		} catch (NumberFormatException e) {
			logger.error(marker, e.getMessage(), e);
		} catch (UnknownHostException e) {
			logger.error(marker, e.getMessage(), e);
		} catch (MongoException e) {
			logger.error(marker, e.getMessage(), e);
		}
		return null;
	}
}

getDataSourceで取得した結果をdbへ設定しています。
各Controllerクラスはこれらを継承することにより、楽にDBに接続できます。

@Component
public class DBController {
	
	@Autowired
	private DB db;
	
	public DB getDb(){
		return db;
	}
}


(2011/08/24追記 MongoDBからデータを取得するクラスを書いてなかったです。)

データアクセス周りその2 MongoDBからデータを取得する

MongoDBからデータを取得するDAOクラスのポイントは、
com.mongodb.DBクラスからgetCollectionで対象のコレクション(RDBMSでいうテーブル)を選択して、
findメソッドの結果をDBCursorへ入れています。

		DBCollection collection = db.getCollection(COLLECTION_NAME);
		DBCursor cursor = collection.find().sort(new BasicDBObject("created", 1));

collection.find().sort()のコードだけ見ると、
これってfindの結果をJVMメモリ上へいれて、その中でソートをやってるのでしょうか?
RDBMSだとソートコストはDBサーバになるけど、ソートのコストはどこにかかるのかなぁ?
よくよく考えたら、カーソル(ポインタ)しかJVMへは持ってないから、ソートコストもDBにかかるのか。
教えてえらい人