190612,13 Day43,44 <로그인, 회원가입 DB>
유효성 검사 마무리-42일차에 추가수정
<로그인과 회원가입>
View
LoginForm( 로그인폼 )
tf_id
tf_pass
bt_login
bt_join
JoinForm
tf_id
tf_pass
tf_pass2
tf_name
tf_ssn1
tf_ssn2 => JPasswordField
tf_phone1
tf_phone2
tf_phone3
tf_addr
cb_job
bt_submit 등록버튼
bt_reset 취소버튼
bt_checkid 중복확인버튼
UpdateForm ( 회원정보수정폼 )
: 타이틀 = > 회원정보수정
: id, 이름, 주민번호의 편집불능
: 중복확인 버튼 제거
ServiceForm (서비스창) => 로그인 성공시 보여지는 서비스폼
: id, 이름, 나이, 성별, 전화번호, 주소, 직업 출력
: 보기버튼 ===> 전체보기, 수정, 삭제, 이름검색 으로!
: JTable table, DefaultTableModel dtm
: bt_sel_all, bt_up, bt_del,
bt_sel_name, bt_exit
Model (j0621.model.vo, j0612.model.dao)
- MembershipVO : DB(테이블)에 있는 (한 개의) 레코드를 표현하는 객체!
- MembershipDAO(추가, 삭제, 수정, 조회)
- create, remove, modify, find, findAll
<작업순서>
시작뷰는 로그인폼
- Controller에 뷰 등록
- LoginForm만 setVisible(true)
회원가입
LoginForm의 '신규가입' 버튼 클릭으로 JoinForm이동
JoinForm 입력값 얻기
입력값을 Membership으로 묶어주기
MembershipDao : insert()호출
=> DB입력
입력성공 또는 실패 메시지 후 성공 LoginForm으로 이동.
로그인
- LoginForm 입력값(아이디,비밀번호) 얻기
- MembershipDAO : findLogin()호출
---> DB조회
- 아이디와 비밀번호 일치시 '로그인성공!!' 후 ServiceForm 이동.
불일치시 '로그인실패!!'메시지 출력.
서비스폼
- 회원정보 출력
- LoginForm => ServiceForm 이동 시 전체 회원정보 JTable에 출력
- ServiceForm에서 '전체보기'버튼 클릭시 전체 회원정보 JTable에 출력
- ===> MembershipDAO : findAll()의 결과값을 통해!!
---> DB조회
UI MembershipDAO DB테이블
액션 ArrayList
findAll() membership (회원정보) ---> select
from각행 --> 회원한명 where X ---
VO
준비:
ArrayList에 저장된
데이터를 출력할 컴포넌트!! ----> JTable
[회원가입폼의 직업샘플]
"학생","공무원","언론/출판","군인/경찰","일반사무직",
"영업직","기술/전문직","보건/의료","자영업","주부","기타"
서비스폼(JTable): 회원정보 수정
5-1. ==> 이전에 저장된 (특정회원)데이터 조회!!- 입력대화상자 통해 수정 아이디 입력!!
- MembershipDAO : findById()
--->예상sql? select ~ from ~ where id=? findById(String id) <===파라미터 VO findById(String id) <===리턴
- 리턴데이터를 출력할 UI ---> 수정폼 (UpdateForm)
5-2. ==> 이전데이터 수정!!===> 뷰 이동 (서비스폼 ---> 수정폼)
- 아래 SQL에 필요한 데이터 ==> getText() : 서비스폼으로 부터
- MembershipDAO : modify()
modify(VO) <==== 매개변수---> 예상sql? update ~ set addr=? job=? .... where id=?
boolean modify(VO) <==== 리턴 - 리턴에 의한 뷰이동 : 서비스폼 이동(수정 성공시) 또는 수정폼에 머무르기(수정 실패시)
서비스폼(JTable) : 회원삭제(탈퇴)
MembershipDao : remove()호출
> 예상되는 sql?
delete from where id = ?
remove(String id) <=== 매개변수
boolean remove(String id) <==리턴
리턴에 의한 뷰이동 : 서비스폼에서 상황 메시지 출력 (성공시 JTable에 데이터 반영)
서비스폼 (JTable) : 이름검색 (입력된 문자를 포함하는)
입력대화상자 통해 조회 이름 입력!!
MembershipDAO : findByName()호출
> 예상되는 sql?
select ~ from ~
where name like ?
findByName(String name) <=매개변수
ArrayList
findByName(String name) <= 리턴 - 리턴에 의한 뷰 이동 : 서비스폼에서 상황 데이터 출력(성공시 JTable에 데이터 반영)
회원정보 입력(회원가입창) : 중복확인!! (중복아이디체크)
※ 중복 체크할 아이디 얻기
첫번째 방법) joinForm의 '등록'버튼 클릭시' 또는 joinForm의 '중복확인'버튼 클릭시 ==> 회원가입폼.tf_id.getText() 이용하여 중복검사 두번째 방법) '중복확인' 버튼 클릭시 ==> 새로운 프레임 오픈 예) class CheckId extends JFrame{ JTextField tf_id; JButton bt_confirm;//확인
CheckId(){
setTitle("중복확인");
setLayout(new FlowLayout()); add(tf_id);
add(bt_confirm);
}
} ==> 입력대화상자 사용
예) String id = JOptionPane.showInputDialog("아이디입력");
세번째방법)
JoinForm에서 '중복확인'버튼 제거
JoinForm의 tf_id에 keyListener를 적용
==> 문자입력될때마다 중복체크해서 결과 보이기MembershipDAO : findExistId()
예상sql? select count(*) from ~
where id=?
findExistId(String id) <=== 파라미터
int findExistId(String id) <=== 리턴 0,1
//---------------------------------------------------------
코드
DAO
public class MembershipDAO
{
Connection conn;
// Statement stmt;
PreparedStatement stmt;
ResultSet rs;
Properties pro;// DB접속관련 정보 저장 객체
public MembershipDAO()
{
try
{
pro = new Properties();// 속성 담는 객체 (속성0개)
pro.load(new FileReader("conn/conn.properties"));
// 속성driver,url,user,password 적재 (속성4개)
Class.forName(pro.getProperty("driver"));
} catch (FileNotFoundException e)
{
e.printStackTrace();
} catch (ClassNotFoundException e)
{
e.printStackTrace();
} catch (IOException e)
{
e.printStackTrace();
}
}// 생성자
//수정 폼에 입력된 데이터로 DB데이터 갱신(재입력)
public boolean modify(MembershipVO vo)
{
connect();
try
{
String sql = " update membership set pass = ? , phone = ?, addr = ?, job = ?" + "where id = ?";
stmt = conn.prepareStatement(sql);
stmt.setString(1, vo.getPass());
stmt.setString(2, vo.getPhone());
stmt.setString(3, vo.getAddr());
stmt.setString(4, vo.getJob());
stmt.setString(5, vo.getId());
int t = stmt.executeUpdate(); // sql실행 요청
if( t == 1 ) return true; // t : 수정된 행의 갯수
} catch (SQLException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}finally
{
disconnect();
}
return false;
}
// public boolean remove(String id) // 선택 삭제
// {
// connect();
//
// try
// {
// String sql = " delete from membership where id = '" + id + "'";
// stmt = conn.prepareStatement(sql); // sql전송
// stmt.setString(1, id);
// int t = stmt.executeUpdate(); // sql실행 요청
// if( t == 1 ) return true; // t : 수정된 행의 갯수
// } catch (SQLException e)
// {
// e.printStackTrace();
// }finally
// {
// disconnect();
// }
//
//
// return false;
//
// }
public boolean remove(String id) {
connect();
try {
String sql="delete from membership where id=?";
stmt = conn.prepareStatement(sql);//sql전송
stmt.setString(1, id);
int t =stmt.executeUpdate();//sql실행요청
if(t==1) return true;//t:수정된 행의 갯수
} catch (SQLException e) {
e.printStackTrace();
} finally {
disconnect();
}
return false;
}//remove
// (전체)회원 정보 조회
public ArrayList<MembershipVO> findAll()
{
connect();
ArrayList<MembershipVO> list = new ArrayList<MembershipVO>();
// 컬럼: id,pass,name,ssn1,ssn2,phone,addr,job
try
{
String sql = "select id,name,ssn1,ssn2,phone,addr,job from membership";
stmt = conn.prepareStatement(sql);// sql문 전송
rs = stmt.executeQuery();// sql문 실행요청(실행시점!!)
// 덩어리
while (rs.next())
{// 행얻기
// 열데이터 얻기
MembershipVO vo = new MembershipVO();
// 7개의 관련있는 속성데이터를 묶어주기 위해 사용.
vo.setId(rs.getString("id"));
vo.setName(rs.getString("name"));
vo.setSsn1(rs.getInt("ssn1"));
vo.setSsn2(rs.getInt("ssn2"));
vo.setPhone(rs.getString("phone"));
vo.setAddr(rs.getString("addr"));
vo.setJob(rs.getString("job"));
list.add(vo);
} // while
} catch (SQLException e)
{
e.printStackTrace();
} finally
{
disconnect();
}
return list;
}// findAll
public ArrayList<MembershipVO> findByName(String name)
{
connect();
ArrayList<MembershipVO> list = new ArrayList<MembershipVO>();
// 컬럼: id,pass,name,ssn1,ssn2,phone,addr,job
try
{
String sql = "select id,name,ssn1,ssn2,phone,addr,job from membership where name like ?";
stmt = conn.prepareStatement(sql);// sql문 전송
stmt.setString(1, "%" + name + "%");
rs = stmt.executeQuery();// sql문 실행요청(실행시점!!)
// 덩어리
while (rs.next())
{// 행얻기
// 열데이터 얻기
MembershipVO vo = new MembershipVO();
// 7개의 관련있는 속성데이터를 묶어주기 위해 사용.
vo.setId(rs.getString("id"));
vo.setName(rs.getString("name"));
vo.setSsn1(rs.getInt("ssn1"));
vo.setSsn2(rs.getInt("ssn2"));
vo.setPhone(rs.getString("phone"));
vo.setAddr(rs.getString("addr"));
vo.setJob(rs.getString("job"));
list.add(vo);
} // while
} catch (SQLException e)
{
e.printStackTrace();
} finally
{
disconnect();
}
return list;
}// findByName
// 회원가입: UI에 입력된 데이터들을 DB테이블에 저장!!
public boolean create(// String id,String pass,String name,int ssn1,int ssn2,String phone,String
// addr,String job
MembershipVO vo)
{
connect();
// 컬럼: id,pass,name,ssn1,ssn2,phone,addr,job
try
{
String sql = "insert into membership (id,pass,name,ssn1,ssn2,phone,addr,job) " + "values (?,?,?,?,?,?,?,?)"; // ?:바인드변수,
// 데이터
// 채우기
stmt = conn.prepareStatement(sql);// (데이터를 제외한)sql문을 DB에 전송
stmt.setString(1, vo.getId());
stmt.setString(2, vo.getPass());
stmt.setString(3, vo.getName());
stmt.setInt(4, vo.getSsn1());
stmt.setInt(5, vo.getSsn2());
stmt.setString(6, vo.getPhone());
stmt.setString(7, vo.getAddr());
stmt.setString(8, vo.getJob());
stmt.executeUpdate();// 전송된 sql문에 대해 실행요청!!
return true;
} catch (SQLException e)
{
e.printStackTrace();
} finally
{
disconnect();
}
return false;
}// create
// 회원정보 수정(폼)에 필요한 데이터 조회(검색)
// 컬럼: id,pass,name,ssn1,ssn2,phone,addr,job
public MembershipVO findById(String id)
{
connect();
MembershipVO vo = null;// 조회된 결과행이 없음을 표현
try
{
String sql = "select id,pass,name,ssn1,ssn2,phone,addr,job from membership " + "where id=?";
stmt = conn.prepareStatement(sql); // sql문 전송
stmt.setString(1, id);
rs = stmt.executeQuery();// 전송sql문에 대한 실행 요청
if (rs.next())
{// 아이디에 일치하는 행이 존재한다면
vo = new MembershipVO(rs.getString("id"), rs.getString("pass"), rs.getString("name"), rs.getInt("ssn1"),
rs.getInt("ssn2"), rs.getString("phone"), rs.getString("addr"), rs.getString("job"));
}
} catch (SQLException e)
{
e.printStackTrace();
} finally
{
disconnect();
}
return vo;
}// findById
public boolean findLogin(String id, String pass)
{
connect();
/*
* select count(*) from emp; (O) select deptno, count(*) from emp; (X) select
* deptno, count(*) from emp group by deptno; (O) select decode(1,2,3), count(*)
* from emp; (X) select decode(1,2,3), count(*) from emp group by decode(1,2,3);
* (O)
*/
try
{
// stmt = conn.createStatement();
String sql = "select count(*) from membership where id=? and pass=?";
stmt = conn.prepareStatement(sql); // DB에 sql문 전송 ==> DBMS에서 파싱
stmt.setString(1, id);// 1: 첫번째 물음표
stmt.setString(2, pass);// 2: 두번째 물음표
// String sql="select count(*) from membership where id='gildong' and
// pass='1234'";
// String sql="select count(*) cnt from membership where id='"+id
// +"' and pass='"+pass+"'";
System.out.println("로그인 SQL>>>" + sql);
// rs = stmt.executeQuery(sql);//(조회)sql문 실행요청
rs = stmt.executeQuery();// 왜? 이미 위에서 sql문을 전송했으므로 중복해서 전송X
if (rs.next())
{
// rs.getInt("count(*)") ==> (O)
// rs.getInt("cnt") ==> (O)
int cnt = rs.getInt(1);
if (cnt > 0)
return true;
}
} catch (SQLException e)
{
e.printStackTrace();
} finally
{
disconnect();
}
return false;
}// findLogin
public void checkId(String id)
{
}
public String findLogin2(String id, String pass)
{
/*
* <비권장> String sql="select * from membership"; ---> 만약 회원의 수의 10만이면 얻어오는 행의 수도
* 10만!!
*
* String sql="select * from membership where id=id and pass=pass"; ---> 필요한
* 데이터는 id와 pass(2개)인데 '*'를 통해 불필요한 컬럼(6개)도 조회!!
*
* String
* sql="select id,pass from membership where id='gildong' and pass='1234'"; --->
* 'gildong','1234' 데이터에 일치하는 조회 결과도 'gildong','1234'
*
* <양호> String sql="select pass from membership where id='gildong'"; ---> 아이디에
* 일치하는 pass정보를 DB로 부터 조회 ---> 장점) 아이디가 존재하는지 여부 비밀번호가 일치하는지 여부를 자세히 파악하기에 좋다!!
* <권장> String sql="select count(*) from membership where id=id and pass=pass";
*
*/
// String sql="select pass from membership where id='gildong'";
connect();
try
{
// stmt = conn.createStatement();
String sql = "select pass from membership where id='" + id + "'";
System.out.println("로그인SQL>>>" + sql);
rs = stmt.executeQuery(sql);// sql문 DB전달, sql문 실행요청!!==> DBMS에서 파싱
if (rs.next())
{
// 아이디 존재 O
String dpass = rs.getString("pass");
// dpass:DB에 저장된 비번 , pass:UI통해 전달된 비번
if (dpass.equals(pass))
{
// 1. 아이디 존재O, 비번 일치O
return "success";
} else
{
// 2. 아이디 존재O, 비번 일치X
return "fail_pass";
}
} // else {
// 3. 아이디 존재 X
// return "fail_id";
// }
} catch (SQLException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
} finally
{
disconnect();
}
// 3. 아이디 존재 X
return "fail_id";
}// findLogin2
private void connect()
{// 연결객체생성
try
{
conn = DriverManager.getConnection(pro.getProperty("url"), pro);
} catch (SQLException e)
{
e.printStackTrace();
}
}
private void disconnect()
{// DB자원반환
try
{
if (conn != null)
conn.close();
} catch (SQLException e)
{
e.printStackTrace();
}
}
}// MembershipDAO
Controller
public class Controller implements ActionListener
{
LoginForm loginForm; // 시작뷰
JoinForm joinForm;
UpdateForm updateForm;
ServiceForm serviceForm;
public Controller()
{
loginForm = new LoginForm();
joinForm = new JoinForm();
updateForm = new UpdateForm();
serviceForm = new ServiceForm();
eventUp();
}// 생성자
private void eventUp()
{// 이벤트 소스 등록
// 로그인폼
loginForm.bt_login.addActionListener(this);
loginForm.bt_join.addActionListener(this);
loginForm.tf_pass.addActionListener(this);
// 회원가입폼
joinForm.bt_submit.addActionListener(this);
joinForm.addWindowListener(new WindowAdapter()
{
// 회원가입폼X버튼 ----> 로그인 폼
public void windowClosing(WindowEvent e)
{
joinForm.setVisible(false);
loginForm.setVisible(true);
}
});
// 서비스폼
serviceForm.bt_sel_all.addActionListener(this);
serviceForm.bt_up.addActionListener(this);
serviceForm.bt_del.addActionListener(this);
serviceForm.bt_sel_name.addActionListener(this);
serviceForm.bt_exit.addActionListener(this);
serviceForm.addWindowListener(new WindowAdapter()
{
// 서비스폼X버튼 ----> 로그인 폼
public void windowClosing(WindowEvent e)
{
serviceForm.setVisible(false);
loginForm.setVisible(true);
}
});
// 회원수정폼
updateForm.bt_submit.addActionListener(this);
updateForm.addWindowListener(new WindowAdapter()
{
// 회원수정폼X버튼 ----> 로그인 폼
public void windowClosing(WindowEvent e)
{
updateForm.setVisible(false);
serviceForm.setVisible(true);
}
});
}// eventUp
@Override
public void actionPerformed(ActionEvent e)
{
Object ob = e.getSource();// 이벤트 발생시킨 컴포넌트의 주소
if (ob == loginForm.bt_login || ob == loginForm.tf_pass)
{
// 1. 로그인폼: 로그인버튼 클릭 ==> DB로그인조회 , 서비스폼으로 이동
// 2. UI입력 데이터 얻기
String id = loginForm.tf_id.getText();
String pass = new String(loginForm.tf_pass.getPassword());
// --------------------------------
// char []
/*
* str.toCharArray() str.getBytes() <--------------- ------------> char []ch
* String str="abc" byte []b {'a','b','c'} {97,98,99} ------------->
* <------------ String s1 =new String(ch); String s2 = new String(b); ---- ---
* "abc" "abc"
*
*/
// 3. 모델호출
MembershipDAO dao = new MembershipDAO();
if (dao.findLogin(id, pass))
{
loginForm.showMsg("로그인성공^O^*");
serviceForm.displayTable(dao.findAll());
loginForm.setVisible(false);
serviceForm.setVisible(true);
} else
{
// loginForm.showMsg("로그인실패T.T*");
loginForm.showMsg("아이디 또는 비밀번호가 일치하지 않습니다!!");
}
// String result = dao.findLogin(id, pass);
// if(result.equals("success")) {
// loginForm.showMsg("로그인성공^O^*");
// }else if(result.equals("fail_id")) {
// loginForm.showMsg("아이디가 존재하지 않습니다!!");
// //confirm("회원가입하시겠습니까?");
// }else if(result.equals("fail_pass")) {
// loginForm.showMsg("비밀번호가 일치하지 않습니다!!");
// }
// 4. 서비스폼 이동
} else if (ob == joinForm.bt_submit)
{// 회원가입폼: 등록버튼 클릭시
// 컬럼: id,pass,name,ssn1,ssn2,phone,addr,job
// UI에 입력된 데이터 수집!!
String id = joinForm.tf_id.getText();
String pass = new String(joinForm.tf_pass.getPassword());
String name = joinForm.tf_name.getText();
String ssn1 = joinForm.tf_ssn1.getText();
String ssn2 = new String(joinForm.tf_ssn2.getPassword());
String phone = joinForm.tf_phone1.getText() + "-" + joinForm.tf_phone2.getText() + "-"
+ joinForm.tf_phone3.getText();
// phone="010-1234-5678"
String addr = joinForm.tf_addr.getText();
String job = joinForm.cb_job.getSelectedItem().toString();
MembershipVO vo = new MembershipVO(id, pass, name, Integer.parseInt(ssn1), Integer.parseInt(ssn2), phone,
addr, job);
MembershipDAO dao = new MembershipDAO();
// ★
if (dao.create(vo))
{// DB입력이 성공했다면 (회원가입성공)
joinForm.showMsg("회원가입성공!!");
// 회원가입폼 ----> 로그인폼 이동
joinForm.setVisible(false);
loginForm.setVisible(true);
} else
{
joinForm.showMsg("입력값을 확인하세요!!");
}
} else if (ob == loginForm.bt_join)
{// 로그인폼 : 신규가입버튼 클릭시
loginForm.setVisible(false);
joinForm.setVisible(true);
} else if (ob == serviceForm.bt_sel_all)
{// 서비스폼: 전체보기 버튼 클릭시
MembershipDAO dao = new MembershipDAO();
ArrayList<MembershipVO> list = dao.findAll();
serviceForm.displayTable(list);
} else if (ob == serviceForm.bt_up)
{// 서비스폼: 수정 버튼 클릭시
// findById호출을 위해 아이디 값 얻어오기
String id = serviceForm.showInput("수정할 아이디:");
// ------------------------------------------------
MembershipDAO dao = new MembershipDAO();
MembershipVO vo = dao.findById(id);
// ------------------------------------------------
if (vo == null)
{ // DB에 일치하는 아이디가 존재하지 않는다면
serviceForm.showMsg("존재하지 않는 아이디입니다!!");
return;
}
// 수정폼에 조회결과(vo)를 출력!!
updateForm.initText(vo);
// 이동 : 서비스폼 ---> 회원정보 수정폼
serviceForm.setVisible(false);
updateForm.setVisible(true);
} else if (ob == updateForm.bt_submit)
{// 회원정보수정폼 : 등록(수정)버튼 클릭시
// 수정할 정보(데이터) 수집
String phone = updateForm.tf_phone1.getText() + "-" + updateForm.tf_phone2.getText() + "-"
+ updateForm.tf_phone3.getText();
// 수집된 정보를 한개의 변수명(vo)으로 정의
MembershipVO vo = new MembershipVO();
vo.setId(updateForm.tf_id.getText());
vo.setPass(new String(updateForm.tf_pass.getPassword()));
vo.setPhone(phone);
vo.setAddr(updateForm.tf_addr.getText());
vo.setJob(updateForm.cb_job.getSelectedItem().toString());
// ----------------------------------------------------
MembershipDAO dao = new MembershipDAO();
if (dao.modify(vo))
{
// ----------------------------------------------------
// DAO실행결과를 반영(뷰이동, 뷰의 내용을 변경)
serviceForm.displayTable(dao.findAll());
updateForm.setVisible(false);
serviceForm.setVisible(true);
} else
{
updateForm.showMsg("다시!");
}
} else if (ob == serviceForm.bt_del) //회원 삭제 폼
{
String id = serviceForm.showInput("삭제할 아이디 : ");
MembershipDAO dao = new MembershipDAO();
if (dao.remove(id))
{
serviceForm.displayTable(dao.findAll());
}else
{
serviceForm.showMsg("삭제 실패! 관리자에게 문의하세요");
}
} else if (ob == serviceForm.bt_sel_name) //서비스 폼 : 이름검색 버튼 클릭시
{
String name = serviceForm.showInput("조회할 이름 : ");
MembershipDAO dao = new MembershipDAO();
ArrayList<MembershipVO> list = dao.findByName(name);
//조회된 결과 뷰에 반영
serviceForm.displayTable(list);
} else if (ob == serviceForm.bt_exit) //서비스폼 : 종료 버튼 클릭시
{
System.exit(0);
}
}// actionPerformed
public static void main(String[] args)
{
new Controller();
}
}
궁금상자
<Statement와 PreparedStatement>
가장 큰 차이점은 cache사용 여부,
Statement는 쿼리 수행시마다,
1. 쿼리 문장 분석
2. 컴파일
3. 실행 을 반복하게 됨.
PreparedStatement는 한번만 세 단계를 거친 후,
캐시에 담아 재사용을 함. DB 부하 감소
SQL Injection 방지,
---
▶ Statement (java.sql.Statement)
Statement에서는 executeQuery("DQL문"),excecuteUpdate("DML문")메소드를
실행하는 시점에 파라미터로 SQL문을 DB에 전달한다.
String sql="insert into person values (1,'"+name+"',13,'학생')";
stmt = conn.createStatement();
stmt.executeUpdate(sql); ==> 사용자가 입력한 데이터를 sql문과 조합해서 최종 sql문 생성
==> 생성된 sql문 실행!!
장점 : 사용된 SQL문 전체를 명확히 알 수 가 있어서 디버깅이 쉽다.
단점 : 조건값이 틀린 많은 수의 SQL문을 반복 실행하게 되는 경우, DB서버에서 모두 새롭게
PARSING되어야 하므로 부하가 생길수 있다.
SQL Injection에 취약.
-------------
SQL문장 주입 ==> 사용자가 입력한 데이터가 SQL문장을 구성할 수 있다!!
예)select count(*) cnt from membership where id='a' or 1=1 --' and pass='1234'
------------
사용자가 입력한 데이터
----------------
sql구문으로 변환
-----------------------------------------------------------------------
▶ PreparedStatement(java.sql.PreparedStatement)
PreparedStatement는 커넥션에서 생성하면서 SQL문이 DB에 전송되어진다.
Statement클래스를 상속하고 있음
String sql="insert into person values (?,?,?,?)";
---
? : 바인드 변수
stmt = conn.prepareStatement(sql); ===> (데이터가 빠진)sql문 전송!!
//?의 수만큼 설정(데이터 설정)!!
stmt.setInt (1, 1);
stmt.setString(2, name);
stmt.setInt (3, 13);
stmt.setString(4, "학생");
stmt.executeUpdate(); ==> ※주의: execute()메소드내에 sql기입하면 안됨.
==> 장점1) 작은따옴표, 큰따옴표, 콤마의 조합 그리고 자료형에 신경쓰지 않아도 됨.
장점2) 사용자가 입력한 (sql구문)데이터가 변경될 염려가 없다.
장점: bind변수를 사용하여 DB서버에서 파싱된 SQL을 재사용하게 만듬으로,
반복적인 다량의 SQL수행시 성능상 이득이 있다.
반복 루프를 통해서 하나의 SQL문에 변수값만 입력하며 반복 실행 할 수 있음.
★ SQL injection예방의 방법이 될 수 있다.
단점:
오류발생 시, 변수에 입력되는 값을 알 수 없어서 디버깅이 어렵다.
궁금상자
- Properties
Hashtables의 하위 클래스, Map의 속성 Key와 Value를 갖고, 파일 입출력을 지원
- Hash는 내부적으로 배열을 사용하여 데이터를 저장하는 것, 빠른 검색 속도.
Hashtable은 Hash의 key값이 불규칙함으로 고유한 숫자를 만들어 낸 뒤 이를 인덱스(hash code)로 사용한 구조.
Hash function(hash method) 사용하여 Hash code 반환.
- Hashtables는 key와 value에 null을 허용하지 않음.
- HashMap은 key값은 중복되지 않고, value는 중복이 허용
- Map이란 Key와 Value를 하나의 쌍으로 묶어 저장, List형태의 조상?!
- 느리지만 많은양의 데이터 검색하는데 뛰어남
- HashMap와 Hashtable은 동기화 유무의 차이
HashMap은 동기화 지원 안함 (thread-not-safe)
Hashtable은 동지화 지원 (thread-safe)
Hashmap은 멀티쓰레드 환경에서 사용하지 않는 걸 권장
---
Hashmap은 Value에 Null허용
Hashtable은 Null 허용 안함
'클라우드 기반 웹 개발자 과정 공부 > DB' 카테고리의 다른 글
190614_Day45 <회원가입 마무리>, <JCF 자바컬렉션 프레임워크> (0) | 2019.06.14 |
---|---|
190611_Day42 <기존 코드 DB연결> (0) | 2019.06.11 |
190610_DAY41 <기존 인메모리 코드에 DB연결 실습 및 연습> (0) | 2019.06.10 |
190504,5_DAY39,40 <복습> <Cursor>, <Package>, <Trigger>, <바인드변수>, <Table>, <Rollup & Cube>, <카티션 곱>, <GROUPING>, <집합연산자>, <JDBC> (0) | 2019.06.04 |
190603_DAY38 <복습>, <조건문>,<반복문>, <Stored Procedure>, <Stored Function> (0) | 2019.06.03 |