본문 바로가기

데이터베이스

데이터베이스 연결, close,thread, 동기 /비동기

 try 
 
 	DB Connection
    
catch

	조회가 안됨 
    
finally 

     DB.close 

위와 같이 db.close()는 finally 구문에 넣어주는것이 좋습니다. 

예를 들어 close 는 이전 포스팅의 예에서 들었던 

화장실이라고 해봅시다

 

만약 수많은 db들을 열고 catch에서 일일이 다 close를 잡아주어야 한다면 어떨까요?

너무 복잡하겠지요?

 

buffer와 flush()는 수동으로 화장실물을 내리는거였지만

close는 그 공간 자체를 나오는것을 말합니다.

 

그러니까 화장실에서 어떤 자원을 할당받고 어떤일을 하든

나올때는 무조건 그냥 한번만 전체다 close 시켜주면

화장실문들을 일일이 close 시켜주지 않아도 된다는 편리성이 있는거에요~ !! 

 

package org.techtown.diary_20191225;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

import java.util.ArrayList;


public class DBHelper extends SQLiteOpenHelper{
    public static String NAME="diary.db";
    public static int VERSION=1;
    public static String USER_TABLE_NAME="user";
    public DBHelper(Context context){
        super(context,NAME,null,VERSION);
    }



    @Override
    public void onCreate(SQLiteDatabase db) {

        String sql="CREATE TABLE IF NOT EXISTS user("+
                "id TEXT PRIMARY KEY,"+
                "password TEXT,"+
                "name TEXT,"+
                "birth TEXT,"+
                "email TEXT )";

        db.execSQL(sql);
    }

    public void insertUser(User user){

        SQLiteDatabase db=this.getWritableDatabase();
        ContentValues values=new ContentValues();
        values.put("id",user.getId());
        values.put("password",user.getPw());
        values.put("name",user.getName());
        values.put("birth",user.getBirth());
        values.put("email",user.getEmail());

        db.insert(USER_TABLE_NAME,null,values);
        db.close();
    }

    public ArrayList<User> getAllUser(){

        ArrayList<User> UserList= new ArrayList<User>();
        String selectQuery="SELECT * FROM "+ USER_TABLE_NAME;

        SQLiteDatabase db=this.getWritableDatabase();
        Cursor cursor=db.rawQuery(selectQuery,null);

        if(cursor.moveToFirst()){
            do{
                User user=new User();
                user.setId(cursor.getString(0));
                user.setPw(cursor.getString(1));
                user.setName(cursor.getString(2));
                user.setBirth(cursor.getString(3));
                user.setEmail(cursor.getString(4));
                UserList.add(user);

            }while(cursor.moveToNext());
        }

        return UserList;
    }



    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        if(newVersion >1){
            db.execSQL("DROP TABLE IF EXISTS user");
        }
    }
}

그리고 위 코드를 보시면 rawQuery라고 나와있는데 이게 무슨 역할을 하는지 볼까요~ 

 

package jdbc0102;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class Test01_selectOne {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		
		Connection con= null;
		PreparedStatement pstmt=null;
		//select 문 실행 시 반환 
		ResultSet rs=null;
		
		try {
			String url     ="jdbc:oracle:thin:@localhost:1521:xe";
		      String user    ="system";
		      String password="1234";
		      String driver  ="oracle.jdbc.driver.OracleDriver";//ojdbc.jar  
		      Class.forName(driver);
		      con=DriverManager.getConnection(url, user, password);
		      System.out.println("오라클 DB 서버 연결 성공");
		      
		      StringBuilder sql=new StringBuilder();
		      sql.append(" SELECT sno,uname,kor,eng,mat,tot,aver,addr,wdate ");
		      sql.append(" FROM sungjuk ");
		      sql.append(" WHERE sno=? ");
		      
		      //sno=22 행 조회하기
		      pstmt=con.prepareStatement(sql.toString());
		      pstmt.setInt(1, 22);
		      
		      //DML (insert,update,delete)
		      //int cnt=pstmt.executeUpdate();
		      
		      //select문 실행 
		      rs=pstmt.executeQuery();
		      //cursor: 현재 가리키는 값. 이동할 수 있다 .
		      if(rs.next()) { // cursor가 존재하는지 ? 
		    	  System.out.println("자료 있음 ! ");
		    	  
		    	  //1)칼럼 순서
		    	  // ->> select 칼럼 1번 , 칼럼 2번 ~~~
		    	  System.out.print(rs.getInt(1)+ " "); // sno칼럼 
		    	  System.out.print(rs.getString(2)+ " "); // uname칼럼 
		    	  System.out.print(rs.getInt(3)+ " "); // kor칼럼 
		    	  System.out.print(rs.getInt(4)+ " "); // eng칼럼 
		    	  System.out.print(rs.getInt(5)+ " "); // mat칼럼 
		    	  System.out.print(rs.getInt(6)+ " "); // tot칼럼 
		    	  System.out.print(rs.getInt(7)+ " "); // aver칼럼
		    	  System.out.print(rs.getString(8)+ " "); // addr칼럼 
		    	  System.out.print(rs.getString(9)+ " "); // wdate칼럼
		    	  
		    	  
		    	  //2) 칼럼명
		    	  
		    	  System.out.print(rs.getInt("sno")+ " "); // sno칼럼 
		    	  System.out.print(rs.getString("uname")+ " "); // uname칼럼 
		    	  System.out.print(rs.getInt("kor")+ " "); // kor칼럼 
		    	  System.out.print(rs.getInt("eng")+ " "); // eng칼럼 
		    	  System.out.print(rs.getInt("mat")+ " "); // mat칼럼 
		    	  System.out.print(rs.getInt("tot")+ " "); // tot칼럼 
		    	  System.out.print(rs.getInt("aver")+ " "); // aver칼럼
		    	  System.out.print(rs.getString("addr")+ " "); // addr칼럼 
		    	  System.out.print(rs.getString("wdate")+ " "); // wdate칼럼
		    	  
		    	  
		    	  
		      }else {
		    	  System.out.println("자료 없음 ! ");
		      }
		      
		      
		      
		      
		}catch(Exception e) {
			System.out.println("실패 : "+ e);
		}finally {
			
			try {
				if(rs!=null)
				rs.close();
				rs=null;
			} catch (Exception e) {}
			
			try {
				if(pstmt!=null)
				pstmt.close();
				pstmt=null;
			} catch (Exception e) {}
			
			try {
				if(con!=null)
				con.close();
				con=null;
			} catch (Exception e) {}
		}
		
	}

}

  위 코드에서는 preparestatement와 비슷한 역할을하고있는건데요~ 

 

