MongoDB에서 Java 응용 프로그램 개발하기 - 30분 가이드

[출처] http://java.dzone.com/articles/mongodb-30-minutes-draft

Java App on MongoDB in 30 Minutes

05.22.2012
| 6423 views |
<style type="text/css"> .microzone_article_ad{ font-size: 15px; font-weight:normal; font-style:italic; color: #222; text-decoration:none; font-family:'Helvetica', 'Arial', 'Verdana'; } </style>
This article is part of the DZone NoSQL Resource Portal, which is brought to you in collaboration with Neo Technology. Visit the NoSQL Resource Portal for additional tutorials, videos, opinions, and other resources on this topic.

I have recently been bitten by the NoSQL bug - or as colleague of mine Mark Atwell coined "Burn the Where!" movement. While I have no intention of shunning friendly "SELECT ... WHERE" anytime soon - or in foreseeable future, I did manage to get my hands dirty with some code. In this article, I share the knowledge of my first attempts in the NoSQL world.

In this article we will aim to get a basic java application up and running that is capable of interacting with MongoDB. By itself, that is not really a tall task and perhaps you could get that in under 10 minutes. Click here or click here or click here, for some excellent material. However, I wanted to push it a bit further.

I want to add ORM support. I have chosen Morphia for this article. I also want to add DAO pattern, unit testing, and logging. In short, I want to it feel, "almost like" the kind of code that most of us would have written for enterprise applications using, let's say Java, Hibernate and Oracle. And, we will try to do all this in under 30 minutes.

My intention is to give a reassurance to Java + RDBMS developers that Java + NoSQL is not very alien. It is similar code and easy to try out. It is perhaps pertinent to add at this point that I have no affinity to NoSQL and no issues with RDBMS. I beieve they both have their own uses (click here for some excellent material). As a technologist, I just like knowing my tools better so that I can do justice to my profession. This article is solely aimed at helping like minded people to dip their toes in NoSQL.

Ok, enought talk. Let's get started. You will need a few softwares / tools before you follow this article. Download and install MongoDB server, if you have not already done so. I am assuming you have Java, some Java IDE and a build and release tool. I am using jdk 7, Eclipse (STS) and Maven 3 for this article.

I start by creating a vanilla standard java application using Maven. I like using a batch file for this.

File: codeRepo\MavenCommands.bat

01.ECHO OFF
02.
03.REM =============================
04.REM Set the env. variables.
05.REM =============================
06.SET PATH=%PATH%;C:\ProgramFiles\apache-maven-3.0.3\bin;
07.SET JAVA_HOME=C:\ProgramFiles\Java\jdk1.7.0
08.
09.REM =============================
10.REM Create a simple java application.
11.REM =============================
12.call mvn archetype:create ^
13. -DarchetypeGroupId=org.apache.maven.archetypes ^
14. -DgroupId=org.academy ^
15. -DartifactId=dbLayer002
16.
17.pause

Import it in Eclipse. Use Maven to compile and run just to be sure.

1.mvn -e clean install.

This should compile the code and run the default tests as well. Once you have crossed this hurdle, now let's get down to some coding. Let's create an Entity object to start with. I think a Person class with fname would serve our purpose. I acknowledge that it is trivial but it does the job for a tutorial.

File: /dbLayer002/src/main/java/org/academy/entity/Person.java

1.package org.academy.entity;
2.
3.public class Person {
4. private String fname;
5.
6. [...]
7.}

I have not mentioned the getters and setters for brevity.

Now let us get the MongoDB java driver and attach it to the application. I like have Maven do this bit for me. You could obviously do this bit manually as well. Your choice. I am just lazy.

File: /dbLayer002/pom.xml

1.[...]
2.<!-- MongDB java driver to hook up to MongoDB server -->
3.<dependency>
4. <groupId>org.mongodb</groupId>
5. <artifactId>mongo-java-driver</artifactId>
6. <version>2.7.3</version>
7.</dependency>
8.[...]

This will allow us to write a util class for connecting to MongoDB server instance. I am assuming you have a server up and running in your machine with default settings.

File: /dbLayer002/src/main/java/org/academy/util/MongoUtil.java

01.public class MongoUtil {
02.
03. private final static Logger logger = LoggerFactory
04. .getLogger(MongoUtil.class);
05.
06. private static final int port = 27017;
07. private static final String host = "localhost";
08. private static Mongo mongo = null;
09.
10. public static Mongo getMongo() {
11. if (mongo == null) {
12. try {
13. mongo = new Mongo(host, port);
14. logger.debug("New Mongo created with [" + host + "] and ["
15. + port + "]");
16. } catch (UnknownHostException | MongoException e) {
17. logger.error(e.getMessage());
18. }
19. }
20. return mongo;
21. }
22.}

We will need logger setup in our application for this class to compile. Click here for my article around logging. All we need to do is to hook up Maven with the correct dependencies.

File: /dbLayer002/pom.xml

01.[...]
02.<slf4j.version>1.6.1</slf4j.version>
03.[...]
04.<!-- Logging -->
05.<dependency>
06. <groupId>org.slf4j</groupId>
07. <artifactId>slf4j-api</artifactId>
08. <version>${slf4j.version}</version>
09.</dependency>
10.<dependency>
11. <groupId>org.slf4j</groupId>
12. <artifactId>jcl-over-slf4j</artifactId>
13. <version>${slf4j.version}</version>
14. <scope>runtime</scope>
15.</dependency>
16.<dependency>
17. <groupId>org.slf4j</groupId>
18. <artifactId>slf4j-log4j12</artifactId>
19. <version>${slf4j.version}</version>
20. <scope>runtime</scope>
21.</dependency>

And also, we will need to specify, exactly what to log.

File: /dbLayer002/src/java/resources/log4j.properties

1.# Set root logger level to DEBUG and its only appender to A1.
2.log4j.rootLogger=DEBUG, A1
3.
4.# configure A1 to spit out data in console
5.log4j.appender.A1=org.apache.log4j.ConsoleAppender
6.log4j.appender.A1.layout=org.apache.log4j.PatternLayout
7.log4j.appender.A1.layout.ConversionPattern=%d [%t] %-5p %c - %m%n

At this point, you already have an Entity class and a utility class to hook up to the database. Ideally I would go about writing a DAO and then somehow use the ORM to join up the DAO with the database. However, Morphia has some excellent DAO support. Also it has some annotations to tie up the Entity with database elements. So, although I would have liked the Entity and DAO to be totally agnostic of the ORM and database, it is not the case here. I know on the face of it, it sounds like Morphia or MongoDB is forcing me to deviate from good code structure, let me hasten to add, that it is not any worse than other ORMs e.g. Hibernate with Annotations would have also forced me to make the same kind of compromise.

So, let's bring in Morphia in the picture. Enters the stage our ever helpful tool, Maven. A bit of an avoidable hitch here. When I was writing this document I could not get the version of Morphia that I wanted in the central Maven repository. So, I had to configure Maven to use the Morphia repository as well. Hopefully this is just a temporary situation.

File: /dbLayer002/pom.xml

01.[...]
02.<!-- Required for Morphia -->
03.<repositories>
04. <repository>
05. <id>Morphia repository</id>
07. </repository>
08.</repositories>
09.[...]
1.<!-- Morphia - ORM for MongoDB -->
2.<dependency>
3. <groupId>com.google.code.morphia</groupId>
4. <artifactId>morphia</artifactId>
5. <version>0.98</version>
6.</dependency>

As I mentioned above, Morphia allows us to annotate the Entity class (much like Hibernate annotations). So, here is how the updated Entity class looks like.

File: /dbLayer002/src/main/java/org/academy/entity/Person.java

1.[...]
2.@Entity
3.public class Person {
4. @Id private ObjectId id;
5. [...]
6.

And now we can also add a DAO layer and lean on the BasicDAO that Morphia provides.

File: /dbLayer002/src/main/java/org/academy/dao/PersonDAO.java

1.public class PersonDAO extends BasicDAO<Person, ObjectId> {
2.
3. public PersonDAO(Mongo mongo, Morphia morphia, String dbName) {
4. super(mongo, morphia, dbName);
5. }
6. [...]

The beauty of the BasicDAO is that just by extending that, my own DAO class already has enough functionality to do the basic CRUD operations, although I have just added a constructor. Don't believe it? Ok, lets write a test for that.

File: /dbLayer002/src/test/java/org/academy/dao/PersonDAOTest.java

01.public class PersonDAOTest {
02. private final static Logger logger = LoggerFactory
03. .getLogger(PersonDAOTest.class);
04.
05. private Mongo mongo;
06. private Morphia morphia;
07. private PersonDAO personDao;
08. private final String dbname = "peopledb";
09.
10. @Before
11. public void initiate() {
12. mongo = MongoUtil.getMongo();
13. morphia = new Morphia();
14. morphia.map(Person.class);
15. personDao = new PersonDAO(mongo, morphia, dbname);
16. }
17.
18. @Test
19. public void test() {
20. long counter = personDao.count();
21. logger.debug("The count is [" + counter + "]");
22.
23. Person p = new Person();
24. p.setFname("Partha");
25. personDao.save(p);
26.
27. long newCounter = personDao.count();
28. logger.debug("The new count is [" + newCounter + "]");
29.
30. assertTrue((counter + 1) == newCounter);
31. [...]

As you might have already noticed. I have used JUnit 4. If you have been following this article as is till now you would have an earlier version of JUnit in your project. To ensure that you use JUnit 4, you just have to configure Maven to use that by adding the correct dependency in pom.xml.

File: /dbLayer002/pom.xml

1.<!-- Unit test. -->
2.<dependency>
3. <groupId>junit</groupId>
4. <artifactId>junit</artifactId>
5. <version>4.10</version>
6. <scope>test</scope>
7.</dependency>

You are good to go. If you run the tests they should pass. Of course you could / should get into your database and check that the data is indeed saved. I will refer you to the MongoDB documentation which I think are quite decent.

Last but not least, let me assure you that BasicDAO is not restrictive in any way. I am sure puritans would point out that if my DAO class needs to extend the BasicDAO that is a limitation on the source code structure anyway. Ideally should not have been required. And I agree with that. However, I also want show that for all practical purposes of DAO, you have sufficient flexibility. Let's go on and add a custom find method to our DAO, that is specific to this Entity i.e. Person. Let's say we want to be able to search on the basis of firstname and that we want to use regular expression for that. Here is how the code will look like.

File: /dbLayer002/src/main/java/org/academy/dao/PersonDAO.java

01.public class PersonDAO extends BasicDAO<Person, ObjectId> {
02.
03. [...]
04. public Iterator<Person> findByFname(String fname){
05. Pattern regExp = Pattern.compile(fname + ".*", Pattern.CASE_INSENSITIVE);
06. return ds.find(entityClazz).filter("fname", regExp).iterator();
07. }
08. [...]
09.}

Important to reemphasize here that, I have just added a custom search function to my DAO, by adding precisely three lines of code (four if you add the last parentheses). In my books, that is quite flexible. Being true to my unflinching love for automated testing, lets add a quick test to check this functionality before we wrap up.

File: /dbLayer002/src/test/java/org/academy/dao/PersonDAOTest.java

1.[...]
2.Iterator<Person> iteratorPerson = personDao.findByFname("Pa");
3.int personCounter = 0 ;
4.while(iteratorPerson.hasNext()){
5. personCounter ++;
6. logger.debug("["+personCounter+"]" + iteratorPerson.next().getFname());
7.}
8.[...]

Before you point out, yes, there are no assert() here, so this is not a real test. Let me assure you that my test class is indeed complete. It's just that this snippet here does not have the assert function.

So, that's it. You have used Java to connect to a NoSQL database, using an ORM, through a DAO layer (where you have used the ORM's functionalities and done some addition as well). You have also done proper logging and unit testing. Not bad use of half an hour, eh? Happy coding.

Note: The original article is available at author's blog. Click here.

Published at DZone with permission of Partha Bhattacharjee, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

<style type="text/css"> .microzone_article_ad{ font-size: 15px; font-weight:normal; font-style:italic; color: #222; text-decoration:none; font-family:'Helvetica', 'Arial', 'Verdana'; } </style>
Neo Technology is leading the charge for the NoSQL movement. You can learn more about the Neo4j Graph Database in the project discussion forums and you can try out the new Spring Data Neo4j, which enables POJO-based development.

'Computer Science' 카테고리의 다른 글

JavaScript 및 CCS 코드 은닉 (php의 경우)  (0) 2012.11.12
2013년 IT 트렌드  (0) 2012.10.29
MongoDB GridFS 튜토리얼  (0) 2012.10.28
[perl script] perl 사용 팁  (0) 2012.10.10
[파이썬] scrapy 로 웹 사이트 크롤링  (0) 2012.10.09

+ Recent posts