반응형

**오라클 연동

1. 프로젝트에 ojdbc.jar 파일을 복사하고 build path에 추가

 

2. 접속 정보를 저장할 텍스트 파일을 생성

=>프로젝트 안에 db.txt 파일을 생성하고 작성

oracle.jdbc.driver.OracleDriver

jdbc:oracle:thin:@ip주소:1521:xe

user29

user29

 

3.main메소드를 소유한  Main클래스를 만들고 접속하는 코드를 만듬

소스는 배포 안한다.

public class OracleMain {

           public static void main(String[] args) {

                       try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("./src/java/db.txt")))){

                                  String driverClass = br.readLine();

                                  String url = br.readLine();

                                  String id = br.readLine();

                                  String pw = br.readLine();

                                 

                                  //드라이브 클래스 로드

                                  Class.forName(driverClass);

                                  //데이터베이스 연결  객체 생성

                                  Connection con = DriverManager.getConnection(url,id, pw);

                                 

                                  con.close();

                       } catch (Exception e) {

                                  System.out.println("데이터베이스 예외: "+e.getMessage());

                                  e.printStackTrace();

                       }

           }

}

 

4.SQL 실행

1).Select 를 제외한 구문

PreparedStatement pstmt= con.prepareStatement("SQL작성");

=>입력받는 값들은 ? 로 설정

pstmt.set자료형(?번호, 실제데이터);

 

int result = pstmt.executeUpdate();

//리턴되는 값은 영향받은 행의 개수입니다.

//0이 리턴되면 조건에 맞는 데이터가 없는 것이고 1이상의 숫자면 테이블에 변화가 생김

//sql이 잘못되면 예외가 발생

pstmt.close();

 

 

python에서는 "num=" + str(3) ;

java "num="+3

c언언는 itoa 사용해야 한다.

 

로그인 만들때 아이디와 비밀번호 확인 해야 하는데

select *

from member

where id = ?

   and pw = ?;

이 경우에는 id가 비밀번호중 하나만 틀리면 안나온다.

pw '' or 1=1; =>이 경우 무조건  true가 된다.

id = ? and pw = ? or 1=1

이 경우 true가 되기 때문에

대입되는 데이터는 sql예약어를 못 쓰게 하는 것을 확인해야 한다. or못들어 오게 검사를 해야 한다.

비번은 복호화가 불가능한 암호화를 해야 합니다.복호화를 해도 안된다.

암호화의 가장 기본은 다른 값으로 바꿔야 한다.

    5

a ->f

비밀번호 보이는 것 다르게 보이지만 관리자는 해석할 수 있다. +5 할 수 있으면 -5하면 안된다.

복호화는 불가능하고 비교는 가능하도록 저장 하는 것에 대해서 고민을 해야 한다.

비밀번호 찾기 하면 최근에는 없다 . 왜냐하면 복호화가 불가능해서 다른 것을 준다.

비교는 되는데 복호화는 안된다.

 

각대입하기 전에 검사를 해야 한다. 유효성검사이다.

 

자주 사용하는 것은 a , an , the

2)삽입하는 구문을 작성하고 실행

String sql = "INSERT INTO TRANSACTIONS (NUM, ITEMCODE, ITEMNAME, PRICE, CNT, TRANSDATE,USERID) VALUES (?,?,?,?,?,?,?)";

                                  PreparedStatement pstmt = con.prepareStatement(sql);

                      

                                  pstmt.setInt(1, 1);

                                  pstmt.setString(2, "k101");

                                  pstmt.setString(3, "안경");

                                  pstmt.setInt(4, 2000000);

                                  pstmt.setInt(5, 1);

                                  Calendar cal = new GregorianCalendar(2021,0,31,14,34,00);

                                  Date transdate = new Date(cal.getTimeInMillis());

                                  pstmt.setDate(6, transdate);

                                  pstmt.setString(7, "gg");

                                  System.out.println(sql);

                                  int result = pstmt.executeUpdate();

                                  if(result>0) {

                                              System.out.println("삽입 성공");

                                  }

                                  pstmt.close();

 

