빅데이터 Java 개발자 교육 - 06일차 [while문, MongoDB]

Jun_Gyu·2023년 2월 25일

오늘은 MongoDB를 이용하여 회원 정보들을 보관할 수 있도록 eclips와 MongoDB를 연동하는 코드를 짜볼것이다.


public void forAge() {
		for (int i = 1; i <= this.age; i++) {
			System.out.print(i + ", ");    // 1, 2, 3,
		}
		System.out.println();
		System.out.println("--------");    // --------
		
		int m = 1;
		while(m <= this.age) {
			System.out.print(m + ", ");    // 1, 2, 3,
			m++;

들어가기 앞서서 while문의 사용법. 두개의 값이 똑같이 출력되니 참고할 것. (age 값은 3으로 설정해두었다.)


먼저 MongoDB 접속을 한다.

MongoDB의 경우

mongodb://아이디:패스워드@주소:포트번호/데이터베이스번호

가 되겠다.

final String url = " ";
		
		url = "aaa";
		// final 을 붙이면 생성 당시의 값으로 프로그램이 끝날때 까지 유지가 된다.
		// 이유는 바꿀수 없는 상수이기 때문.

url의 경우 똑같은곳에 자료들을 저장을 해야하기때문에 바뀌지 않도록 값을 고정시킨다.

​

들어가기 앞서 먼저 전체적으로 구성된 코드를 참고용으로 미리 올려두고 살펴보도록 하겠다.

package day6;

import org.bson.Document;
import org.bson.conversions.Bson;

import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.Filters;
import com.mongodb.client.model.Updates;
import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.InsertOneResult;
import com.mongodb.client.result.UpdateResult;

// 기능용 클래스
// 몽고DB 연동

public class MemberDB {
	MongoCollection<Document> collection = null;
	// 변수는 모든 메소드에 사용 가능하기 위해 바깥으로 뺌.
	// 변수 X
	// 생성자
	public MemberDB() {
		// 공통변수가 아니기 때문에 생성자 내부에서만 사용가능한 변수 생성.

		// final 을 붙이면 생성 당시의 값으로 프로그램이 끝날때 까지 유지가 된다. 이유는 바꿀수 없기 때문.
		// mongodb://아이디:비밀번호@주소:포트번호/디비명

		final String url = " mongodb://아이디:비밀번호@주소:포트번호/디비명";

		// static클래스를 통해서 접속이 가능함. (import도 해주어야 함.)
		MongoClient client = MongoClients.create(url);
		MongoDatabase db = client.getDatabase("db209");
		this.collection = db.getCollection("members");

	}

	// 이름이 "가나다"인 사람만 조회
	public void printMembersName(String searchName) {

		// 키 또는 필드가 name인 것중에서 searchName과 정확하게 일치하는 필터
		Bson filter = Filters.eq("name", searchName);
		MongoCursor<Document> list = this.collection.find(filter).iterator();
		while (list.hasNext()) { // 2개 있으니 2번 수행
			Document doc = list.next();
			System.out.println("아이디 =>" + doc.getString("_id"));
			System.out.println("비밀번호 =>" + doc.getString("password"));
			System.out.println("나이 =>" + doc.getInteger("age"));
			System.out.println("------------------------------------");
		}
	}

	// 전체 회원조회 메소드
	public void printMembers() {
		MongoCursor<Document> list = this.collection.find().cursor(); // 반복자
		// ex)1000 => 500개만 부분출력(X)
		// 반복자(처음부터 끝까지 전체다 반복할거라고 가정
		/*-----------------------------반복자 반복문----------------------------*/
		// 가져올 데이터가 있나요?? (반복문)
		while (list.hasNext()) { // 그 다음 가져 올 데이터가 있는지?
			Document doc = list.next(); // 있다면 가져오기
			System.out.println("아이디 =>" + doc.getString("_id"));
			System.out.println("비밀번호 =>" + doc.getString("password"));
			System.out.println("나이 =>" + doc.getInteger("age"));
			System.out.println("------------------------------------");

		}
	}

	// 회원가입 메소드
	public int insertMember(Member member) {
		try { // 정상동작
			Document doc = new Document();
			// 키가 반드시 _id 기본키로 봄. (id는 중복되어 DB에 올라갈 수 없다.)
			doc.append("_id", member.getId());
			doc.append("password", member.getPassword());
			doc.append("name", member.getName());
			doc.append("age", member.getAge());
			doc.append("phone", member.getPhone());
			doc.append("role", member.getRole());
			doc.append("regdate", member.getRegdate());

			InsertOneResult result = this.collection.insertOne(doc);
			System.out.println(result.toString());
			return 1;

		} catch (Exception e) {// 오류가 발생 시 이쪽의 메소드가 수행됨.

			// Exception클래스의 e변수에 오류의 정보(오류 메시지)가 전송되게 됨.
			e.printStackTrace(); // 오류 메세지를 전체적으로 출력해줌. 개발자를 위한 기능

			return -1; // 오류시 보통 -1로 반환함!
		}
		

	}
package day6;

import java.util.Date;

public class Main1 {

	public static void main(String[] args) {

	// 1. 객체 생성
	// DB에 접속하고 members collection 접속
	MemberDB mDB = new MemberDB();
		
	// 2. 회원가입하고 싶은 임시 데이터 (아이디,암호,이름,나이,연락처,권한,현재시간)
	Member member = new Member("43", "40000", "가나다", 19, "010-0020-0001", "C", new Date());
	
	// 3. DB에 추가하는 메소드 수행
	int ret = mDB.insertMember(member); //성공하면 1, 실패시 -1
	System.out.println(ret);
	}
	
}

여러 정보들을 저장해보자.


이렇게. 그렇다면 한번 저장되어 있는 정보들을 가져와보자

먼저 전체 회원들이 누가 있는지 뽑아와보자. MemberDB클래스에 아래 메소드 작성하여

	// 전체 회원조회 메소드
	public void printMembers() {
		MongoCursor<Document> list = this.collecttion.find().cursor(); // 반복자
		// 1000 => 500개만 출력(X)
		// 반복자(처음부터 끝까지 전체다 반복할거라고 가정
		
		/*-------------------------------반복자 반복문----------------------------*/
		// 가져올 데이터가 있나요??  (반복문)
		while (list.hasNext()) { // 그 다음 가져 올 데이터가 있는지?
			Document doc = list.next();
			System.out.println("아이디 =>" + doc.getString("_id"));
			System.out.println("비밀번호 =>" + doc.getString("password"));
			System.out.println("나이 =>" + doc.getInteger("age"));
			System.out.println("------------------------------------");
		}
}

메인클래스에서 mDB.printMembers();로 값을 뽑아내게 되면 MongoDB에 저장되어있는 데이터를 바탕으로 아래와 같은 결과가 나오게 된다.

이번엔 이름이 "가나다"인 사람만 조회하여 보자. 아래처럼 이름만 분리해주는 메소드를 만들어

// 이름이 "가나다"인만 조회(searchName값을 "가나다")
	public void printMembersName( String searchName ) {
		// 키 또는 필드가 name인 것중에서 searchName과 정확하게 일치하는 필터
		Bson filter = Filters.eq("name", searchName );
		MongoCursor<Document> list = this.collecttion.find(filter).iterator();
		while(list.hasNext()) { // 2개 있으니 2번 수행
			Document doc = list.next();
			System.out.println("아이디 =>" + doc.getString("_id"));
			System.out.println("비밀번호 =>" + doc.getString("password"));
			System.out.println("나이 =>" + doc.getInteger("age"));
			System.out.println("------------------------------------");
		}
}

이를 메인에서

MemberDB mDB = new MemberDB()

을 통해서 DB에 접속하고 mDB.printMembersName();메소드를 불러와 실행하게 되면

로 나오게 된다.


확인해보면 정확히 '가나다'라는 이름의 사람만 출력된걸 확인할 수 있다. 여기서 여러 조건의 메소드를 생성할 것 같으니 객체를 줄이고자 분류된값을 출력해주는 메소드는 따로 만들어주도록 하겠다!

public void printAction(Bson filter) {
		MongoCursor<Document> list = this.collecttion.find(filter).iterator();
		while (list.hasNext()) {
			Document doc = list.next();
			System.out.println("아이디 =>" + doc.getString("_id"));
			System.out.println("비밀번호 =>" + doc.getString("password"));
			System.out.println("나이 =>" + doc.getInteger("age"));
			System.out.println("------------------------------------");
	}
}

이렇게.

그렇다면 이제 분류를 하기위한 조건을 만드는 메소드에서는 Bson filter = Filters.와 printAction(filter); 를 이용해서 불러오기만 하면 된다.

여기서 실습을 두가지 진행하였다. // 문제1) 고객, 판매자만 조회하는 필터링

public void printMembersRole(String searchRole) {
		// 키 또는 필드가 name인 것중에서 searchRole과 정확하게 일치하는 필터
		Bson filter = Filters.eq("role", searchRole);

		printAction(filter);
}

// 문제2) 나이가 n 이상인 것만 필터링

public void printMembersAge(Integer n) {
		// 키 또는 필드가 name인 것중에서 searchName과 정확하게 일치하는 필터
		Bson filter = Filters.gte("age", n); // 나이가 n 이상이면 .gte, 이하면 .lte이다. [맛있는MongoDB Pg.91]

printAction(filter);
}

여기서 주의할것이 있다.

문제의 조건에서 나이가 'n' 이상인 것만 필터링을 하기 위해서는 Filters. 뒤에 "gte"를 붙여주어야 한다. 초과는 gt.

(이하인 것만 출력하려면 lte, 미만은 lt이다)

​
​

그다음으로는

데이터베이스에 저장된 아이디 bbb의 회원정보를 수정해볼것이다.

// 회원정보 수정하기. 이름, 연락처, 나이정보 (암호는 변경 불가능.)
	public int updateMember(Member member) {
		try {
			//변경하고자 하는 항목의 조건
/*2번*/		Bson filter = Filters.eq("_id", member.getId());
			
			//변경할 항목들...
/*3번*/   	Bson update1 = Updates.set("name", member.getName());
			Bson update2 = Updates.set("phone", member.getPhone());
			Bson update3 = Updates.set("age", member.getAge());
			
			// updateOne (조건, 변경값) => 변경값이 하나의 Bson에만 가능.. combine
/*4번*/		Bson update = Updates.combine(update1, update2, update3);
			
/*1번*/		UpdateResult result = this.collection.updateOne(filter, update);
			System.out.println(result.toString());
			return 1;
		} catch (Exception e) {
			e.printStackTrace();
			return -1;
	}

}

데이터베이스에 다른 정보들과 구분되는 기준이 '아이디'이기때문에 아이디는 수정할 수 없다.

그리고 암호또한 암호화 키로 변경되어 저장되기에 현재 배운것들로써는 암호를 변경하기는 어렵다. 위의 코드 실행 조건은 좌측에 써있는 번호의 순번대로 이루어진다.

// 회원정보 수정하기
	Member member = new Member();
	member.setId("bbb");
	member.setName("abcd"); // 변경할 이름
	member.setPhone("010-3455-6778"); // 변경할 전화번호
	member.setAge(33); // 변경할 나이
	
	int ret = mDB.updateMember(member); //성공하면 1, 실패시 -1
	System.out.println(ret);

이렇게 메인클래스에서 기준이 되는 ID를 제외하고 나머지를 바꿔줄 값으로 대입한다. 문제없이 따라왔다면

위와 같이 1이 출력된걸 확인할 수 있고,

변경이 된것을 확인 할 수 있다.

그렇다면 다음으로는 회원탈퇴, 데이터 삭제이다.

방금 수정이 된 아이디 bbb의 회원정보를 한번 삭제시켜보자.

public int deleteMember(String id) {
		try {
			Bson filter = Filters.eq("_id", id);
			DeleteResult result = this.collection.deleteOne(filter);
			System.out.println(result.toString());
			return 1;
		} catch (Exception e) {
			e.printStackTrace();
			return -1;
    }
 }

다음과 같이 메소드를 만들어 DeleteResult 메소드를 이용하여 입력된 id 값을 삭제시킨다. try catch문을 사용해 오류가 없는지 또한 검사한다. 이후 메인에서 아래 코드로 실행하게되면

public static void main(String[] args) {

        MemberDB mDB = new MemberDB();
	    // 회원정보 삭제하기
		int ret = mDB.deleteMember("bbb");  // 정보가 삭제되어도 1이 뜨는 문제 해결필요
		System.out.println(ret);
}


(모르고 1을 출력하는 코드를 안넣고 찍었다.. 양해바란다.)

위처럼 나오게 된다. 계정이 하나 지워졌고
{deletedCount = 1}

정상적으로 잘 작동했다고 1이 출력되었다.

하지만 여기서 문제가 발생한다.


이미 지워진 아이디를 다시 한번 더 삭제했는데도

1이 출력이 되는 것이다.
​
그렇다면 어떻게 해결하여야 할까??

public int deleteMember(String id) {
		try {
			Bson filter = Filters.eq("_id", id);
			DeleteResult result = this.collection.deleteOne(filter);
			System.out.println(result.toString());
			if (result.getDeletedCount() == 1L) {
				return 1;
			}
			return 0;

		} catch (Exception e) {
			e.printStackTrace();
			return -1;
	}
 }

바로 try문에서 if문을 넣어

삭제가 이루어진 경우 {deletedCount = 1} 에만 1이라는 값을 반환하도록 조건문을 넣을 수 있다.

삭제가 이루어지지 않는 경우, 0이 출력되도록 try문을 살짝 수정하였다.
​
그렇다면 이미 지워진 아이디값에 대해서


이렇게 0이라는 값을 도출하게 되기 때문에 추후 혼동이 될 부분을 원천적으로 차단할 수 있겠다.
​
아래는 이후 추가된 예제문제까지 구성이 완료된 코드이다.

package day6;

import org.bson.Document;
import org.bson.conversions.Bson;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.Filters;
import com.mongodb.client.model.Updates;
import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.InsertOneResult;
import com.mongodb.client.result.UpdateResult;
// 기능용 클래스
// 몽고DB 연동

public class MemberDB {
	MongoCollection<Document> collection = null;

	// 변수는 모든 메소드에 사용 가능하기 위해 바깥으로 뺌.
	// 변수 X
	// 생성자
	public MemberDB() {
		// 공통변수가 아니기 때문에 생성자 내부에서만 사용가능한 변수 생성.

		// final 을 붙이면 생성 당시의 값으로 프로그램이 끝날때 까지 유지가 된다. 이유는 바꿀수 없기 때문.
		// mongodb://아이디:비밀번호@주소:포트번호/디비명
		final String url = "mongodb://아이디:비밀번호@주소:포트번호/디비명";
		// static클래스를 통해서 접속이 가능함. (import도 해주어야 함.)
		MongoClient client = MongoClients.create(url);
		MongoDatabase db = client.getDatabase("db209");
		this.collection = db.getCollection("members");
	}

	// 특정 이름의 사람만 조회
	public void printMembersName(String searchName) { // 
		// 키 또는 필드가 name인 것중에서 searchName과 정확하게 일치하는 필터
		Bson filter = Filters.eq("name", searchName);
		MongoCursor<Document> list = this.collection.find(filter).iterator();
		while (list.hasNext()) { // 2개 있으니 2번 수행
			Document doc = list.next();
			System.out.println("아이디 =>" + doc.getString("_id"));
			System.out.println("비밀번호 =>" + doc.getString("password"));
			System.out.println("나이 =>" + doc.getInteger("age"));
			System.out.println("------------------------------------");
		}
	}

	// 전체 회원조회 메소드
	public void printMembers() {
		MongoCursor<Document> list = this.collection.find().cursor(); // 반복자
		// 1000 => 500개만 출력(X)
		// 반복자(처음부터 끝까지 전체다 반복할거라고 가정
		/*-----------------------------반복자 반복문----------------------------*/
		// 가져올 데이터가 있나요?? (반복문)
		while (list.hasNext()) { // 그 다음 가져 올 데이터가 있는지?
			Document doc = list.next();
			System.out.println("아이디 =>" + doc.getString("_id"));
			System.out.println("비밀번호 =>" + doc.getString("password"));
			System.out.println("나이 =>" + doc.getInteger("age"));
			System.out.println("------------------------------------");
		}
	}

	// 회원가입 메소드
	public int insertMember(Member member) {
		try { // 정상동작
			Document doc = new Document();
			// 키가 반드시 _id 기본키로 봄. (id는 중복되어 DB에 올라갈 수 없다.)
			doc.append("_id", member.getId());
			doc.append("password", member.getPassword());
			doc.append("name", member.getName());
			doc.append("age", member.getAge());
			doc.append("phone", member.getPhone());
			doc.append("role", member.getRole());
			doc.append("regdate", member.getRegdate());
			InsertOneResult result = this.collection.insertOne(doc);
			System.out.println(result.toString());
			return 1;

		} catch (Exception e) {// 오류가 발생 시 이쪽의 메소드가 수행됨.

			// Exception클래스의 e변수에 오류의 정보(오류 메시지)가 전송되게 됨.
			e.printStackTrace(); // 오류 메세지를 전체적으로 출력해줌. 개발자를 위한 기능

			return -1; // 오류시 보통 -1로 반환함!
		}
	}
    // 결과 생성용 메소드
	public void printAction(Bson filter) {
		MongoCursor<Document> list = this.collection.find(filter).iterator();
		while (list.hasNext()) {
			Document doc = list.next();
			System.out.println("아이디 =>" + doc.getString("_id"));
			System.out.println("비밀번호 =>" + doc.getString("password"));
			System.out.println("나이 =>" + doc.getInteger("age"));
			System.out.println("------------------------------------");
		}
	}
	
	/*---------------------문제-------------------------*/
	// 문제1) 고객, 판매자만 조회하는 필터링
	// 조건과 같으면 .eq
	public void printMembersRole(String searchRole) {
		// 키 또는 필드가 name인 것중에서 searchRole과 정확하게 일치하는 필터
		Bson filter = Filters.eq("role", searchRole);
		printAction(filter);

	}

	// 문제2) 나이가 n 이상인 것만 필터링
	// 이상이면 .gte, 이하면 .lte이다. 크면 gt, 작으면 lt[맛있는MongoDB Pg.91]
	public void printMembersAge(Integer n) {
		// 키 또는 필드가 name인 것중에서 searchName과 정확하게 일치하는 필터
		Bson filter = Filters.gte("age", n);
		printAction(filter);
	}

	// 회원정보 수정하기. 이름, 연락처, 나이정보 (암호는 변경 불가능.)
	public int updateMember(Member member) {
		try {
			// 변경하고자 하는 항목의 조건
			/* 2번 */ Bson filter = Filters.eq("_id", member.getId());

			// 변경할 항목들...
			/* 3번 */ Bson update1 = Updates.set("name", member.getName());
			Bson update2 = Updates.set("phone", member.getPhone());
			Bson update3 = Updates.set("age", member.getAge());

			// updateOne (조건, 변경값) => 변경값이 하나의 Bson에만 가능.. combine
			/* 4번 */ Bson update = Updates.combine(update1, update2, update3);

			/* 1번 */ UpdateResult result = this.collection.updateOne(filter, update);
			System.out.println(result.toString());
			return 1;
		} catch (Exception e) {
			e.printStackTrace();
			return -1;
		}

	}

	public int deleteMember(String id) {
		try {
			Bson filter = Filters.eq("_id", id);
			DeleteResult result = this.collection.deleteOne(filter);
			System.out.println(result.toString());
			if (result.getDeletedCount() == 1L) {
				return 1;
			}
			return 0;
		} catch (Exception e) {
			e.printStackTrace();
			return -1;
		}
	}

추가적으로 MongoDB란

C++로 작성된 오픈소스 문서지향(Document-Oriented) 적 Cross-platform 데이터베이스이며, 뛰어난 확장성과 성능을 자랑한다. 또한, 현존하는 NoSQL 데이터베이스 중 인지도 1위를 유지하고있는 DB이다.

MongoDB 공식 홈페이지의 다운로드 페이지에서 MSI 파일로 설치하면

C:\Program Files\MongoDB\Server\3.2\bin\ 에 설치된다.

CMD 창을 열어서 디렉토리로 들어가 mongod 를 실행하면 서버가 실행되게 된다.

기본 데이터베이스 디렉토리가 C:\data\db 이므로 실행 전에 폴더를 수동으로 만들어주어야 한다.


profile
시작은 미약하지만, 그 끝은 창대하리라

0개의 댓글