국비지원

[JAVA]JDBC - DB Connection 활용

yeon-96 2022. 12. 27. 21:42
반응형

 

JDBC를 활용한 DB와 상호작용

본격적으로 Connection과 Statement를 활용한 DB에서 CRUD를 해보는 연습을 해보자

그 전에 간단하게 close와 Connection, 드라이버 적재를 어떻게 동작하게 할 것인지 먼저 설정하자

1.드라이버 적재는 클래스가 로드되는 동시에 적재되면 되기에 static 블럭을 활용하여 클래스 로드가 되는 동시에 동작되도록 했다.

스태틱블럭

2.다음으로 커넥션을 생성하는 메소드를 만들었다.

커넥션 생성

3. 다음으로 인터페이스를 close할 수 있도록 해주는 메소드도 생성했다.

커넥션,스테이트먼트,리절트셋 close

정의한 메소드들을 라이브러리를 활용하여 타 프로젝트파일에서 사용할 수 있도록 한다.

Create

DB와 연결하여 book테이블을 생성하는 메소드를 만들어보았다.

executeUpdate파라미터에 SQL명령문을 넣어 pk, title, price 컬럼을 갖는 테이블을 만들었다.

executeUpdate는 int값을 반환하는데, 이는 SQL에서 볼 수 있는 명령문이 실행된 후 행의 갯수 값을 반환한다.

 

 

Insert, Delete, Update

[Insert]

위의 Create에서 executeUpdate파라미터에 Insert 명령문을 넣어 insert메소드를 만들어보았다.

컬럼정보를 파라미터를 통해 받아 int값을 반환하도록 만들었다.

public static int insertBook(int no, String title, int price) {
		Connection conn = makeConnection();
		Statement stmt = null;
		try {
			// 명령어(insert into) 수행
			// statement객체는 명령 마무리에 자동으로 세미콜론을 찍어준다.
			stmt = conn.createStatement();
			int result = stmt.executeUpdate(
					"INSERT INTO book (no, title, price) VALUES (" + no + ", '" + title + "', " + price + ");");
			return result;
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			// 접속해제
			closeStatement(stmt);
			closeConnection(conn);
		}
		return 0;
	}

INSERT INTO 명령문을 작성하면된다.

[Delete]

똑같이 pk값을 건네받아 executeUpdate파라미터에 DELETE 명령문과 삭제를 원하는 행의 pk값을 넣게되면 해당 행이 삭제되는 메소드를 만들었다.

public static int deleteBook(int no) {
		Connection conn = makeConnection();
		Statement stmt = null;
		try {
			stmt = conn.createStatement();
			return stmt.executeUpdate("DELETE FROM book WHERE no = " + no + ";");
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			// 접속해제
			closeStatement(stmt);
			closeConnection(conn);
		}
		return 0;
	}

[Update]

public static int updateBook(int no, String newTitle, int newPrice) {
		Connection conn = makeConnection();
		Statement stmt = null;
		try {
			stmt = conn.createStatement();
			return stmt.executeUpdate(
					"UPDATE book SET title = '" + newTitle + "', price = " + newPrice + " WHERE no = " + no + ";");
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			// 접속해제
			closeStatement(stmt);
			closeConnection(conn);
		}
		return 0;
	}

 

 

Select

셀렉트 명령어는 조금 다른 메소드를 활용해야한다.

똑같이 커넥션과 스테이트먼트를 생성하지만 executeQuery메소드를 활용해야한다.

executeQuery는 ResultSet을 반환하며 이 객체에 하나의 행정보가 담기게 된다.

ResultSet클래스의 next메소드는 꺼낼 행이 있다면 true 없다면 false를 반환하며

ResultSet의 getter를 활용해 각각의 컬럼값을 가져 올 수 있다.

나는 각각의 컬럼값을 가져와 java에서 쓸 수 있는 Book객체로 만들어 list에 담아 반환할 수 있도록 메소드를 작성하였다.

