본문 바로가기
꽉java

[JDBC] Java Properties 활용 SQL 쿼리문을 위한 XML 파일 작성

by 박다비 2023. 1. 1.

기존에는 Java의 JDBC에서 dbms에 있는 데이터를 불러올 때 Dao클래스 내에 직접 쿼리문을 작성했다

< String sql = "SELECT * FORM TABLE "; > 식으로 정적 코딩 방식 (하드코딩 방식)으로 쿼리문을 불러왔다. 

 

이 방법은 SQL문을 수정해야 할 경우 자바프로그램에서 소스코드를 직접 수정해야 하기 때문에 , 수정된 내용을 반영시키기 위해서는 프로그램을 정지 시키고 다시 재구동(RUN) 해야한다.  실제 현업에서는 프로그램을 재구동한다는것은 서버를 다운시키는 것과 같은것이기 때문에 불가넝. 

 

때문에 SQL문을 별도로 관리하는 외부파일(XML)을 만들어서 그 파일을 읽어들이는 방식으로 실행해야한다.

이것을 동적 코딩 방식이라고 한다. 외부파일을 읽어들인다는 것은 내부내용(쿼리문,DBMS프로그램, 연결된 계정 등..) 이 변경이 되어도 프로그램이  계속 돌아가면서 새로고침? 방식으로 파일을 실시간으로 계속 읽어들이기 때문에 재구동, 서버다운을 할 필요가 없다. 즉 변경을 해도 파일에 들어가서 바꾸고 파일저장만하면 알아서 잘 적용이 된다.

 

 

xml파일을 resources폴더내에 새로운 xml파일을 만들어서 query.xml 명으로 저장을 했다.

 

java에서 xml 파일 만들기 생성하기
저장된 xml파일

 

driver.properties 파일은 db의 계정 정보와, 드라이버연결 경로가 쓰여있다. 이부분은 중복되는 Connection , Class.forName 을 위해 사용했다.

 

아무튼 이렇게 새로운 xml파일을 생성하게 되면 

<?xml version="1.0" encoding="UTF-8"?> 이런 내용만 쓰인 파일이 생성된다 

xml파일이기 때문에 properties 같은(map타입 키와,벨류값을이용) 효과? 기능? 을 사용할수 있도록

DOCTYPE 을 줘야한다...그럼 걍 properties로 파일을 사용하면 되지 않냐...하지만 properties 파일은 한줄로만 작성이 가능하기 때문에 쿼리문같이 긴 문장을 사용하려면 xml파일을 사용해야한다

 

<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>

 

</properties>

 

이렇게 적으면됨!

그럼 이제 properteis 태그 안에 이제 entry태그로 sql문을 작성하면된다

이..런 코드? 태그?는 어떻게 알았냐면...! 선생님이 알려줬다..

저부분을 Mybaties..?로 사용하는 코드들이 많지만...우린 아직 그걸 안배웠어요!

오직 자바와 , oracle dbms만 배우고 둘을 연결하고 있습니다.

 

properties 파일의 특징은 key 와 values 값이 따로 있고

java 코드에서 key값을 부르면 valuues 값이 반환된다는 특징이있다.

 

 

그럼이제 이 xml파일에서 쿼리문 작성을 어떻게 하냐!

기존에 dao에서 String sql = "쿼리문"; 썼던거랑 똑같이쓰면된다

dao에서 쓸 때는 PreparedStatement 객체를 사용해  쿼리문에서 ?  물음표를 이용해서 쿼리를 작성했는데 

그냥 똑같이 쓰면 됨~!

 

 

제일 간단한 DELETE 문을 써야한다고 하면 기존에는 Dao 클래스에 

String sql =  "DELETE FROM MEMBER WHERE USERID = ?";  

(MEMBER 테이블의 USERID가 사용자가 입력한 USERID랑 같으면 데이터삭제) 

이런식으로 썼다면 , 쌍따움표 안에 썼던 쿼리문을 그냥 XML파일에 쓰면 된다.

 

<entry key = "dao에서 호출할 key 이름(sql문이름)">

~~~~~sql문 ~~~~~

</entry>

 

entry 태그는 ctrl + space 하면 자동생성문으로 작성 가능함!

 

쓰면됨.

entry 태그 안에 들어가야 ~~~sql문~~~~ 내용은

