반응형

 

 

 

 

 

 

 

 

 

 

 

 

Log

 

httpClient는 아파치 재단에서 URL 클래스를 훨씬 좋게 만든 것 (HTTP 프로토콜로 요청/ 응답 수행 가능)

안드로이드 OS에도 표준탑재되어 서버에서 정보를 다운받는 용도로 사용한다.

 

public class Test127{
	public static void main(String[] args) throws IOException{
    	//CloseableHttpCilent : 실제로 요청 / 응답을 수행하는 핵심
        
         CloseableHttpClient httpClient = HttpClients.createDefault();
         
         String l = "http://192.168.2.11:8081/study3/Test126.jsp?pw=1234";
         HttpGet httpGet = new HttpGet(l); //get 방식요청
         httpGet.addHeader("User-Agent", "Mozila/5.0"); //헤더 조작 여지
         
         // execute 실제로 요청/응답을 수행한다. httpResponse가 응답이다
         CloseableHttpResponse httpResponse = httpClient.execute(httpGet);
         
         int resCode = httpResponse.getStatusLine().getStatusCode();
         if(resCode == 200) {
        	 InputStream in = httpResponse.getEntity().getContent();
        	 BufferedReader bin = new BufferedReader(new InputStreamReader(in));
         // new InputStremReader(in, "utf-8") 한글 깨지면 이거 써라...
       
        	BufferedReader bin = new BufferedReader(new InputStreamReader(in));
          
        //  new InputStremReader(in, "utf-8") 한글 깨지면 이거 써라… **
       // why? => java default unicode / web default utf-8
 		String str = null;
 		while((str=bin.readLine())!=null){
 		System.out.println(str);
        }
      }
      
     }
     
   }
우리는 지금 Get 방식으로 사용하는 법을 배웠다. 많은 정보를 서버에서 다운받는 것에는 차이가 없다 GET이 든 POST든 Client에서 대량의 정보를 업로드 하려면 POST를 써야함 ** 위 코드와 많이 틀려지게 되니 이 점 유의할것 BufferedReader bin = new BufferedReader(new InputStreamReader(in)); ** new InputStremReader(in, "utf-8") 한글 깨지면 이거 써라… **

 

 

commons-logging.jar log4j-1.2.17.jar 은 lib 폴더에 넣는다.

Commons-logging.properties, log4j.properties는 src 폴더에 넣는다.

그러면 classes 폴더에 자동으로 복사된다. (실제 운영할 때는 classes 폴더에 넣으면 된다)

 

jar 파일이 버전이 다른 두개가 모이는 경우가 있는데 그럴 경우에는 안돌아가는 경우가 흔하다

 

Commons-logging.properties

# org.apache.commons.logging.Log=org.apache.commons.logging.impl.NoOpLog org.apache.commons.logging.Log=org.apache.commons.logging.impl.Log4JLogger

> 원하는 것 고르고

 

 log4j.properties

log4j.appender.A2.File=./../0805/web/log.txt

>경로 고치고

 

<%@page import="org.apache.log4j.Logger"%>
<%! static Logger logger = Logger.getLogger("about"); %>
<% logger.info("HelloWorld"); %>

 

>실행시키고 하면 ! ==> log.txt <== HelloWorld 이런식으로 찍힌다!

 

1. Commons-logging 에 대한 설정이 commons-logging.properties에 있음

    Log4JLogger : log4j 를 내부적으로 사용하겠다는 설정

    Log4JLogger에 대한 설정이 log4j.properties가 된다

 

2. log4j.appender.A2.layout.ConversionPattern = [%d] %5p %d : %m%n

    %m%n 만 해도 됨ㅎㅎ [시간] INFO about : HelloWorld 이런 식으로 뜸

    로그 파일의 형식 지정 : 단순히 콘솔에 찍어보는 걸 넘어서 내부적인 동작을 고스란히 담아낼 수 있다.

    로그파일 분석 툴을 이용하면 사이트 전반의 분석을 가능하게 한다.

 

3. 실전에는 Util.L(…) 같은 거 만들어서 쓰는 경우가 많다.

 

 

pageNavigation

 

페이지 개수 = ((글 갯수 -1) / 페이지 크기 ) + 1
블럭 사이즈 (BS) : 10 단위로 하단에 보여짐
이전 페이지 : (BB!=1)
다음 페이지 : (BE != 총 페이지 수)
BB = ((CP -1)/ 10) * 10 +1 : 처음 보여줄 1 2 3 4 5 개 / CP 는 1 2 3 4 5 .. 들 중 하나

1. 정렬된 순서 보기

SELECT id, title FROM Temp10T ORDER BY id DESC;

 

2. rownum??

SELECT id, rownum FROM Temp10T;

SELECT id, rownum FROM Temp10T ORDER BY id DESC;

—row num은 order by 이전에 부여된다. 따라서 order by 이후에 rownum으로 쪼개는 건 무의미

 

— 그러면 orderby 시켜놓고 그 다음에 rownum 붙이겠다?

SELECT id, rownum FROM ( SELECT id FROM Temp10T ORDER BY id DESC );

 

3. rownum을 기준으로 페이지 나누기?

SELECT id, rownum FROM ( SELECT id FROM Temp10T ORDER BY id DESC ) WHERE rownum > 0 AND rownum <= 5;

SELECT id, rownum FROM ( SELECT id FROM Temp10T ORDER BY id DESC ) WHERE rownum > 5 AND rownum <= 10;

Rownum 이 10까지 없고 모자란다? 5개 가져오는 중에 5~10 사이가 없음 안됨

 

4. rownum을 field로 굳혀놓고 나누기!!

SELECT id, rownum as sq FROM ( SELECT id FROM Temp10T ORDER BY id DESC );

SELECT id FROM ( SELECT id, rownum as sq FROM ( SELECT id FROM Temp10T ORDER BY id DESC ) ) WHERE sq > 0 AND sq <= 5; SELECT id FROM ( SELECT id, rownum as sq FROM ( SELECT id FROM Temp10T ORDER BY id DESC ) ) WHERE sq > 5 AND sq <= 10;

 

5. 서브쿼리로 정리해서 깔끔하게!!

SELECT * FROM Temp10T WHERE id IN ( SELECT id FROM ( SELECT id, rownum as sq FROM ( SELECT id FROM Temp10T ORDER BY id DESC ) ) WHERE sq > 10 AND sq <= 20 ) ORDER BY id DESC;

 

select * from (select id, rownum as sq from (select id from temp10t where 0=0 order by id desc))

where sq>20 and sq<=30;

 

6. 나중의 검색을 위해서 0 = 0 은 그냥 끼워 넣어준다(검색을 어떻게 할지 생각해 보자)

SELECT * FROM Temp10T WHERE id IN ( SELECT id FROM ( SELECT id, rownum as sq FROM ( SELECT id FROM Temp10T WHERE 0 = 0 ORDER BY id DESC ) ) WHERE sq > 5 AND sq <= 10 ) ORDER BY id DESC;

 

여기에서 0 = 0 을 응용하여 검색기능에서의 나누기 시도한다.

 

StringBuffer find = new StringBuffer(" WHERE 0 = 0"); if( title != null ){ find.append(" AND title LIKE '%"); find.append( title ); find.append("%'"); } if( user != null ){ find.append(" AND user ='"); find.append( title ); find.append("'"); } if( content != null ){ find.append(" AND content LIKE '%"); find.append( content ); find.append("%'"); }

 

String subSql = "SELECT id FROM " + "( SELECT id, rownum as sq FROM " + "( SELECT id FROM Temp10T "+ find.toString() + " ORDER BY id DESC ) )" + "WHERE sq > 5 AND sq <= 10";

 