3)수정하는 구문을 삽입한 구문 대신 작성하고 실행

                                  String sql = "UPDATE TRANSACTIONS SET ITEMCODE = ? ,ITEMNAME = ?, PRICE =?, CNT = ?, TRANSDATE = ?, USERID=?"

                                                         + " WHERE NUM = ?";

                                  PreparedStatement pstmt = con.prepareStatement(sql);

                      

                                  //값 검증 작업을 해야 합니다.

                                  //값이 들어가도 되는지 확인 해야 한다.

                                 

                                  pstmt.setString(1, "t1000");

                                  pstmt.setString(2, "터미네이터");

                                  pstmt.setInt(3, 20000);

                                  pstmt.setInt(4, 1);

                                  Calendar cal = new GregorianCalendar(2021,2,27,14,34,00);

                                  Date transdate = new Date(cal.getTimeInMillis());

                                  pstmt.setDate(5, transdate);

                                  pstmt.setString(6, "gg1");

                                 

                                  pstmt.setInt(7, 1);

                                  System.out.println(sql);

                                  int result = pstmt.executeUpdate();

                                  if(result>0) {

                                              System.out.println("수정 성공");

                                  } else if(result == 0) {

                                              System.out.println("조건에 맞는 데이터가 없습니다.");

                                  }

                                 

                                  pstmt.close();

 

 

4) 삭제하는 구문을 수정하는 구문 대신 작성하고 실행

//데이터 삭제 - 기본키로 가지고 데이터를 삭제하는 것이 일반적

                                  String sql = "DELETE FROM TRANSACTIONS WHERE NUM = ?";

                                  PreparedStatement pstmt = con.prepareStatement(sql);

          

                                  pstmt.setInt(1, 1);

                                  int result = pstmt.executeUpdate();

                                  if(result>0) {

                                              System.out.println("삭제 성공");

                                  } else if(result == 0) {

                                              System.out.println("조건에 맞는 데이터가 없습니다.");

                                  }

                                  pstmt.close();

 

2. 복호화가 불가능한 암호화

=>비밀번호와 같은 데이터를 저장할 때는 관리자도 알아볼수 없도록 복호화가 불가능한 형태로 저장해야 합니다.

=>Java에서 JBcrypt 라이브러리를 이용해서 구현

암호화 할 떄는 BCrypt.hashpw(String 평문 , Bcrypt.getSalt()) ;//암호화 방식을 설정한다.

비교할 때는 BCrypt.checkpw(String 평문, String 암호화된 문장); //두개가 일치하면 true 그렇지 않으면 false

암호화를 할 때는 최소 64자리 이상 저장할 수 있습니다.

 

1)www.mvnrepository.com에서 jbcrypt를 검색해서 다운로드 받아서 프로젝트에 복사하고 build path에 추가

2)데이터를 삽입하는 부분을 수정

                                  //암호화된

                                  System.out.println(BCrypt.checkpw("더미네이터", BCrypt.hashpw("더미네이터", BCrypt.gensalt())));

                                  System.out.println(BCrypt.checkpw("더미네이터1", BCrypt.hashpw("더미네이터", BCrypt.gensalt())));

                                 

                                  System.out.println(BCrypt.hashpw("더미네이터", BCrypt.gensalt()));

                                  System.out.println(BCrypt.hashpw("더미네이터", BCrypt.gensalt()));

똑같은 것도  다르게 저장된다.

A ->3E

A ->4E

gensalt가 라운드 값이다.

 

                                  System.out.println(BCrypt.checkpw("더미네이터", "$2a$10$UZeN.BWhdf6ITyNXOFv18Om1S8y/9UKVPVS8RXfkfK.ZgEPy5lIye"));

                                  System.out.println(BCrypt.checkpw("더미네이터", "$2a$10$tK7xnYE5gxy0TlI0iQbGNeK359rQbUaUHd17m7m8IPxXx5mrF70.m"));

 

복호화가 가능한 것 이메일 이메일은 암호화되서 하는 것이다.

https -> 보안에 적용된 것

 

 

텍스트 마이님 일 경우 replace 해서 "" 으로 치환해서 한다.

비밀번호는 대소문자 구분하지만 아이디는 대소문자 구분하지 않는다.

 

 

