😵 ~23.11.10/⏩ CodeReview

[ Java ] 코드 리뷰 :: DB를 가변배열에 읽어오기

unikue 2023. 8. 13. 17:13

✅ 구현해본 버전

  1. 기본 배열을 가변배열화 해서 데이터 개수만큼 배열을 늘려나가기
  2. ArrayList를 사용하기

#️⃣ DB를 담을 Member 클래스 정의

import java.util.ArrayList;

public class Member {
	
	private int id;
	private String name;
	private int age;
	
	public Member() {
		super();
	}
	
	public Member(int id, String name, int age) { //getter, setter만 했다가 생성자도 추가해봄
		this.id = id;
		this.name=name;
		this.age=age;
	}
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
}

 

 

 

#️⃣ 1) 기본배열을 가변배열화 하기

1차.

public class Program0810 {

	public static void main(String[] args) throws ClassNotFoundException, SQLException {

		System.out.println("[ 회원 검색 프로그램 ]");
		System.out.println("검색할 이름 : ");

		String searchWord = "";

		// 검색어 입력
		Scanner scan = new Scanner(System.in);
		searchWord = scan.next();
		System.out.println();

		// 검색어를 이용해서 데이터를 가져오기 (변수를 쿼리문에 끼워넣기)
		String url = "url";
		String sql = "SELECT ID,NAME,AGE FROM MEMBER WHERE NAME LIKE '%" + searchWord + "%'";
		Class.forName("oracle.jdbc.driver.OracleDriver");
		Connection con = DriverManager.getConnection(url, "ID", "PW");
		Statement st = con.createStatement();
		ResultSet rs = st.executeQuery(sql);

		// 멤버클래스에 저장하기
		int index = 0;
		Member[] arr = new Member[1]; //최소 개수를 만들어두고 늘려나갈 예정
		
		while(rs.next()) {
			System.out.println("길이1:" +arr.length);
			
			// 인덱스가 다 차면 새로운 배열 만들어서 옮겨주기
			if(index==arr.length-1) {
				Member[] tmp = new Member[arr.length+1];
				
				// 1)새 배열로 내용 복사하기
				for (int i=0; i<arr.length; i++) {
					tmp[i]= arr[i];
				}
				
				// 2)객체 연결하기
				arr=tmp;
				System.out.println("길이2:" +arr.length);
			} //if ends
			
			
			int id = rs.getInt("id");
			String name = rs.getString("name");
			int age = rs.getInt("age");
			
			arr[index] = new Member(id, name, age);
//			arr[index].setId(id);
//			arr[index].setName(name);
//			arr[index].setAge(age);
				
			index++;
		} // while ends
		
		int size =index;
		

		// 출력하기
		System.out.printf("%s\t%-10s\t%-10s\n", "ID", "이름", "나이");

		for (int i = 0; i < size; i++) {
			System.out.printf("%-2d\t", arr[i].getId());
			System.out.printf("%-10s\t", arr[i].getName());
			System.out.printf("%-10d\n", arr[i].getAge());
		}

		rs.close();
		st.close();
		con.close();
	}

}

 

 

👉 원래 while(rs.next())조건 안에서 먼저 데이터를 받고, 그 후에 index가 다 차면 if문을 통해서 배열을 늘리려고 생각을 했었다. 그렇게 되면 (인덱스가 다 찼음 && 다음줄이 있는지 체크) 이 조건이 동시에 들어가야 하는데, 이때 rs.next()로 다음줄을 읽어와버리게 되므로 한줄씩 날아가게 된다. 그래서 hasNext()같은 놈이 있는지 찾아보고 한참을 고민해봤는데... 중복 조건을 쓸 필요가 없다는 생각이 퍼뜩 들어서 if문을 위로 올림.

 

👉 그 결과, 이미 다음값이 있는지 체크하고 while문이 시작되므로 진행에 문제는 없었다!

다만 1줄이라도 데이터가 있는 경우 처음부터 인덱스 0 == 길이-1 이 일치하므로, 멀쩡한 배열을 한번 더 생성해서 복사한다는 단점이 생긴다. 그래서 데이터 개수보다 인덱스가 하나 더 많다. 

 


2차.