String countSql = "SELECT COUNT(*) FROM Temp10T " + find.toString(); String sql = "SELECT * FROM ("+ subSql +") ORDER BY id DESC";

 

그러면 아래와 같은 형태의 결과를 보게 될 것이다.

 

SELECT COUNT(*) FROM Temp10T WHERE 0 = 0 AND user = 'root' AND content LIKE '%ab%'

....

SELECT * FROM Temp10T WHERE id IN ( SELECT id FROM ( SELECT id, rownum as sq FROM ( SELECT id FROM Temp10T WHERE 0 = 0 AND user = 'root' AND content LIKE '%ab%' ORDER BY id DESC ) ) WHERE sq > 0 AND sq <= 3 ) ORDER BY id DESC;

 

0=0 위치가 검색 조건이 들어갈 위치

select * from temp10t where id in(select id from (select id, rownum sq from (select id from temp10t where title like '%bc%' order by id desc))where sq>0 and sq<=10) order by id desc;

 

Mysql

create table Temp10t(

-> id integer(3),

-> title varchar(7));

~insert로 입력

 

select * from temp10t order by id desc limit 0, 10;

10 씩 쪼개줌

select * from temp10t order by id desc limit 10, 10;

10개 세고 또 10개

 

> form-group으로 지정된 div를 이용하여 label과 input을 한쌍으로 묶어서 보여준다

<form role="form">
 <div class="form-group">
 <label for="email">이메일</label>
 <input type="text" id="email" class="form-control"/>
 </div>
</form>

 

>그리드 이용하여 모바일용 화면과 pc용 화면을 하나의 페이지에서 구현한 사례

<div class="row">
   <div class="col-xs12 col-sm-4">
     <form role="form">
       <div class="form-group">
         <label for="email">이메일</label>
         <input type="text" id="email" class="form-control temp"/>
         </div>
       <div>
         <label>암호</label>
         <input type="password" id="password" class="form-control" />
       </div>
     </form>
   </div>
</div>

 

>> form에 추가 

class = "form-inline"
sm 크기 이상인 경우 class="form-inline"이 지정되면 라벨과 컨트롤은 좌우로 배치된다.
input 크기가 가지런하지 않아 이 부분 개선 class="form-hoizontal"로 지정된 경우에 라벨과 인풋이 가지런하게 배치되도록 할 수 있다

input은 div에 넣어 크기를 지정하고
label의 class에 크기를 지정한다

 

JavaScript

<a href = "javascripts:alter('<%=1%>');"> Click </a>

브라우저가 요청하면 서버가 요청을 받고, 요청에 해당하는 servlet/jsp가 동작한다

보여지는 브라우저 상 에서 javascript는 동작한다

 

jsp 에서 javascript 코드를 생성하는 일은 가능하다.

하지만 javascript에서 jsp쪽이 코드를 생성하는 일은 불가능하다.

왜? jsp가 먼저 동작하기 때문에

 

함수의 매개변수의 갯수가 틀려도 호출된다.
만일 갯수가 틀리면 앞의 변수부터 대입이 된다.
변수 선언시에는 var라는 키워드를 사용한다.
변수는 모든 값이 대입 가능 (정수, 문자열, 실수, 함수, 객체...)
두번 선언해도 에러 안나고, var없이 선언해도 에러 안난다
script 태그 안에 있는 코드는 페이지가 모두 로딩 되지 않은 상태에서
호출 변수를 선언하지 않고 사용하면 초기값은 undefined이고 여난이 불가능하다.
var total=0; 코드가 빠졌을 때 에러가 나는 이유를 점검하자.
java는 블럭 안에서 선언한 변수는 블럭에서만 쓸 수 있는 개념인데
javascript는 선언만 되어 있으면 쓸 수 있고, 선언 안해도 쓴다


모든 html 요소는 id 속성을 가질 수 있다 

속성 값은 pk처럼 겹치면 안된다

 

Document.getElementById("abcd") : id 값으로 객체의 포인터를 찾는다

 

window.onload = function(){
 var op = document.getElementById("abcd");
 op.onclick = function () {
 alert();
 }
}

/*op라는 포인터 변수로 해당 객체를 가리킨다
  포인터를 통해 객체가 가진 속성을 읽고, 조작할 수 있다
  op.onclick은 op 포인터가 가리키는 객체의 onclick 이라는 변수(프로퍼티)
  javascript 변수는 다 가리킬 수 있다.
  onclick은 이름없는 함수와 다름 없다.
  가리키는 것과 호출하는 것은 다르다(여기서는 가리키기만 한다.)
  
  호출되는 시점? 
  op 가리키는 객체에 click 상황이 벌어지면 onclick 이 가리키는 함수가 호출된다.
	
  이벤트 처리의 두가지 방법
	1. onXXX 속성을 이용하는 방법 : onclick="alert();"
	2. onXXX 속성을 함수포인터로 쓰는 방법 : 위 코드의 방법.(이 방법이 더 많이 스임).*/

 

 

window.onload = function(){
 var is = document.getElementsByTagName("img");
 for(var i=0;i<is.length;i++){
 alert(is[i].src);
 }
}

/*ls[0] = function(){alter(i)} 가리키는 시점에서는 i가 0인데, 호출하는 시점에서는 4가 된다

가리키는 시점의 값과 호출하는 시점의 값이 같아야 한다

=> 함수의 매개변수를 활용한 로컬변수를 사용해야한다*/
반응형

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

6. 자바, 더 간편하게  (0) 2019.09.08
5. 자바, 더 정확하게  (0) 2019.09.08
제주에서 자바_Week3_4  (0) 2019.08.11
##자바 헷갈리는 이론  (0) 2019.08.01
제주에서 자바_Week3_3  (0) 2019.07.31
반응형

 

 

 

 

 

 

 

 

 

<MVC 아키텍쳐>

MVC 이전
Model DAO
View HTML 영역
Controller java영역(서블릿)

 

MODEL(DAO)

package study;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
public class BangMyungDAO_OracleImpl implements BangMyungDAO
{
     @Override
     public void add(BangMyungVO vo) throws Exception
     {
         Connection conn = null;
         Statement stmt = null;
         try {
                 Class.forName("oracle.jdbc.driver.OracleDriver");
                 conn =
            DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:32771/xe",
             "system", "1234");
                stmt = conn.createStatement();
             String sql = "insert into bangmyung_t values (
            seq_bangmyung.nextval, '"+
             vo.getGul() + "', sysdate )";
             stmt.executeUpdate( sql );
             }
                catch( Exception e ){ throw e; }
                finally {
                 if( stmt != null ) stmt.close();
                 if( conn != null ) conn.close();
                }
         }
         @Override
         public List<BangMyungVO> findAll() throws Exception {
             List<BangMyungVO> ls = new ArrayList<BangMyungVO>();
             Connection conn = null;
             Statement stmt = null;
             ResultSet rs = null;
         try {
             Class.forName("oracle.jdbc.driver.OracleDriver");
             conn =
        DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:32771/xe",
         "system", "1234");
             stmt = conn.createStatement();
             String sql = "SELECT no, gul, the_time FROM bangmyung_t order by
        no desc";
             rs = stmt.executeQuery( sql );
         while( rs.next() ) {
              BangMyungVO vo = new BangMyungVO();
             vo.setNo( rs.getInt("no") );
             vo.setGul( rs.getString("gul") );
             vo.setTheTime( rs.getString("the_time") );
             ls.add( vo );
         }
         }
         catch( Exception e ){}
         finally {
             if( rs != null ) rs.close();
             if( stmt != null ) stmt.close();
             if( conn != null ) conn.close();
         }
     return ls;
     }
}