//데이터베이스 데이터를 저장하거나 수정할 때 사용할 수 없는 단어를 확인해서 저장하거나 수정하는 것이 좋습니다.

                                  //특히 sql예약어는 확인해서 데이터로 사용하지 못하도록 하는 것이 좋습니다.

                                  String[] stop_words = {"or", "and"};//나중에는

                                  //워드 클라우드 시 관련 된 것을 빼고 할 것이다.

                                 

                                  String sql = "INSERT INTO TRANSACTIONS (NUM, ITEMCODE, ITEMNAME, PRICE, CNT, TRANSDATE,USERID,PASSWORD) VALUES (?,?,?,?,?,?,?,?)";

                                  PreparedStatement pstmt = con.prepareStatement(sql);

                      

                                  pstmt.setInt(1, 6);

                                  String str = "dkdskfasand";

                                  //stop_words의 모든 데이터를 수행

                                  for(String temp : stop_words) {

                                              //idnexOftemp가 몇번째 있는지 검색해주는 메소드

                                              //찾으면 찾은 위치를 리턴하고 못 찾으면 -1을 리턴

                                              if(str.indexOf(temp) >= 0) {

                                                         System.out.println("사용할 수 없는 단어가 포함되어 있습니다.");

                                                         //return 을 하면 작업을 수행하지 않음

                                                         //return;

                                                         //찾으면 ""으로 치환 - 제거

                                                         str = str.replace(temp, "");

                                              }

                                  }

                                  //id나 검색어 등은 모두 대문자 또는 소문자로 변경해서 저장하는 것이 일반적

                                  pstmt.setString(2, str.toUpperCase());

                                  pstmt.setString(3, "안경");

                                  pstmt.setInt(4, 2000000);

                                  pstmt.setInt(5, 1);

                                  Calendar cal = new GregorianCalendar(2021,0,31,14,34,00);

                                  //java.sql.Date

                                  Date transdate = new Date(cal.getTimeInMillis());

                                  pstmt.setDate(6, transdate);

                                  pstmt.setString(7, "gg");

                                  pstmt.setString(8, BCrypt.hashpw("터미네이터", BCrypt.gensalt()));

                                  //BCrypt두가지 방법 밖에 없어서 확인하는 것 밖에 안된다.

                                  //BCrypt두가지 방법 밖에 없어서 확인하는 것 밖에 안된다.

                                  int result = pstmt.executeUpdate();

                                  if(result>0) {

                                              System.out.println("삽입 성공");

                                  }

                                  pstmt.close();

 

3.Transaction

=>한번에 이루어 져야 하는 작업의 논리적인 단위

=>SQL은 명령어 단위로 실행되는데 실제 업무에서는 여러 개의 SQL이 모여서 하나의 작업을 구성하는 경우가 많습니다.

이런 경우에는 트랜잭션을 만들어서 전부수행되거나 전부 수행되지 않도록 해주어야 합니다.(ALL Or Nothing)

 

1) commitrollback

=>commit은 현재 까지 수행한 내용을 원본에 반영

=>rollback은 현재 까지 수행한 내용을 원본에 반영하지 않음

=>savepointrollback할 지점을 생성

 

2)트랜잭션 처리 방법

auto commit: sql문장을 성공적으로 수행될 때 마다 바로 commit

 

manual commit : 명시적으로 commit이나 rollback을 호출해야 하는 방법

 

 

3)트랜잭션 생성

=>commit이나 rollback을 한 후 첫번째 dml(insert, update, delete)을 만났을 때 생성

 

4)commit을 하지 않아도 commit을 수행하고 트랜잭션을 종료하는 경우

=>접속 프로그램을 정상적으로 종료할 때

=>DDL(create, alter, drop,truncate, rename) 이나 DCL(grant, revoke)을 성공적으로 수행한 경우

 

5)자동으로 rollback되는 경우

=>데이터베이스나 접속 프로그램이 비정상적으로 종료되는 경우

 

6)java에서의 트랜잭션 처리

=>java는 기본적으로 auto commit

=>manual commit을 하고자 하는 경우에느느 Connection객체가 setAutoCommit(false)를 호출하고

Connection객체 가지고 commit()이나 rollback()을 호출하면 됩니다.

 

RDBMS(ORACLE)