public static void main(String[] args) throws ClassNotFoundException, SQLException {

    System.out.println("[ 회원 검색 프로그램 ]");
    System.out.println("검색할 이름 : ");

    String searchWord = "";

    // 사용자 이름의 검색어를 입력하는 코드
    Scanner scan = new Scanner(System.in);
    searchWord = scan.next();
    System.out.println();

    // 검색어를 이용해서 데이터를 가져오기 (변수를 쿼리문에 끼워넣기)
    String url = "url"; // 약속된 사용문장
    String sql = "SELECT ID,NAME,AGE FROM MEMBER WHERE NAME LIKE '%" + searchWord + "%'";
    Class.forName("oracle.jdbc.driver.OracleDriver");
    Connection con = DriverManager.getConnection(url, "id", "pw");
    Statement st = con.createStatement();
    ResultSet rs = st.executeQuery(sql);

    // 1. 멤버클래스에 저장하기
    int index = 0; // 기존배열의 인덱스
    int size = 0; // 새 배열의 인덱스이자 최종 길이
    Member[] arr = new Member[index];

    // 데이터가 있을 시 배열 늘리기
    for (int i = 0; rs.next(); i++) {
        Member[] tmp = new Member[++size];

        // 1)새 배열로 내용 복사하기
        for (int j = 0; j < arr.length; j++) {
            tmp[j] = arr[j];
        }

        // 2)객체 연결하기
        arr = tmp;

        //3) 배열에 데이터 넣기
        int id = rs.getInt("id");
        String name = rs.getString("name");
        int age = rs.getInt("age");

        arr[i] = new Member(id, name, age);
    } // for ends

    // 2. 출력하기
    System.out.println("size"+ size);
    System.out.printf("%s\t%-10s\t%-10s\n", "ID", "이름", "나이");

    if (size == 0)
        System.out.println("데이터가 없습니다");
    else {
        for (int i = 0; i < size; i++) {
            System.out.printf("%-2d\t", arr[i].getId());
            System.out.printf("%-10s\t", arr[i].getName());
            System.out.printf("%-10d\n", arr[i].getAge());
        }
    }
    rs.close();
    st.close();
    con.close();
}

 

👉 인덱스가 하나 더 늘어나는 문제점을 보완하기 위해 다시 짠 코드.

코드공유하면서 얘기를 나누다가 while과 조건(if)를 묶으면 결국 for문이라서 다시 정리했다.

for(int i=0; rs.next(); i++) {} 이걸 왜 생각못해서 굳이 if문으로 인덱스와 길이를 비교하려 했을까.... 덕분에 코드가 한결 간결해짐!

 

 

 

 

#️⃣ 2) ArrayList 활용하기

public class Program0811 {

	public static void main(String[] args) throws ClassNotFoundException, SQLException {

		System.out.println("[ 회원 검색 프로그램 ]");
		System.out.println("검색할 이름 : ");

		String searchWord = "";

		// 사용자 이름의 검색어를 입력하는 코드
		Scanner scan = new Scanner(System.in);
		searchWord = scan.next();
		System.out.println();

		// 검색어를 이용해서 데이터를 가져오기 (변수를 쿼리문에 끼워넣기)
		String url = "url";
		String sql = "SELECT ID,NAME,AGE FROM MEMBER WHERE NAME LIKE '%" + searchWord + "%'";
		Class.forName("oracle.jdbc.driver.OracleDriver");
		Connection con = DriverManager.getConnection(url, "ID", "PW");
		Statement st = con.createStatement();
		ResultSet rs = st.executeQuery(sql);

		// 멤버클래스에 저장하기
		ArrayList<Member> arrList = new ArrayList<Member>();
		int index = 0;

		while(rs.next()) {
			int id = rs.getInt("id");
			String name = rs.getString("name");
			int age = rs.getInt("age");
			
			arrList.add(new Member(id,name,age));
//			list[index].setId(id);
//			list[index].setName(name);
//			list[index].setAge(age);
			
			index++;
		}
		int size =index;
		

		// 출력하기
		System.out.printf("%s\t%-10s\t%-10s\n", "ID", "이름", "나이");

		for (int i = 0; i < size; i++) {
			System.out.printf("%-2d\t", arrList.get(i).getId());
			System.out.printf("%-10s\t", arrList.get(i).getName());
			System.out.printf("%-10d\n", arrList.get(i).getAge());
		}
		rs.close();
		st.close();
		con.close();
	}
}

 

👉 ArrayList를 사용하면 데이터를 읽어오는 족족 배열이 늘어나므로 배열 길이를 직접 늘리려는 수고를 하지 않아도 된다. 제네릭도 잠시 잊고있다가 Member[]과 다르게 ArrayList는 타입을 써줄 공간이 없구나 참 하면서 다시 리마인드 됨. 굿굿

👉 ArrayList에 값을 더할때는 add(), 값을 읽어올때는 get()을 사용한다!!! 그놈의 push, pop좀 잠시 잊어봐

👉list.add(1)로 값을 넣으므로, 아무생각없이 list.add(Member(id,name,age))로 넣었다가 오류가 뜨기에, new가 빠졌다는걸그제서야 알아챘다. new 객체를 바로 때려넣으면 되는구나 싶어서 좀 속시원했음!