VIEW(HTML)

<%@ page language="java" contentType="text/html; charset=EUC-KR"
 pageEncoding="EUC-KR"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="sso" %>
<!DOCTYPE>
<html>
    <body>
        <table border='1'>
             <tr>
             <td>No</td>
             <td>글</td>
             <td>작성시간</td>
             </tr>
             <sso:forEach varStatus="vs" var="vo" items="${ lst }">
             <tr bgColor="${ (vs.count % 2 != 0)?'#aabbcc':'#bbccdd' }">
                 <td>${ vs.count }</td>
                 <td>${ vo.no }</td>
                 <td>${ vo.gul }</td>
                 <td>${ vo.theTime }</td>
             </tr>
             </sso:forEach>
        </table>
        <form method="POST" action="bangmyung_add.jsp">
         <input type="text" name="gul" size="50"/>
         <input type="submit"/>
        </form>
    </body>
</html>

 

CONTROLLER(JAVA)

<%@ page language="java" contentType="text/html; charset=utf-8"
 pageEncoding="utf-8" import="java.util.List, study.*" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="sso" %>
<%!
 public void submit() {
 System.out.println("submit");
 }
%>
<%
     // 1. 변수선언
     List<BangMyungVO> rl = null;
     Exception err = null;
     // 2. DB 연동
     BangMyungDAO dao = new BangMyungDAO_OracleImpl();
     try {
     rl = dao.findAll();
     } catch (Exception e) {
     err = e;
     }
     // 3. 흐름 만들기
     if ( rl == null || err != null ) {
     response.setCharacterEncoding("utf-8");
     response.sendRedirect("/study3/error.jsp");
     } else {
     request.setAttribute("lst", rl);
     RequestDispatcher rd = request.getRequestDispatcher("/Test125_1.jsp");
     rd.forward(request, response);
    %>
<!DOCTYPE>
<html>
    <body>
        <table border='1'>
         <tr>
             <td>No</td>
             <td>글</td>
             <td>작성시간</td>
         </tr>
         <sso:forEach varStatus="vs" var="vo" items="${ lst }">
         <tr bgColor="${ (vs.count % 2 != 0)?'#aabbcc':'#bbccdd' }">
             <td>${ vs.count }</td>
             <td>${ vo.no }</td>
             <td>${ vo.gul }</td>
             <td>${ vo.theTime }</td>
         </tr>
         </sso:forEach>
        </table>
    <form method="POST" action="bangmyung_add.jsp">
     <input type="text" name="gul" size="50"/>
     <input type="submit"/>
    </form>
    <% } %>
    </body>
</html>

 

MVC 만들기

package mvc;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    public interface Controller {
         public String handleRequest(HttpServletRequest request,
        HttpServletResponse response) throws Exception;
}
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
    public @interface RequestMapping {
     public String value();
}
package mvc;
//import 생략~
    public class DispatcherServlet extends HttpServlet {
     private Map<String, Controller> map = null;

     @Override
     public void init(ServletConfig config) throws ServletException{
         map = new Hashtable<String, Controller>();

         String cs = "mvc.CtrlList,mvc.CtrlAdd2";
         for(String str : cs.split(",")){
         try{
             //해당 클래스 가져오고
             Class<?> cls = Class.forName(str);
             //RequestMapping에서 지정된 url 패턴 따오고
             RequestMapping an = cls.getAnnotation(RequestMapping.class);
            //얘 때문에 Controller에너는 Annotation!
             System.out.println("this is an : " + an);
             //해당 controller instance 받아오고
             Controller value = (Controller) cls.newInstance(); 
             // 이름이 str인 Controller 클래스 찾기
             // url 따기
             String key = an.value();
             //url-pattern과 controller 매핑
                 map.put(key, value);
                 }catch (Exception e) {}
                 } //String[] cs2 = cs.split(","); for(int i=0;i<cs2.length;i++)
                 System.out.println(map.toString());
         }
     @Override
     protected void service(HttpServletRequest request, HttpServletResponse
    response)
     throws IOException, ServletException {
     }
 }