String sql = "   ";   의 쌍 따움표안에 들어갈 내용을 그냥  xml entyr 태그 내에 고~대로 쓰면된다.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
	<entry key="deleteMember">
		DELETE 
		  FROM 
		  	  MEMBER 
		 WHERE 
		 	  USERID = ?
	</entry>
    
    
	<entry key="selectList">  
    <!-- select* 을 쓰면..속도가 느려짐, 명식적으로 컬럼제시해야함  -->
		SELECT
			  USERNO
 			, USERID
 			, USERPWD
 			, USERNAME
 			, GENDER
 			, AGE
 			, EMAIL
 			, PHONE
 			, ADDRESS
 			, HOBBY
 			, ENROLLDATE
		 FROM MEMBER 
		ORDER BY AGE
	
	</entry>
</properties>

줄바꿈이 많은이유? 알아보기 쉽게하기위해 

 

 

 

그럼 이렇게 쓴걸 어떻게 사용을 하냐?

 

일단 이 xml문과 Properties 객체와 연결을 해야겠쥬....

Dao 클래스에 전역으로 prop이란 변수명으로 Properties 객체를 하나 생성하고

 

prop에 loadFromXML함수로 연결을 해주면 된다.

prop.loadFromXML(new FileInputStream("resources/query.xml"));

근데 이 코드를 Dao의 기본생성자 안에 넣어서, 다른 클래스에서 Dao클래스를 호출할때마다, 새로 로드하는 방식으로 작성할 수 있다. 

 

 

이렇게 전역으로 Properties를 선언해두고

 

 

 

각 메소드의 String sql = "   "; 안에 쿼리문대신 prop 객체를 활용하면된다.

왜냐면 prop객체안에는 우리가 작성한 쿼리문들이 있기 때문.

이제 우리는 위에 미리 생성한 Properties객체를 호출해  prop의 get함수로 key명을 입력해 반환받으면된다.

String sql = "prop.getProperty("key이름");

=> String sql = prop.getProperty("deleteMember"); 

이 key이름은 우리가 xml문에 작성해놓은 다양한 쿼리문의  key이름이다.

 

 

그 이외에는 properties를 사용하기 전의   코드와 별반다를게 없다

 

Dao클래스 파일

 

public clss MemberDao{



	private Properties prop = new Properties(); //프로퍼티즈 객체생성
	
    
	public MemberDao() { 
		try {
				prop.loadFromXML(new FileInputStream("resources/query.xml"));
			} catch (IOException e) {
				e.printStackTrace();
			}
        
	} //MemberDao의 기본생성자로, MemberDao호출시 자동으로 실행됨. 쿼리문을 실행할때마다 새로 불러옴(새로고침효과)
	
    
    
    
    //delete문 
    public int deleteMember(Connection conn, String userId) {  //사용자에게 삭제할 유저아이디를 받아서가져옴
		
        
		int result = 0;
		PreparedStatement pstmt = null;
		
		String sql = prop.getProperty("deleteMember"); 
        //xml에 작성한 key가 deleteMember 인 value를 가져와서 sql에 저장
		
		try {
			pstmt = conn.prepareStatement(sql);
			pstmt.setString(1, userId);
			result = pstmt.executeUpdate();
			//트랜젝션처리는 서비스에서 
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			/*JDBCTemplate.*/close(pstmt);
            //comm은 아직 반납하면 안됨! (트랜젝션 처리때 필요하기 때문) 
		}
		return result;
	}
    
    
    
    //seletList문  (전체조회) 
    public ArrayList<Member> selectList(Connection conn){
	
    
		ArrayList<Member> list = new ArrayList<Member>();
		PreparedStatement pstmt = null;
		ResultSet rset = null;
        
		String sql =prop.getProperty("selectList");
		
		try {
			pstmt = conn.prepareStatement(sql);
			
			rset = pstmt.executeQuery();
			
			while(rset.next()) {
				list.add(new Member(rset.getInt("userno"),
									rset.getString("userid"),
									rset.getString("userpwd"),
									rset.getString("username"),
									rset.getString("gender"),
									rset.getInt("age"),
									rset.getString("email"),
									rset.getString("phone"),
									rset.getString("address"),
									rset.getString("hobby"),
									rset.getDate("enrolldate")
									));
		
			}
			
		} catch (SQLException e) {
			e.printStackTrace();
		}finally {
			close(rset);
			close(pstmt);
		}	
		return list;		
	}
        
}