public static List<Book> selectAllBook() {
		Connection conn = makeConnection();
		Statement stmt = null;
		ResultSet rs = null;
		List<Book> list = new ArrayList<>();
		try {
			stmt = conn.createStatement();
			rs = stmt.executeQuery("SELECT * FROM book WHERE title = '파워자바';");
			while (rs.next()) {
				int no = rs.getInt("no");
				String title = rs.getString("title");
				int price = rs.getInt("price");
				
				list.add(new Book(no, title, price));
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			closeResultSet(rs);
			closeStatement(stmt);
			closeConnection(conn);
		}
		return list;
	}

 

 

다음과 같이 하나의 컬럼값을 건네받아 해당 컬럼값과 같은 book정보를 확인할수도 있다.

public static List<Book> selectBookByTitle(String t) {
		Connection conn = makeConnection();
		Statement stmt = null;
		ResultSet rs = null;
		List<Book> list = new ArrayList<>();
		try {
			stmt = conn.createStatement();
			// ResultSet = 한 행의 정보를 전달해줌
			rs = stmt.executeQuery("SELECT * FROM book WHERE title = '" + t + "';");
			while (rs.next()) {
				int no = rs.getInt("no");
				String title = rs.getString("title");
				int price = rs.getInt("price");
				
				list.add(new Book(no, title, price));
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			closeResultSet(rs);
			closeStatement(stmt);
			closeConnection(conn);
		}
		return list;
	}

Restaurnat 정보 조회 연습

1. Connection,Statement, ResultSet, List 생성

2. executeQuery로 명령 ("SELECT * FROM restaurant")

3. next메소드로 행정보를 건네받아 각각의 컬럼의 자료형에 맞게 getter호출, 초기화한 컬럼값들을

Restaurant 생성자 파라미터에 넣는다.

4. 생성된 객체를 list에 add한 후 next가 모든 행 정보를 가져왔을 때 list가 반환되게끔 한다.

// 식당 전부 다 조회하기
	public List<Restaurant> selectAll() {
		Connection conn = ConnectionProvider.makeConnection();
		Statement stmt = null;
		ResultSet rs = null;
		List<Restaurant> list = new ArrayList<>();
		try {
			stmt = conn.createStatement();
			rs = stmt.executeQuery("SELECT * FROM restaurant");
			while (rs.next()) {
				int id = rs.getInt("no");
				String name = rs.getString("name");
				String phoneNumber = rs.getString("phoneNumber");
				String address = rs.getString("address");
				double score = rs.getDouble("score");
				list.add(new Restaurant(id, name, phoneNumber, address, score));
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			ConnectionProvider.closeResultSet(rs);
			ConnectionProvider.closeStatement(stmt);
			ConnectionProvider.closeConnection(conn);
		}
		return list;
	}

[집계 식당 총 개수 구하기]

처음 만들었을 때에는 이렇게 모든 행을 구하고 그 list의 size개수를 반환하게끔 만들었는데

rs = stmt.executeQuery("SELECT COUNT(score) FROM restaurant");

int count = rs.getInt(COUNT(score))를 하게되면 집계함수 값이 반환되는 것을 알게 되었다.

명령문을 용도에 맞게 작성하자. 모든 행을 조회하는 것은 용도에 맞지 않다.

[식당 이름으로 검색해서 조회하기]

// 식당 이름으로 검색해서 조회하기
	public List<Restaurant> selectRestaurantByName(String restName) {
		Connection conn = ConnectionProvider.makeConnection();
		Statement stmt = null;
		ResultSet rs = null;
		List<Restaurant> list = new ArrayList<>();
		try {
			stmt = conn.createStatement();
			rs = stmt.executeQuery("SELECT * FROM restaurant WHERE name = '" + restName + "';");
			while (rs.next()) {
				int id = rs.getInt("no");
				String name = rs.getString("name");
				String phoneNumber = rs.getString("phoneNumber");
				String address = rs.getString("address");
				double score = rs.getDouble("score");
				list.add(new Restaurant(id, name, phoneNumber, address, score));
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			ConnectionProvider.closeResultSet(rs);
			ConnectionProvider.closeStatement(stmt);
			ConnectionProvider.closeConnection(conn);
		}
		return list;
	}

[식당 정보가 담긴 list를 건네받아 INSERT해보기]

처음 의도는 list를 건네받아 for문을 활용해 list의 각 index를 Update하는 식으로 접근했었다.

그리고 listsize를 반환하여 몇 행이 추가되었는지 알 수 있도록 해주었다.

public int createValues(List<Restaurant> list) {
		Connection conn = ConnectionProvider.makeConnection();
		Statement stmt = null;
		try {
			stmt = conn.createStatement();
			for (int i = 0; i < list.size(); i++) {
				String name = list.get(i).getName();
				String phoneNumber = list.get(i).getPhoneNumber();
				String address = list.get(i).getAddress();
				double score = list.get(i).getScore();
				stmt.executeUpdate("INSERT INTO restaurant (name, phoneNumber, address, score)" + " VALUES ('" + name
						+ "', '" + phoneNumber + "', '" + address + "', " + score + ")");
			}
			return list.size();
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			ConnectionProvider.closeStatement(stmt);
			ConnectionProvider.closeConnection(conn);
		}
		return 0;
	}

이 방법은 강의실 다른 친구가 생각해낸 방법인데, 인상 깊었다.

foreach문을 활용하였고, 기존에 정의해 둔 create메소드를  list에 객체가 있을 때마다 실행되게끔, 꺼내온 r값은 create파라미터에 들어가도록 만들었다. 훨씬 보기편하고 간결해진 것을 볼 수 있다.

기존 create메소드 정의는 이렇다.

// 식당 행 추가하기
	public int create(String name, String phoneNumber, String address, double score) {
		Connection conn = ConnectionProvider.makeConnection();
		Statement stmt = null;
		try {
			stmt = conn.createStatement();
			return stmt.executeUpdate("INSERT INTO restaurant (name, phoneNumber, address, score)" + " VALUES ('" + name
					+ "', '" + phoneNumber + "', '" + address + "', " + score + ")");
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			ConnectionProvider.closeStatement(stmt);
			ConnectionProvider.closeConnection(conn);
		}
		return 0;
	}

 

반응형