package mvc;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

    @RequestMapping("/apple_list.do")
    public class CtrlList implements Controller {

     @Override
         public String handleRequest(HttpServletRequest request,
    HttpServletResponse response) throws Exception {
         return null;
 }
package mvc;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@RequestMapping("/apple_add2.do")
public class CtrlAdd2 implements Controller{

     @Override
     public String handleRequest(HttpServletRequest request,
    HttpServletResponse response) throws Exception {
     return null;
     }
 }

JSP MODEL1 / MVC MODEL2

 

 

model1 VS model2

<model1>

가장먼저 들어오는 곳이 JSP이다.

JSP에서 비즈니스 로직, VIEW모든 것을 처리한다.

 

<model2>

가장먼저 요청하는 곳이 서브릿단이다.

비즈니스 로직을 처리하는 서블릿을 완전히 분리시켜서 VIEW단과 로직을 처리하는 단을 분리시킨다.




 

 

Controller 추가해야할 때

<servlet>
 <servlet-name>abcd2</servlet-name>
 <servlet-class>mvc.DispatcherServlet</servlet-class>
     <init-param>
         <param-name>controllers</param-name>
         <param-value>
         mvc.CtrlList,
         mvc.CtrlAdd2
         </param-value>
     </init-param>
</servlet>

<!-- 여기 이렇게 controller를 추가하면 되지 않을까! -->

public void init(ServletConfig config) throws ServletException{
 map = new Hashtable<String, Controller>();
 String cs = config.getInitParameter("controllers");

 

HTML 소스 긁어오는애

package main;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.net.URLConnection;
public class Test126 {
     public static void main(String[] args) throws Exception{
         URL rl = new URL("http://localhost:8081/0802/apple_list.do");
         URLConnection ucon = rl.openConnection();
         InputStream in = ucon.getInputStream();

     BufferedReader bin = new BufferedReader(new InputStreamReader(in,
    "UTF-8")); //>> char 단위로 읽게해주는 adapter
     //사실 UTF-8 빼도 되더라 얜 응답 내용
            String l = null;
         while((l = bin.readLine()) !=null){

         System.out.println(l);
         }
     in.close();
    }
}

java.net.URL은 이것 자체가 작은 웹브라우저의 역할을 한다. 요청을 날리고 그에 해당하는 응답을 받아들인
다 안드로이드 앱에서 버튼을 누르면 오늘의 배송정보가 넘어오는 ? 배송정보는 서버에 올라와 있는 상태! => 이
다운 받는 역할, 서버에 존재하는 배송정보를 다운받는 역할을 수행한다. 소켓으로 다 짜는 것이 아니라 http 프
로토콜로 서버와 통신할 때는 이 클래스를 주로 이용한다.
소켓으로 다 짜는 것이 아니라 http 프로토콜로 서버와 통신할 때는 이 클래스를 주로 이용한다.
앱 같은 경우에서 서버로부터 많은 데이터를 다운 받아야 할 경우에 URL 클래스를 이용하여 jsp 파일로부터 정
보를 다운받는다
이게 워낙 많이 쓰이다 보니 이를 강화한 오픈 소스 라이브러리가 등장 = apache http client 프로젝트 = 안
드로이드의 http 기반 표준 통신 수단

 

암호가 맞으면 다운, 아니면 안됨

    <%@ page contentType="text/plain; charset=UTF-8" pageEncoding="EUC-KR" %><%
     String pw = request.getParameter("pw");
     if(pw.equals("1234")){
         String[] l = {"사과", "귤", "배", "토마토"};
         String nl = "\r\n"; //줄 바꿈 표시

     for (int i = 0; i < l.length; i++) {%>
         <%=l[i]%><%=nl%>
         <%}}else{%>
         암호틀림
 <%}%>
public static void main(String[] args) throws Exception{
     URL rl = new URL("http://localhost:8081/0802/Test126.jsp?pw=1230");
     URLConnection ucon = rl.openConnection();
     InputStream in = ucon.getInputStream();

     BufferedReader bin = new BufferedReader(new InputStreamReader(in, "UTF8")); //>> char 단위로 읽게해주는 adapter
     //사실 UTF-8 빼도 되더라 얜 응답 내용

     String l = null;
     while((l = bin.readLine()) !=null){
         System.out.println(l);
         }
         in.close();
}
반응형

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

5. 자바, 더 정확하게  (0) 2019.09.08
제주에서 자바_Week4  (0) 2019.08.12
##자바 헷갈리는 이론  (0) 2019.08.01
제주에서 자바_Week3_3  (0) 2019.07.31
제주에서 자바_Week3_2  (0) 2019.07.30
반응형

Day 4

1. Thread(스레드)

  • 하나의 프로세스 내부에서 독립적으로 실행되는 하나의 작업 단위를 말하며,
  • 세부적으로는 운영체제에 의해 관리되는 하나의 작업 혹은 태스크
  • 스레드와 태스크(혹은 작업)은 바꾸어 사용해도 무관
  • 스레드 구현 방법 : 1. 스레드 이용  / 2. Runnable 이용하는 방법
JVM에 의해 하나의 프로세스가 발생하고 main( ) 안의 실행문 들이 하나의 스레드
main( ) 이외의 또 다른 스레드를 만들려면 Thread 클래스를 상속하거나 Runnable 인터페이스를 구현
다중 스레드 작업 시에는 각 스레드 끼리 정보를 주고받을 수 있어 처리 과정의 오류를 줄일 수 있음
프로세스끼리는 정보를 주고받을 수 없음

 

package Lecture.Week2;

//외우기
class CustomThreaded implements Runnable{
    //implements 받아오려면 runaable을 오버라이딩 해줘야 한다. / 오버라이딩 시 throws exception 같은 것은 붙일 수 없다.
    @Override
    public void run() {
        for(int i = 0; i < 100; i++){
            System.out.println("HelloWorld" + i);
        }
    }

}
    public class Test12 {
        public static void main(String[] args){
            //단순한 함수 호출
            Runnable rb = new CustomThreaded();
            rb.run();

            /*new Thread를 하면 가상의 cpu를 OS에서 할당한다. (분신)
            //할당받은 CPU는 생성자에 넘겨진 포인터를 물고 간다.
            start() 호출 : 준비과정을 거쳐 새로운 가상 CPU가 rb.run()을 호출한다.

            1. Runnable  상속받은 클래스 선언
            2. new Thread 하면서 1의 인스턴스의 포인터를 넘긴다
            2. Thread::start() 를 호출하면 가상 CPU(쓰레드) 가 run()을 호출*/
            Thread th = new Thread(rb); //thread의 참조형 변수
            th.start(); //이걸 해야 돌아감
        }
}

2. 프로세스 ,프로그램, 스레드

  • 프로세스 : 데이터(data) + 자원(memory) + 쓰레드(Thread) 로 구성(a running program)
  • 프로그램 : executable file
  • 스레드 : a light-weighted process (독자 행동을 하지만 조금 다르다)
    • 스레드는 프로세스 안에서만 존재가 가능하다
    • 스레드 간 메모리를 공유할 수 있다
    • 프로세스 간 메모리 전달은 가능해도 공유는 불가능하다
    • 프로세스간의 메모리 전달의 대표적 수단이 소켓이다(복사 & 붙이기도 전달로 볼 수 있지만 이건 윈도우에서 국한된 개념)
    • 프로세스 종료 == 프로세스가 가진 모든 쓰레드의 종료
    • start() : 이 스레드가 실행을 시작하도록 함-> 가상 머신 run이 thread의 메소드를 호출한다
    • run() : 이 스레드가 별도의 Runnable 실행 객체를 사용하여 작성한 경우 해당 runnable 객체의 run 메소드 호출
      그렇지 않을 경우 , 이 메서드는 아무것도 수행하지 않고 반환함.
package Lecture.Week2;
class Toilet{
    public void bigWork(String by){
        System.out.println("Step1," + by);
        System.out.println("Step2," + by);
        System.out.println("Step3," + by);
        System.out.println("Step4," + by);
        System.out.println("Step5," + by);

    }
}

/*참조형 : 오른쪽이 가르키는 대상을 왼쪽이 가르친다.
* 멤버변수 : 인스턴스 만들어진 시점에 생성*/


class A implements Runnable{
    private Toilet toilet = null;

    public A(Toilet t){
        toilet = t;
    }

    public void run(){
        for(int i = 0; i < 100;){
//            System.out.println("APPLE");
            toilet.bigWork("APPLE");
            try{
                int time = (int)(Math.random() *1000); //초 단위로 쉬게 하기
                Thread.sleep(time); //try  catch 필요
            }
            catch (InterruptedException e){}
        }
    }
}


class B implements Runnable{
    private Toilet toilet = null;

    public B(Toilet t){
        toilet = t;
    }

    public void run(){
        for(int i = 0; i < 100;){
//            System.out.println("BANANA");
            toilet.bigWork("BANANA");

            try{
                int time = (int)(Math.random() *1000); //초 단위로 쉬게 하기
                Thread.sleep(time); //try  catch 필요
            }
            catch (InterruptedException e){}
        }
    }
}
public class Test13 {
    public static void main(String[] args){
        Toilet t = new Toilet();
        new Thread( new A(t)).start(); //RUNNABLE에서 implements 받은 A의 인스턴스를 생성자에 넣어주고 START
        new Thread( new B(t)).start();
    }
}
/*쓰레드는 독자적으로 돌아가는 프로그램이 된다
* APPLE 과 BANANA 끼어들게 안 짯는데도 결과 가 나옴
* APPLE
BANANA
BANANA
APPLE
BANANA
BANANA
APPLE
BANANA
BANANA
BANANA....
*/

결과 :

Step1,APPLE
Step1,BANANA
Step2,APPLE
Step2,BANANA
Step3,BANANA
Step3,APPLE
Step4,BANANA
Step4,APPLE
Step5,BANANA
Step5,APPLE


* > 아무런 제약이 없다면 이렇게 동시 진행될 수도 있다
* 쓰레드는 독자적이기 떄문에 일어나는 현상
* -> 화장실 문을 잠가야 하니까 

=> 그것을 동기화(Synchronization)이라고 한다.

 

class Toilet{
    public void bigWork(String by){
        synchronized (this) { //this : 참조형 변수 (자기 자신에 대한)
            System.out.println("Step1," + by);
            System.out.println("Step2," + by);
            System.out.println("Step3," + by);
            System.out.println("Step4," + by);
            System.out.println("Step5," + by);
        }
    }
}

 

-모든 인스턴스에는 lock이라는 개념의 자물쇠? 열쇠?가 있다

-synchronized (this) => this가 가리키는 인스턴스가 가지고 있는 록을 획득해야 { .. 에 진입 가능

  획득하지 못하면 쓰레드는 멈추어 기다려야 한다. 

   }로 일을 마쳤으면 lock을 반납한다.

-이런 방법으로 공유하는 메모리에서 작업 도중 끊기는 일을 막을 수 있다. 

 

 

-스레드 조인  / run

package Lecture.Week2;


class A1 implements Runnable{
    public void run(){
        for(int i = 0; i <10; i++){
            System.out.println("A running");
        }
    }
}

class B1 implements Runnable{
    public void run(){
        for(int i = 0; i <10; i++){
            System.out.println("B running");
        }
    }
}

class C1 implements Runnable{
    public void run(){
        for(int i = 0; i <10; i++){
            System.out.println("C running");
        }
    }
}


public class Test14 {
    public static void main(String[] args){
        Thread[] threads = new Thread[3];

        threads[0] = new Thread(new A1());
        threads[1] = new Thread(new B1());
        threads[2] = new Thread(new C1());

        threads[0].start();
        threads[1].start();
        threads[2].start();

        try{
            threads[0].join(); //threads[0]이 끝나기전에는 내려가지 않는다.
            threads[1].join();//join()메소드는 쓰레드가 멈출때까지 기다리게 한다.
            threads[2].join();
        }//모든 쓰레드들이 다 끝나고 난 다음에 최종정리가 찍힌다.
        catch (InterruptedException e){}
//        new Thread(new A1()).start();
//        new Thread(new B1()).start();
//        new Thread(new C1()).start();

        System.out.println("최종정리");
    }
}

3. 자바 - DB 연동

줄 건다 -> 바구니 건다 -> 바구니에 물건 담는다 -> 왕복한다 -> 바구니 내린다 -> 줄 내린다

conn 형성 -> stmt 형성 -> 쿼리 작업 -> stmt.close() -> conn.close()

 

Connection conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/study","root","1111");

Statement stmt = conn.createStatement();//바구니 만든다

String sql = "insert into studentt values ('10107', '또오치','쌍문동')"; //바구니에 담는다

stmt.executeUpdate(sql2);//쿼리 실행-> sql문 실어서 간다

stmt.close(); //바구니 내린다

conn.close(); //줄 푼다.

<전체 코드>

package Lecture.Week2;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;

public class Test15 {
    public static void main(String[] args) throws Exception{
        Class.forName("com.mysql.jdbc.Driver");
        /*Connection은 mysql에 소켓으로 접속하는 것과 관계가 깊음
        * study : 데이터베이스 명
        * root  / 1111 : 계정 및 암호
        * 127.0.0.1 : 네트워크 카드 밖으로 나가지 않고 나에게 접속할 때
        * Statement는 바구니라고 생각하면 된다. */
        Connection conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/study","root","1111");
        //소켓을 이용해서 접속한다-> 줄 단다
        //db 연결

//        System.out.println(conn.toString());
            //connection 객체에 의해 프로그램에 리턴되는 객체에 의해 구현되는 일종의 메소드 집합
        Statement stmt = conn.createStatement();//바구니 건다
        String sql = "insert into studentt values ('10107', '또오치','쌍문동')";
        String sql2 = "delete from studentt where stid = '10107'";
        String sql3 = "update studentt set addr = '이도동' where stid = '10101'";

        stmt.executeUpdate(sql2);//쿼리 실행-> sql문 실어서 간다

        stmt.close(); //바구니 내린다
        conn.close(); //줄 푼다.

        /*Connection : IP, PORT, ID, PWD  -> 줄
        * Statement : SQL, 결과 -> 바구니
        * -> SQL로 -> RETURN 받아 -> STATEMENT.close() (바구니 먼저 내리고) -> CONNECTION.close() (줄 마지막으로 내리고)
        * executeUpdate : 함수의 리턴값은 변경된 레코드 개수 -> select는 레코드를 변경하지 않기 때문에 executeUpdate는 inser/delete/update문장에 사용한다
         */
 }
}

//java -classpath .;mysql-connector-java-5.0.8-bin.jar Test15
package Lecture.Week2;

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

public class Test16 {
    public static void main(String[] args) throws Exception {
        /*static {
            //클래스가 로딩되는 시점에 호출

            /*connection , statement 모두 인터페이스다
            * DriverManager, getConnection 안에서 Connection 상속받은 모종의 클래스의 인스턴스를 리턴한다.
            * -> Mysql에 접속할 수 있는 기능을 구현하고 있다.        }*/

        Class.forName("com.mysql.jdbc.Driver"); //모종의 클래스 세팅하는 코드
        Connection conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/study","root","1111");
//        System.out.println(conn.getClass().getName()); // conn이 어디 클래스에서 가져오나 찍어보는 것 -> com.mysql.jdbc.Connection
        Statement stmt = conn.createStatement(); //바구니 생성
//
        String sql = "select stid,name,addr from studentt";
        ResultSet rs = stmt.executeQuery(sql);

        while (rs.next()){
            String stid = rs.getString("stid");
            String name = rs.getString("name");
            String addr= rs.getString("addr");
            System.out.println(stid + "\t" + name +"\t" +addr);
        }
        rs.close();

        stmt.close();
        conn.close();

    }
}

///암기 하자

-select문에 정보들어가서 바구니에 담긴 걸 : CURSOR이라고 한다. -> 서버 쪽이라서 서버사이드 커서 

-쿼리에서 정보로 넘어갈 때 한 튜플을 채우고 그 밑으로 내려가면서 채운다 

Stid name
←   ↓
←   ↓
←   ↓
←   ↓

 

 

4. O-R Mapping 규칙(Golden Rule, Rule of Thumb)

  • ResultSet 은 CURSOR(select 결과)에 접근 가능한 정보
  • CURSOR는 서버에 생긴다
  • Connection 이 닫인 다음에서는 ResultSet은 사용 불가하다
    (Connection 닫기 전에 사용 끝나야 한다)
    -> connection은 비싼고 제한적인 지원이다
    -> 접속 후에 빨리 끊어주는게 바람직 하다 (콜 센터 연상)

<ArrayList 사용>

package Lecture.Week2;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

class StudentV0{
    /*property : 멤버 변수 -> public으로 열지 않는다.
    -> 대신에 getter , setter을 사용해 가져온다
    -> private 하게 선언 해야한다.*/
    private String stId = null;
    public String getStId(){ return stId;}
    public void setStId(String i){ stId = i;}

    private String name = null;
    public String getName(){ return name;}
    public void setName(String i){ name = i;}

    private String addr = null;
    public String getAddr(){ return addr;}
    public void setAddr(String i){ name = i;}
}




public class Test17{
    public static void main(String[] args) throws Exception {

        Class.forName("com.mysql.jdbc.Driver");
        Connection conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/study","root","1111");
        Statement stmt = conn.createStatement(); //바구니 생성

        /*O-R Mapping 규칙(Golden Rule, Rule of Thumb)

        Field => property
        * table -> class
        * record => instance*/
        //connection은 살아있을때 할거 다해야 하고 / 빨리 끊어야한다 -> 아래 코드에서 이상적으로 구현

        //왜 arrayList 일까? -> 중간 삽입삭제가 필요없고 쌓기만 하는거니까 속도가 빠른 ArrayList
        //VO : Value Object : 값을 담는 객체
        /*테이블 구조와 동일하게 레코드 하나를 인스턴스에 담을 수 있는 역할
        *
        *  DTO : DATA TRANSFER OBJECT
        * Entity 등을 사용하는 경우도 있는데 실은 다 같은 얘기*/
        List<StudentV0> rl = new ArrayList<StudentV0>();

        String sql = "select stid,name,addr from studentt";
        ResultSet rs = stmt.executeQuery(sql);

        while (rs.next()){
            StudentV0 vo = new StudentV0(); //-> 하나의 인스턴스로 만들어 버림
            vo.setStId(rs.getString("stid"));
            vo.setName(rs.getString("name"));
            vo.setAddr(rs.getString("addr"));
            rl.add(vo);
        }
        rs.close();

        stmt.close();
        conn.close();
        //conn.close()이후에도 LIST 안에는 결과가 담겨 있다.
        for(StudentV0 vo : rl){
            System.out.println(vo.getStId() + "\t" + vo.getName() + "\t" + vo.getAddr());
        }
    }
}

<Oracle DB 연동>

package Lecture.Week2;

//import java.sql.Connection;
//import java.sql.DriverManager;
import java.sql.*;

public class Test18 {
    public static void main(String[] args) throws Exception {
        Class.forName("oracle.jdbc.driver.OracleDriver");
        Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521/XE","HR","HR");
        System.out.println(conn.getClass().getName());
        /*oracle.jdbc.driver.T4CConnection -> connection은 인터페이스 -> 모종의 클래스(T4C)를 상속받아 사용 -> 오로지 오라클에서만 사용가능
          2019-07-25 17:23:23.0

          MYSQL과 코드가 거의 틀린점이 없다
          Connection, Statement 를 상속한 ORACLE 과 연동 가능한 클래스를 OracleDriver에서 DriverManager에 세팅해주면 Oracle에 맞추어
          개발된 , Connection Statement ResultSet 등을 상속받은 클래스가 공급되는 구조
         */

        Statement stmt = conn.createStatement();
        //현재 시간 - MYSQL : now() / ORACLE : SYSDATE
        String sql = "SELECT SYSDATE FROM DUAL";
        ResultSet rs = stmt.executeQuery(sql);
        //결과 레코드가 하나인 경우에는 while 대신에 if문 사용한다.
        if (rs.next()){
            //필드명 대신에 숫자 가능 / 1은 나열된 펏번째 필드를 의미
            String l = rs.getString(1); //첫번째 필드 얘기
            System.out.println(l);
        }

        rs.close();
        stmt.close();

        conn.close();
    }
}

 

Day 5

  1. ORACLE
SQL> conn hr/hr;
연결되었습니다.
SQL> CREATE TABLE STUDY01t(
  2  ID NUMBER(3),
  3  DATA VARCHAR2(10)
  4  );
SQL> INSERT INTO STUDY01t VALUES (100, 'HelloWorld');

-오라클 숫자 : NUMBER(3) -최대 3자리 숫자

-VARCHAR2 : 오라클에서 만든 속도가 조금 빠른 VARCHAR

 

SQL> CREATE TABLE STUDY11t(
  2  ID NUMBER(5),
  3  DATA CHAR(10)
  4  );
SQL> CREATE SEQUENCE seq_study11t;

시퀀스가 생성되었습니다.
SQL> insert into study11t values(seq_study11t.NEXTVAL, 'apple');

-오라클은 mysql은 일련번호가 만드는 방법이 다르다

:mysql : auto_increment primary key를 썼다

 

SQL> SELECT ID, DATA || '*' FROM STUDY11t;
:mysql 의 concat과 동일한 기능을 수행한다.
//char여서 조금 더 떨어져 있음 (|| 공백처리)
//CHAR(10)으로 선언한 필드에 'apple'을 넣으면 'apple       '이 된다
//mysql은 그냥 'apple'이 된다

        ID DATA||'*'
---------- ----------------------
         1 apple     *
         2 apple     *
         3 apple     *
         4 apple     *
SQL> SELECT ID, TRIM(DATA) || '*' FROM STUDY11t;
//TRIM() : 좌/우 공백 문자를 제거하는 역할을 한다

        ID TRIM(DATA)||'*'
---------- ----------------------
         1 apple*
         2 apple*
         3 apple*
         4 apple*
SQL> CREATE TABLE Study12t(
  2  THE_TIME DATE
  3  );
SQL> INSERT INTO STUDY12t VALUES(SYSDATE);
SQL> SELECT * FROM STUDY12T;

THE_TIME
--------
19/07/26
SQL> SELECT TO_CHAR(THE_TIME) FROM STUDY12T;

TO_CHAR(THE_TIME
----------------
19/07/26
19/07/26
19/07/26

SQL> SELECT TO_CHAR(THE_TIME,'YYYY-MM-DD') FROM STUDY12T;

TO_CHAR(THE_TIME,'YY
--------------------
2019-07-26
2019-07-26
2019-07-26

//ORACLE 날짜 시간은 DATE자료형을 사용한다

//현재 시간은 SYSDATE를 이용한다

//보여지는 형식은 TO_CHAR을 이용하여 형식을 지정하면 된다.

 

SQL> SELECT TO_CHAR(THE_TIME,'YYYY-MM-DD HH24:MI:SS') FROM STUDY12T;

TO_CHAR(THE_TIME,'YYYY-MM-DDHH24:MI:SS
--------------------------------------
2019-07-26 11:52:54
2019-07-26 11:53:30
2019-07-26 11:53:32

Q. 역삼동 사는 학생들의 국어점수와 STID를 서브쿼리로?

SQL> SELECT * FROM SCORET WHERE STID IN (SELECT STID FROM STUDENTT WHERE ADDR LIKE '%역삼%') AND SUBID = 'KOR1';

STID       SUBID         SCORE
---------- -------- ----------
10101      KOR1             60
10103      KOR1             70

Q. 학생별 평균점수를 GROUP BY로 구하기(GROUP BY 에서 지정한 컬럼은 SELECT 절에서 쓸 수 있다)

 

SQL> SELECT STID, AVG(SCORE) FROM SCORET GROUP BY STID;

STID       AVG(SCORE)
---------- ----------
10104      73.3333333
10101      76.6666667
10102      93.3333333
10103      76.6666667
10105      63.3333333
10106      66.6666667

#INNER JOIN

SQL> SELECT * FROM STUDENTT INNER JOIN SCORET ON STUDENTT.STID = SCORET.STID; 
= SQL> SELECT * FROM STUDENTT, SCORET WHERE STUDENTT.STID = SCORET.STID; //조금 더 직관적


STID       NAME               ADDR               STID       SUBID         SCORE
---------- ------------------ ------------------ ---------- -------- ----------
10101      홍길동             역삼동             10101      KOR1             60
10101      홍길동             역삼동             10101      ENG1             80
10101      홍길동             역삼동             10101      MAT1             90
10102      고길동             개포동             10102      KOR1             90
10102      고길동             개포동             10102      MAT1             90
10102      고길동             개포동             10102      ENG1            100
10103      이기자             역삼동             10103      KOR1             70
10104      박기자             한남동             10104      KOR1             80
10105      김영삼             홍제동             10105      KOR1             50
10106      김대중             한남동             10106      KOR1             60
10103      이기자             역삼동             10103      ENG1             90

STID       NAME               ADDR               STID       SUBID         SCORE
---------- ------------------ ------------------ ---------- -------- ----------
10104      박기자             한남동             10104      ENG1             70
10105      김영삼             홍제동             10105      ENG1             60
10106      김대중             한남동             10106      ENG1             80
10103      이기자             역삼동             10103      MAT1             70
10104      박기자             한남동             10104      MAT1             70
10105      김영삼             홍제동             10105      MAT1             80
10106      김대중             한남동             10106      MAT1             60

# OUTER JOIN 

SQL> SELECT * FROM SUBJECTT LEFT OUTER JOIN SCORET
  2  ON SUBJECTT.SUBID = SCORET.SUBID;

SUBID    NAME               STID       SUBID         SCORE
-------- ------------------ ---------- -------- ----------
KOR1     국어1              10101      KOR1             60
ENG1     영어1              10101      ENG1             80
MAT1     수학1              10101      MAT1             90
KOR1     국어1              10102      KOR1             90
MAT1     수학1              10102      MAT1             90
ENG1     영어1              10102      ENG1            100
KOR1     국어1              10103      KOR1             70
KOR1     국어1              10104      KOR1             80
KOR1     국어1              10105      KOR1             50
KOR1     국어1              10106      KOR1             60
ENG1     영어1              10103      ENG1             90

SUBID    NAME               STID       SUBID         SCORE
-------- ------------------ ---------- -------- ----------
ENG1     영어1              10104      ENG1             70
ENG1     영어1              10105      ENG1             60
ENG1     영어1              10106      ENG1             80
MAT1     수학1              10103      MAT1             70
MAT1     수학1              10104      MAT1             70
MAT1     수학1              10105      MAT1             80
MAT1     수학1              10106      MAT1             60
PHY1     물리
SQL> SELECT * FROM SUBJECTT, SCORET
  2  WHERE SUBJECTT.SUBID = SCORET.SUBID(+);

SUBID    NAME               STID       SUBID         SCORE
-------- ------------------ ---------- -------- ----------
KOR1     국어1              10101      KOR1             60
ENG1     영어1              10101      ENG1             80
MAT1     수학1              10101      MAT1             90
KOR1     국어1              10102      KOR1             90
MAT1     수학1              10102      MAT1             90
ENG1     영어1              10102      ENG1            100
KOR1     국어1              10103      KOR1             70
KOR1     국어1              10104      KOR1             80
KOR1     국어1              10105      KOR1             50
KOR1     국어1              10106      KOR1             60
ENG1     영어1              10103      ENG1             90

SUBID    NAME               STID       SUBID         SCORE
-------- ------------------ ---------- -------- ----------
ENG1     영어1              10104      ENG1             70
ENG1     영어1              10105      ENG1             60
ENG1     영어1              10106      ENG1             80
MAT1     수학1              10103      MAT1             70
MAT1     수학1              10104      MAT1             70
MAT1     수학1              10105      MAT1             80
MAT1     수학1              10106      MAT1             60
PHY1     물리

-> 오라클용 아우터 조인 문법

-NULL 값으로 채워지는 일이 발생하는 쪽에 + 표시 붙인다.

 

-INNER JOIN ON , OUTER JOIN ON => 국제 표준 SQL

-각 DB별로 변형 SQL을 탑재 

-ORCLE 의 변형방법을 다른 DB 업체들이 따라하기도 하고 

-오라클만 쓴느 사람들은 오라클의 방법만 고집하는 경우가 많다

 

SQL> SELECT STID, AVG(SCORE) AS AVG FROM SCORET GROUP BY STID;

STID              AVG
---------- ----------
10104      73.3333333
10101      76.6666667
10102      93.3333333
10103      76.6666667
10105      63.3333333
10106      66.6666667
SQL> SELECT * FROM (SELECT STID, AVG(SCORE) AS AVG FROM SCORET GROUP BY STID);

STID              AVG
---------- ----------
10104      73.3333333
10101      76.6666667
10102      93.3333333
10103      76.6666667
10105      63.3333333
10106      66.6666667
SQL> SELECT X.STID, X.AVG FROM (SELECT STID, AVG(SCORE) AS AVG FROM SCORET GROUP BY STID) X; //테이블 별칭 줄때 AS를 사용하지 않는다.
//MYSQL에서는 쓰인다.


STID              AVG
---------- ----------
10104      73.3333333
10101      76.6666667
10102      93.3333333
10103      76.6666667
10105      63.3333333
10106      66.6666667
SQL>  SELECT x.stid, x.AVG FROM (
  2     SELECT stid, AVG( score ) AS AVG
  3     FROM scoret GROUP BY stid) x;

STID              AVG
---------- ----------
10104      73.3333333
10101      76.6666667
10102      93.3333333
10103      76.6666667
10105      63.3333333
10106      66.6666667

6 개의 행이 선택되었습니다.
SQL>  SELECT y.name, x.AVG FROM (
  2     SELECT stid, AVG( score ) AS AVG
  3     FROM scoret GROUP BY stid) x , studentt y WHERE x.stid = y.stid ;

NAME                      AVG
------------------ ----------
박기자             73.3333333
홍길동             76.6666667
고길동             93.3333333
이기자             76.6666667
김영삼             63.3333333
김대중             66.6666667

Constraint in Oracle

-primary key , foreign key, check, unique, not null

 

SQL> ALTER TABLE STUDENTT ADD CONSTRAINT PK_STUDENTT_STID PRIMARY KEY (STID);

테이블이 변경되었습니다.

-참조 무결성 : FK 쪽에는 PK에 없는 데이터는 존재하면 안된다

SQL> ALTER TABLE SCORET ADD CONSTRAINT FK_SCORET_STID
      2  FOREIGN KEY(STID) REFERENCES STUDENTT (STID);
SQL> DELETE FROM STUDENTT WHERE STID = '10101';
DELETE FROM STUDENTT WHERE STID = '10101'
*
1행에 오류:
ORA-02292: 무결성 제약조건(HR.FK_SCORET_STID)이 위배되었습니다- 자식 레코드가
발견되었습니다
SQL> ALTER TABLE SCORET ADD CONSTRAINT CH_SCORET_SCORE
  2  CHECK (SCORE >= 0 AND SCORE <= 100);

테이블이 변경되었습니다.

SQL> ALTER TABLE SUBJECTT ADD CONSTRAINT UQ_SUBJECT_SUBID
  2  UNIQUE (SUBID);

테이블이 변경되었습니다.
SQL> INSERT INTO SUBJECTT VALUES(NULL, '없음0');

-> NULL 값의 중복은 허용한다

SQL> INSERT INTO SUBJECTT VALUES('KOR1', '없음0');
INSERT INTO SUBJECTT VALUES('KOR1', '없음0')
*
1행에 오류:
ORA-00001: 무결성 제약 조건(HR.UQ_SUBJECT_SUBID)에 위배됩니다

왜? NOT NULL은 보장안함  / NO DUPLICATE 는 보장 

 

 권장사항 : constraint 는 테스트 끝나고서 ,,,,
         ( 회원가입 담당자가 일 다 안한 상태에서 게시판 담당자가 테스트 하려면? 절레절레)
 
-- constraint 지우기(제약 걸어있을 시 순서대로)

SQL> ALTER TABLE subjectt DROP CONSTRAINT uq_subject_subid;

테이블이 변경되었습니다.

SQL>
SQL> ALTER TABLE scoret DROP CONSTRAINT fk_scoret_stid;

테이블이 변경되었습니다.

SQL>
SQL> ALTER TABLE studentt DROP CONSTRAINT pk_studentt_stid;

 

-방명록 만들기

SQL> CREATE TABLE BANGMYUNG_T(
  2  NO INT,
  3  GUL VARCHAR2(100),
  4  THE_THIME DATE
  5  );

테이블이 생성되었습니다.

 


SQL> CREATE SEQUENCE SEQ_BANGMYUNG;

시퀀스가 생성되었습니다.
SQL> INSERT INTO BANGMYUNG_T VALUES(SEQ_BANGMYUNG.NEXTVAL, '만나서 반갑습니다', SYSDATE);

1 개의 행이 만들어졌습니다.

--MYSQL 

CREATE TABLE BANGMYUNG_T(

    NO INT AUTO_INCREMENT PRIMARY KEY,

    GUL VARCHAR(100),

    THE_TIME DATETIME

);

 

INSERT INTO BANGMYUNG_T VALUES (DAFAULT, '만나서 반갑습니다', NOW());

 

오라클 디비 JDBC

package Lecture.Week2;

import java.sql.*;

public class Test20 {
    public static void main(String[] args) throws Exception{
        Class.forName("oracle.jdbc.driver.OracleDriver");
        Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521/XE","HR","HR");
        System.out.println(conn.getClass().getName());

        Statement stmt = conn.createStatement();

        String gul = "HelloWorld";
        //String sql = "INSERT INTO BANGMYUNG_T VALUES" + "(SEQ_BANGMYUNG.NEXTVAL, '만나서 반갑습니다'" +" ,SYSDATE)";

        String sql = "INSERT INTO bangmyung_t VALUES " +
                "( seq_bangmyung.NEXTVAL, '" + gul +"'" +
                ", SYSDATE )";

        stmt.executeUpdate(sql);
        conn.close();
    }
}
package Lecture.Week2;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

class BangMyungV0{
    private Integer no = null;
    public void setNo (Integer i ){no = i;}
    public Integer getNo() {return no;}


    /*멤버 변수는 private 하게 선언하는게 바람직함
    * 멤버 변수는 오버라이딩 개념이 없다
    * 조상에서 생성된 변수는 자손에서 재 정의하는게 바람직하지 않다
    * 멤버 변수는 get, set으로 가져와야 한다. */
    private  String gul = null;
    public  void setGul(String i ){gul = i;}
    public String getGul() {return gul;}

    private String theTime = null;
    public void setTheTime(String i){theTime = i;}
    public String getTheTime(){return theTime;}
}


public class Test21 {
    public static void main(String[] args)throws Exception{
        Class.forName("oracle.jdbc.driver.OracleDriver");

        Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521/XE","HR","HR");
        Statement stmt = conn.createStatement();
        String sql = "select * from bangmyung_t";

        ResultSet rs = stmt.executeQuery(sql);

        List<BangMyungV0> ls = new ArrayList<BangMyungV0>();
        while(rs.next()){
            BangMyungV0 vo = new BangMyungV0();

            vo.setNo(rs.getInt("no"));
            vo.setGul(rs.getString("gul"));
            vo.setTheTime(rs.getString("THE_THIME"));

            ls.add(vo);
        }

        while (rs.next()){
            String no = rs.getString("no");
            String gul = rs.getString("gul");
            String THE_THIME = rs.getString("THE_THIME");

            System.out.println(no);
            System.out.println(gul);
            System.out.println(THE_THIME);
        }
        rs.close();

        stmt.close();
        conn.close();

        for(BangMyungV0 t: ls ){
            System.out.println(t.getNo() + "\t" + t.getGul() + "\t" + t.getTheTime()+"\t");
        }


    }
}

-함수로 선언해서 재사용성을 높였다 

SQL 문장에서 에러 -> stmt.executeUpdate(sql) 에서 예외발생 -> conn.close() 실행 안한다 -> conn은 빨리 끊어야한다. 

 

위의 내용을 왜 아래처럼 짤까? -> executeUpdate 상황에서 에러나도 conn.close()는 되어야 한다?

-> 되어야 한다. finally 영역 도입 시 try 영역에서 에러가 나건 안나건 무조건 실행한다. 

-> stmt.close() con.close()를 finally로 옮김

-> 변수 선언 정리

 

getConnection() 에서 에러나면? conn stmt 는 null 인채로 finally 행

stmt.close() conn.close()가 stmt, conn이 null 이 아닐 때만 호출하도록 개선했다.

 

-try -catch문 사용

package Lecture.Week2;

import java.sql.*;

class BangMyungV0{
    private Integer no = null;
    public void setNo (Integer i ){no = i;}
    public Integer getNo() {return no;}
    private  String gul = null;
    public  void setGul(String i ){gul = i;}
    public String getGul() {return gul;}

    private String theTime = null;
    public void setTheTime(String i){theTime = i;}
    public String getTheTime(){return theTime;}
}


public class Test21 {
    public static void addGul(String gul) throws Exception {
        Connection conn = null;
        Statement stmt = null;

        try{
            conn = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521/XE","HR","HR");

 String sql = "INSERT INTO bangmyung_t VALUES " +
                    "( seq_bangmyung.NEXTVAL, '" + gul +"'" +
                    ", SYSDATE )";
            stmt.executeUpdate(sql);
        }
        catch (Exception e){

        }finally { //try에서 에러가 나건 안나건 무조건 거친다.
            if (stmt != null) {stmt.close();}
            if(conn != null){conn.close();}
        }

public static void main(String[] args)throws Exception{
        Class.forName("oracle.jdbc.driver.OracleDriver");
        addGul("HelloWORLD");

트랜잭션 : 두 개 이상의 업데이트 문장을 하나처럼 묶어주는 작업 

-> LOG 에 쌓인 걸 한번에 반영하거나 버린다  

-> 동일한 CON에서 작업한 내용만 트랜잭션으로 묶을 수 있다. 

 

-비디오 가게에서의 예

대여 : INSERT
대여중 : 대여 기능에 들어가야함
예치금 --
대여중 -> 삭제
대여 기록 -> INSERT
연체금 -> 예치금에서 뺀다
대여중 -> 대여 가능
댓글 입력
댓글 수 ++ 

 

 

//autocommit

SQL> create table txt_tx(
  2  data int
  3  );
package Lecture.Week2;

import java.sql.DriverManager;
import java.sql.*;

/*conn을 통해서 executeUpdate를 하면 LOG를 거쳐 TABLE에 저장된다
* JDBC는 AUTOCOMMIT을 지원한다
* executeUpdate 시에 무조건 commit이 자동으로 먹는다
* 원래 커밋이 자동으로 먹게 되어있다. -> 로그에 잠시 머물다가 곧바로 커밋으로 올라감
* conn.setAutoCommit(false) // commit이 자동으로 먹지 않는다.*/

public class Test23 {
public static void main(String[] args) throws Exception{
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521/XE","HR","HR");

conn.setAutoCommit(false);

Statement stmt = conn.createStatement();
stmt.executeUpdate("insert into txt_tx values (101)");
stmt.executeUpdate("insert into txt_tx values (102)");
stmt.executeUpdate("insert into txt_tx values (103)");
stmt.executeUpdate("insert into txt_tx values (104)");

stmt.close();
conn.commit();//테이블에 올려버린다
// conn.rollback();//로그를 그냥 비운다 => 테이블에 반영이 안된다
conn.close();
}
}
SQL> select * from txt_tx;

      DATA
----------
       100
       101
       102
       103
       104
package Lecture.Week2;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;

public class Test23_2 {
        public static void main(String[] args) throws Exception{
            Class.forName("oracle.jdbc.driver.OracleDriver");
            Connection conn= null;
            Statement stmt = null;

//            conn.setAutoCommit(false); -> 있으면 롤백 에러 잡고 아니면 commit되서 올라감

            try{
                conn = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521/XE","HR","HR");

                stmt = conn.createStatement();
                stmt.executeUpdate("insert into txt_tx values (105)");
                stmt.executeUpdate("insert into txt_tx values (106)");
                stmt.executeUpdate("insert into txt_tx values (107)");
                stmt.executeUpdate("insert into txt_tx values (108)");

                conn.commit();//테이블에 올려버린다

                //에러가 나면 앞에있는 것도 몽땅 다 롤백

            }catch (Exception e){//try 에서 에러가 안나면 catch에서 안잡힘
                if(conn != null){ conn.rollback();}
                throw e;
            }finally {
                if(stmt != null) stmt.close();
                if(conn != null)conn.close();
            }
        }
    }


//향상된 코드 
반응형

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

제주에서 자바_Week3_2  (0) 2019.07.30
제주에서 자바_Week3_1  (0) 2019.07.29
제주에서 자바_Week2_2  (0) 2019.07.24
제주에서 자바_Week2_1  (0) 2019.07.22
제주에서 자바_Week1  (0) 2019.07.20

+ Recent posts