selectsms 되는데 commit가 된 경우는 다른데서 트랜잭션을 사용하고 있다.

관계형 데이터베이스 하나의 장점은 강력한 트랜잭션이다.

 

commit();//복제의 것을 원본으로 덮어 씌우는 것이다.

트랜잭션은 원본에 하는 것이다.

 

4.select 구문 실행

=>select구문은 PreparedStatement객체를 가지고 executeQuery()를 호출하면 됩니다.

ResultSet을 리턴합니다.

=>ResultSet은 조회된 데이터에 접근할 수 있는 Cursor의 역할을 합니다.

next()메소드를 이용해서 다음 데이터가 있는지 확인하고 있으면 다음 데이터를 가리킵니다.

=>각 컬럼의 데이터를 읽고자 하는 경우에는 ResultSet.get자료형(컬럼의 인덱스 또는 컬럼이름)으로 가져옵니다.

 

=>데이터를 읽어서 다른 곳에서 사용을 하고자 할 때는 검색된 데이터를 하나의 변수에 저장을 해야 합니다.

여러개의 데이터의 경우는 컬럼의 데이터를 저장할 수 있는 DTO클래스를 생성하고나 mAP을 이용해서 저장하고 이러한 DTO클래스나 mAP클래스의 인스턴스들은 lIST에 저장합니다.

이런 구조를 r이나 Pythonpandas에서는 DataFrame이라고 합니다.

MapList구조입니다.

public class SelectMain {

           public static void main(String[] args) {

                       try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("./src/java/db.txt")))){

                                  String driverClass = br.readLine();

                                  String url = br.readLine();

                                  String id = br.readLine();

                                  String pw = br.readLine();

                                 

                                  //드라이브 클래스 로드

                                  Class.forName(driverClass);

                                  //데이터베이스 연결  객체 생성

                                  Connection con = DriverManager.getConnection(url,id, pw);

                                 

                                  //transactions테이블의 모든 데이터 가져오기

                                  String sql = "Select * from transactions";

                                  PreparedStatement pstmt= con.prepareStatement(sql);

                                  ResultSet rs = pstmt.executeQuery();

                                 

                                  //여러개의 컬럼으로 구성된 여러 개의 데이터를 저장

                                  List<Map<String , Object>> list = new ArrayList<Map<String , Object>>();

                                 

                                  //데이터를 순회

                                  while(rs.next()) {

                                              //하나의 행을 저장할 Map을 생성

                                              Map<String , Object> map = new HashMap<String ,Object>();

                                             

                                              map.put("num", rs.getInt("num"));

                                              map.put("itemcode", rs.getString("itemcode"));

                                              //3번째 컬럼의 값을 itemname으로 가져오는 것

                                              map.put("itemname", rs.getString(3));

                                              map.put("price", rs.getInt("price"));

                                              map.put("cnt", rs.getInt("cnt"));

                                              map.put("userid", rs.getString("userid"));

                                              map.put("transdate", rs.getDate("transdate"));

                                              map.put("password", rs.getString("password"));

                                             

                                              //하나의 행을 list에 저장

                                              list.add(map);

                                  }

                                 

                                  //list의 데이터 출력

                                  for(Map<String , Object> map :list) {

                                              //System.out.println(map);

                                              System.out.println(map.get("num"));

                                  }

                                 

                                  pstmt.close();

                                  con.close();

                       } catch (Exception e) {

                                  System.out.println("데이터베이스 예외: "+e.getMessage());

                                  e.printStackTrace();

                       }

           }

}

 

=>DTO패턴: Map 대신에 여러 개의 데이터를 저장할 수 있는 별도의 클래스를 만들어서 사용하는 패턴

이러한 클래스를 DTO(Data Transfer Object)또는 VO(Variable Object) 또는 Domain 클래스라고 합니다.

public class Transactions {

           private int num;

           private String itemcode  ;

           private String itemname  ;

           private int price     ;

           private int cnt       ;

           private Date transdate ;

           private String userid    ;

           private String password  ;

          

           public Transactions() {

                       super();

           }

          