JAVA                                                

STRING                           SQL            

SELECT                                

DB ------------------DB

 

 

이렇게 외부 DB랑 연결하고잇는역할을 하는것이 preparestatment이고 

rawquery 입니다.

 

 

public void serverCreate() {
        Collections.synchronizedMap(clientsMap);
        try {
            serverSocket = new ServerSocket(7777);
            new Thread(new Runnable() {
                @Override
                public void run() {
                    while (true) {
                        /** XXX 01. 첫번째. 서버가 할일 분담. 계속 접속받는것. */
                        Log.v("", "서버 대기중...");
                        try {
                            socket = serverSocket.accept();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        Log.v("", socket.getInetAddress() + "에서 접속했습니다.");
                        msg = socket.getInetAddress() + "에서 접속했습니다.\n";
                        handler.sendEmptyMessage(SERVER_TEXT_UPDATE);

                        new Thread(new Runnable() {
                            private DataInputStream in;
                            private DataOutputStream out;
                            private String nick;

                            @Override
                            public void run() {

                                try {
                                    out = new DataOutputStream(socket.getOutputStream());
                                    in = new DataInputStream(socket.getInputStream());
                                    nick = in.readUTF();
                                    addClient(nick, out);

                                } catch (IOException e) {
                                    e.printStackTrace();
                                }

                                try {// 계속 듣기만!!
                                    while (in != null) {
                                        msg = in.readUTF();
                                        sendMessage(msg);
                                        handler.sendEmptyMessage(SERVER_TEXT_UPDATE);
                                    }
                                } catch (IOException e) {
                                    // 사용접속종료시 여기서 에러 발생. 그럼나간거에요.. 여기서 리무브 클라이언트 처리 해줍니다.
                                    removeClient(nick);
                                }


                            }
                        }).start();
                    }
                }
            }).start();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

여기 이부분을 보시면 

스레드 안에 스레드가 들어간 것을 확인할 수 있습니다.

 

thread A        thread B 

 

 

accept               닉네임

                              채팅

            

 

 

threadA가 accept되면 thread B에서

닉네임을 받고 채팅도 할 수 있도록 짜보았습니다.

 

 

 

참고 

 

동기 비동기 처리도 있는데요 

 

package io_stream;

import java.net.ServerSocket;
import java.net.Socket;
import java.util.Vector;

public class ServerEx4 {
	private Vector handlers;
	public ServerEx4(int port) {
		try {
			ServerSocket server= new ServerSocket(port);
			handlers=new Vector();
			System.out.println("ServerEx4 is ready.");
			
			while(true) {
				Socket client=server.accept();
				ChatHandler c=new ChatHandler(this,client);
				c.start();
			}
			
		}catch(Exception e) {}
	}
	
	public Object getHandler(int index) {
		return handlers.elementAt(index); // Ư���� ����ϰ� �޽��� ���� �� 
	}
	
	public void register(ChatHandler c) {
		handlers.addElement(c);
	}
	
	public void unregister(Object o) {
		handlers.removeElement(o);
	}
	public void broadcast (String message) {
		synchronized(handlers) {
			int n=handlers.size();
			for (int i=0; i<n; i++) {
				ChatHandler c= (ChatHandler) handlers.elementAt(i);
				c.println(message);
			}
		}
	}
	
	public static void main(String[] args) {
		new ServerEx4(9830);
	}

}

위 예제는 브로드 캐스트 될때  동기화 처리를 해준 코드 입니다.

브로드 캐스트할때는 다른 작업이 처리 되지 못하도록 코드를 작성한 것인데요~

비동기 처리를 해줄 수도 있겠죠~ ?

 

예를 들어 옥돌이가 강아지와 고양이 둘 다 키운다고 해봅시다

같은 화장실안에서 

강아지 가 변기에서 메모리를 할당받고 있다고 하더라도

강아지 친구 고양이는 별개로 샤워하기 메모리를 할당 받을 수있겠죠 ??

 

마찬가지 동기 , 비동기 처리는 같은 공간안에서

개발자의 마음대로 처리해주면 되는것입니다.