           public Transactions(int num, String itemcode, String itemname, int price, int cnt, Date transdate, String userid,

                                  String password) {

                       super();

                       this.num = num;

                       this.itemcode = itemcode;

                       this.itemname = itemname;

                       this.price = price;

                       this.cnt = cnt;

                       this.transdate = transdate;

                       this.userid = userid;

                       this.password = password;

           }

          

           public int getNum() {

                       return num;

           }

           public void setNum(int num) {

                       this.num = num;

           }

           public String getItemcode() {

                       return itemcode;

           }

           public void setItemcode(String itemcode) {

                       this.itemcode = itemcode;

           }

           public String getItemname() {

                       return itemname;

           }

           public void setItemname(String itemname) {

                       this.itemname = itemname;

           }

           public int getPrice() {

                       return price;

           }

           public void setPrice(int price) {

                       this.price = price;

           }

           public int getCnt() {

                       return cnt;

           }

           public void setCnt(int cnt) {

                       this.cnt = cnt;

           }

           public Date getTransdate() {

                       return transdate;

           }

           public void setTransdate(Date transdate) {

                       this.transdate = transdate;

           }

           public String getUserid() {

                       return userid;

           }

           public void setUserid(String userid) {

                       this.userid = userid;

           }

           public String getPassword() {

                       return password;

           }

           public void setPassword(String password) {

                       this.password = password;

           }

 

           @Override

           public String toString() {

                       return "Transactions [num=" + num + ", itemcode=" + itemcode + ", itemname=" + itemname + ", price=" + price

                                              + ", cnt=" + cnt + ", transdate=" + transdate + ", userid=" + userid + ", password=" + password + "]";

           }

          

}

 

=>데이터 읽어서 DTO List만들기

 

                                  List<Transactions> list = new ArrayList<Transactions>();

                                 

                                  //데이터를 순회

                                  while(rs.next()) {

                                              //하나의 행을 저장할 Map을 생성

                                              Transactions transactions = new Transactions();

                                              transactions.setNum(rs.getInt("num"));

                                             transactions.setItemcode(rs.getString("itemcode"));

                                             transactions.setItemname(rs.getString("itemname"));

                                              transactions.setPrice(rs.getInt("price"));

                                              transactions.setCnt(rs.getInt("cnt"));

                                             transactions.setTransdate(rs.getDate("transdate"));

                                             transactions.setUserid(rs.getString("userid"));

                                             transactions.setPassword(rs.getString("password"));

                                             

                                              //하나의 행을 list에 저장

                                              list.add(transactions);

                                  }

                                 

                                  //list의 데이터 출력

                                  for(Transactions transactions :list) {

                                              //System.out.println(transactions);

                                             System.out.println(transactions.getNum());

                                  }

장점은 오타가 적다 .

하지만 테이블 구조를 바꾸고 다시 생성할 경우 다시 실행할 때 데이터가 있을 경우 오류가 난다.

 

mapwhile에만 바꾸면 된다.

 

5.MapDTO비교

=>DTO는 메소드를 호출해서 대입하고 가져오기 때문에 오류를 발생시킬 가능성이 줄어든다는 장점은 있지만 데이터 구조가 변경되는 경우에 수행할 부분이 많아 집니다.

관계형 데이터베이스 (RDBMS - 테이블 기반의 데이터베이스)의 특징입니다.

 

=>Map을 사용하면 put이라는 메소드를 이용할 때 문자열로 키를 지정하고 get으로 읽어올 때 문자열로 키를 대입해야 하는데 이 때 키 이름등의 오류가 많이 발생합니다.

데이터 구조가 변경되더라도 저장과 읽기 할 때 키만 변경하면 됩니다.

NoSQL 데이터베이스의 특징

 

 

**Web From End

HTML ->CSS-> JavaScript ->HTML5

HTML5javaScript를 사용

IDEEclipse를 사용하는데 Front End만 하는 경우에는 느려서 다른 VSCode, Aptana Studio등을 이용해서 됩니다.

EclipseWAS가 없으면 웹프로그램을 실행할 수 없음

 

반응형

'Study > Java' 카테고리의 다른 글

quickSort, SelectionSort,URLRouting  (0) 2020.11.03
java-20  (0) 2020.10.10
java-18  (0) 2020.10.10
java-17  (0) 2020.10.10
java-16  (0) 2020.10.10

+ Recent posts