반응형

1.게시판을 만들어보자^^ (로그인 필요 없이 간단한 게시판 형태)

 

<oracle db>

SQL> create table temp20t(
  2  data char(3) null
  3  );

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

SQL> insert into temp20t values('abc');

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

SQL> insert into temp20t values(null);

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

Q. NULL 4글자가 입력 가능? null은 빈값을 의미

insert into temp20t values('null'); -> null과 'null'은 구분하자

 

% select * from temp20t where data = null;        NO

    select * from temp20t where data is null;        YES

(null 과의 비교는 is를 이용한다)

 

<문제점>

package main;

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

public class Test110 {
	public static void main(String[] args) throws Exception {
		String data = "xyz";
		
		Class.forName("oracle.jdbc.driver.OracleDriver");
		Connection conn = DriverManager.getConnection(
			"jdbc:oracle:thin:@127.0.0.1:1521/XE","HR","HR");
		
		
		//sql 이어 붙일 땐 ''에 주의해야한다
		//data에 null 일 때는 에러 -> 왜? null이라는 문자열이 들어가는 것으로 됨
		//나름 해결책 이지만 null 가능 필드가 2개면 경우의 수가 4개 / 3개면 8개
		//이런 문제 떄문에 현업에서는 PreparedStatement를 더 선호한다.
		//현업에서는 아예 char 는 무조건 4자리 이상을 잡게 하는 경우도 있다.
		String sql =(data != null) ? 
				"insert into temp20t values ('"+data+"')":
				"insert into temp20t values(null)";
		Statement stmt = conn.createStatement();
		
		stmt.executeUpdate(sql);
		
		stmt.close();
		conn.close();
	}

}

<해결책>

package main;

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

public class Test111 {
	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 가 어떤 sql 문장이든 실행하는 범용적인데 반해서
		 * preparedStatement 는 생성시에 준비한 그 문장만 실행 할 수 있다
		 * 대신 ?  영역을  setString , setInteger등을 이용하여 채울 수 있다
		 * (순서가 1부터 시작하는 것에 주의)
		 * execute 시에 매개변수 없음에 주의*/
		
		String sql = "insert into temp20t values(?)";
		PreparedStatement stmt = conn.prepareStatement(sql); //sql문장 전용의 바구니
//		stmt.setString(1,"LEE");
		stmt.setString(1, null);//에러 안남 null값이 들어간 행이 생김
		//이걸 쓰면 null 값을 넣을 때 ''를 붙여야 할지를 결정하기 위해 이런저런 고민 할 필요가 없어진다(위의 코드처럼)
		stmt.executeUpdate();
		
		stmt.close();
		conn.close();
	}
}

/*SQL> select * from temp20t;

DATA
------
abc

xyz
xyz
xyz
LEE -> 컴파일 시 들어감*/

AUTOBOXING / UNBOXING

package main;

public class Test112 {
	//매개변수로 String 을 0..*개를 넣어도 에러가 안나는 선언 방식
	public static void test2(Object...args){
		for(int i = 0; i < args.length; i++){
			if(args[i] == null){
				System.out.println("null");
			}else if(args[i] instanceof Integer){
				int r = ((Integer)args[i]).intValue();
				System.out.println("null");
			}else if(args[i] instanceof Double){
				double r = ((Double)args[i]).doubleValue();
				System.out.println(r+0.1);
			}else if(args[i] instanceof String){
				System.out.println((String)args[i]);
			}
		}
		
	}
	
	public static void test(String... args){
		System.out.println(args.length);
	}
	//Object arg_1 = 100; -> 100을 new Integer(100)로 자동변환
	//Object arg_3 = 3.14; => 3.14를 new Double(3.14)로 자동변환
	public static void main(String[] args){
		
		test2(100, "Hello", 3.14, null);
		
		test("apple");
		test();
		test("apple", "banana");
	}
}


/*autoboxing unboxing
 * 
 * Object i = 100;(o)
 * int i = j;(x)
 * 
 * Integer i = 100(o)
 * int j = i;(o)*/

<프레임워크 만들기>

package main;

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

public class Test113 {
	public static int update(String sql, Object... args) throws Exception{
		int rc = 0;

		Class.forName("oracle.jdbc.driver.OracleDriver");
		Connection conn = DriverManager.getConnection(
			"jdbc:oracle:thin:@127.0.0.1:1521/XE","HR","HR");
		PreparedStatement stmt = conn.prepareStatement(sql); //sql문장 전용의 바구니
	
		for(int i = 0; i < args.length; i++){
			if(args[i] == null){
				stmt.setObject(i+1, null);
			}else if(args[i] instanceof Integer){
				int r = ((Integer)args[i]).intValue();
				stmt.setInt(i+1, r);
			}else if(args[i] instanceof Double){
				double r = ((Double)args[i]).doubleValue();
				stmt.setDouble(i+1, r);
			}else if(args[i] instanceof String){
				stmt.setString(i+1, (String)args[i]);
			}
		}
		rc = stmt.executeUpdate();
		
		stmt.close();
		conn.close();
		return rc;
	}
	
	public static void main(String[] args) throws Exception{
		String sql = "insert into temp20t values(?,?)";
		update(sql, "KIM",100);
		
	}
}
/*프레임워크 만들기 */

<Anonymous class>

package main;

interface ITemp{
	public void print();//인스턴스 못만듬 , abstract 클래스이기 떄문에 
	//클래스 : 참조형변수 선언/  인스턴스 생성 / 상속해서 인스턴스 선언
}
public class Test114 {
	public static void main(String[] args){
		/*Anonymous class : 이름 없는 클래스
		 * -> 조상은 있음 : ITemp
		 * ITemp를 상속받고 -> 모든 메소드 오버라이딩 해주고 
		 * 이름이 없어서 재사용은 불가능하다
		 * -클래스 선언하고 , 인스턴스 생성하고는 끝
		 * t가 왜 가리킬 수 있는 거지? A t = new B() 자손이 조상에서 오버라이딩한 것을 가져올 수 있기 때문에 */
		
		final int i = 100; //i = 로컬변수다  -> final로 선언해주면 어나니머스 클래스에서 사용할 수 있음 / 객체 지향 개념
		
		ITemp t = new ITemp(){
			public void print(){
				System.out.println("HelloWorld" + i);
			}
		};
		t.print();//자손 인스턴스가 소환
	}
}

JSP 기본 문법

  • JSP 페이지
    • <%-- JSP 주석  --%>
    • <% 스클립틀릿(자바 명령문) %>  -> 웹 서버 쪽 실행
    • <%= 익스프레션 %> -> 자바식 (연산자 포함식, 메서드 호출식) -> 웹 서버 쪽 실행 => 웹 브라우저로 실행
    • ${  익스프레션 랭귀지 } - 빠른 간단한 연산 가능
<HTML>
	<BODY>
    	<% int total = 0;
        	for(int cnt = 0; cnt <= 100; cnt++)
            	total += cnt;
       	%> //스클립틀릿 -> 자바 명령문
        
        <%= total %> //익스프레션 -> 자바식(연산자 포함식, 메서드 호출식)
	</BODY>
</HTML>
  • 서블릿 클래스
    • 서블릿 클래스 골격 선언 -> service 함수 메서드 선언 -> 명령 -> 파일로 텍스트 출력
//서블릿 클래스 골격 선언
public class Servlet extends HttpServlet{
	//service 함수 메서드 선언
	public void service(HttpServletRequest request, HttpServletResponse response) 
    					throws IOException ServletException{
                        
        //명령
		for(int cnt = 1; cnt <= 100; cnt++)
        	total += cnt;
            //파일로 텍스트 출력
            PrintWriter out = response.getWriter();
            out.println("<HTML>");
            out.println("<BODY>");
            out.println("%d",total);
            out.println("</BODY>");
            out.println("</HTML>");
    }
}
 
        

<web.xml> 에 서블릿 등록

<servlet>
	<servlet-name>Servlet-test</servlet-name>
    <servlet-class>servlet</servlet-class>
</servlet> //서블릿 클래스 이름이 들어감

<servlet-mapping>
	<servlet-name>servlet-test</servlet-name>
    <url-pattern>/servlet</url-pattern>
</servlet-mapping> //서블릿 클래스 호출할 때 사용할 URL 들어감
	

 

<쿠키 : 웹 브라우저 쪽에서 데이터 입력, 수정, 삭제, 조회 >

-> 결제 모듈에서 사용 / A, B, C 서블릿이 각자 있고 각자의 유저가 쿠키를 생성하여 따로 저장할 수 있음 (장바구니 , 로그인 정보에 사용)

package study3;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


/*http://localhost:8081/study3/state?use=readCookie
 * 요청 -> 응답, 요청의 방법이 두가지 get / post // get : 엽서 / post : 택배
 * 
 * 엽서와 주소의 내용을 구분하는 선의 역할 : ?
 * ? 오른쪽 내용 : key=value 형태로 구성
 *  request.getParameter를 이용하여 추출할 수 있따
 *  거의 대부분이 get방식이고 form 에서 method = "POST"로 지정된 경우만 POST방식*/
public class StateServlet extends HttpServlet{

	@Override
	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		String use = request.getParameter("use");
		
		if("addCookie".equals(use)){
			Cookie ck = new Cookie("name", "apple");
			response.addCookie(ck);
		}else if("readCookie".equals(use)){
			Cookie[] cks = request.getCookies();
			if(cks != null){
				for(int i = 0; i < cks.length; i++){
					String l = cks[i].getName() + ","+ cks[i].getValue();
					System.out.println(l);
				}
			}else{
				System.out.println("Cookie is null");
			}
		}
		
		System.out.println(use);
	}
	//addcookie 후 read 쿠키를 하니 
	/*Cookie is null
	readCookie
	getCookie
	
	/*쿠키는 서블렛과 다르게 브라우저에서 생성 -> 서버에서 알 수 있는 방법은 응답이 넘어갈 때(addCookie -> response 멤버 변수)
	*요청할 때 쿠키를 물고온다 / 응답 내보낼때만 서블릿이 조작할 수 있음 
	*/
}

세션사용

      최초 getSession() 호출시에는 고유 넘버가 없이 요청이 들어온다
       * 기억장소 생성 - Map<String, Object> 형태
       * 고유 넘버 생성
       * JSESSIONID 키 값으로 고유 넘버를 쿠키에 저장
       * 
       * 그 이후에 getSession() 호출 : 고유 넘버 물고 왔으니 그걸로 기억장소 찾는다
       * "브라우저 마다 개별적인 기억장소가 생성된다"
package study3;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

//session으로 접근 가능하게 만드세요 
// http://localhost:8081/study3/state?use=readCookie

public class SessionServlet extends HttpServlet {

   @Override
   protected void service(HttpServletRequest request, HttpServletResponse response) 
         throws ServletException, IOException {
         
      HttpSession session = request.getSession();
      System.out.println( session.isNew() );
      
      //true
      //JSESSIONID,2C7E8E0D95817C0E56780B2B4644924D
      
      session.setAttribute("apple", "Object!!");
      Object value = session.getAttribute("apple");
      System.out.println(value.toString());
      
      /*false
		Object!!
       	*/
      
      /*최초 getSession() 호출시에는 고유 넘버가 없이 요청이 들어온다
       * 기억장소 생성 - Map<String, Object> 형태
       * 고유 넘버 생성
       * JSESSIONID 키 값으로 고유 넘버를 쿠키에 저장
       * 
       * 그 이후에 getSession() 호출 : 고유 넘버 물고 왔으니 그걸로 기억장소 찾는다
       * 
       * "브라우저 마다 개별적인 기억장소가 생성된다"*/
   }

}

 

<jsp>

<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
    <%!
    
    int i = 0;
    
    %>
    <%
    
    int j = 0;
    
    %>
http://www.w3.org/TR/html4/loose.dtd">

<%=i++ %>
<%=j++ %>

<%-- jsp 주석 ,html 파일 요청하듯이 요청한다(web.xml 수정할 필요 없다)
i = 멤버 변수 / j = 로컬 변수의 느낌이 난다
jsp 파일을 요청하면 톰캣은 이것을 *.java 파일로 변환한다(서블릿코드)
이것은 컴파일하고 인스턴스를 만들어 적재하고 인스턴스 재활용 한다

서블릿 이후에 asp의 등장으로 위기를 느낀 자바쪽에서 ASP 비슷하게 만든 게 JSP
  http://192.168.2.11:8081/study/Test115.jsp --%>
package study3;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class JSPServlet extends HttpServlet{
	
	private ServletContext application = null;
	//대표적인 함수 getRealPath
	private ServletConfig config = null;

	
	//적재된 서블릿의 시점을 가져오는 것이 init 함수
	

	@Override
	public void init(ServletConfig config) throws ServletException {
		this.config = config;
		application = config.getServletContext();
	}

	/*-------------------------------------------------------------------------------- 
	 *<%! ... %> 은 여기에 온다
	 *    int i = 0;
	 *-------------------------------------------------------------------*/

	@Override
	public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		HttpSession session = request.getSession();
		PrintWriter out = response.getWriter();
		/*--------------------------------------------------
		 * <%....%>은 여기에 온다
		 *     int j = 0;
		 * --------------------------------------------------*/
		/*--------------------------------------------------
		 * <%=... %은 print()로 감싸서 나온다
		 * 	<%=i++ %>
		 * out.println(i++);
			<%=j++ %>
		   out.println(j++);
		   
		   Test115.jsp > 유사한 형태로 변환되고 컴파일되고 인스턴스 만들어지고 적재된 뒤에 실행한다
		 * --------------------------------------------------*/
		out.flush();
		out.close();
	
	}
}

 

어디에 들어있어야 하는지, 왜 되는지 정확하게 알아보기!

 

문제

1. 구구단 배경색 새로고침 시 변경

 

<%@ page contentType="text/html;charset=UTF-8"%><%!
    String getColor(){
        char[] chs = "0123456789abcdef".toCharArray();
        StringBuffer sb = new StringBuffer();

        for(int i=1;i<=6;i++) {
            int index = (int)(Math.random() * 16);
            sb.append(chs[index]);
        }
        return sb.toString();
    }
%>
<html>
<body>
    <table border ="1" bordercolor="black" cellspacing = "0" align="center" cellpadding="7">
    <% for(int i=2;i<=9;i++){ %>
        <tr>
      <% for(int j=1;j<=9;j++){ %>
            <% String color = getColor(); %>
            <td bgColor="#<%=color%>" >
        <%=i%> * <%=j%> = <%=i*j%>
            </td>
      <% } %>
        </tr>
    <% } %>
</body>
</html>

 

2. errortrace.jsp 만들어서 찍어보기

 

<error.jsp>

<%@ page contentType="text/html; charset=utf-8" isErrorPage="true"
	pageEncoding="EUC-KR"%>
<%
	Exception e = (Exception) session.getAttribute("error");
%>
<!DOCTYPE html>
<html>
<body>
	<%
		StackTraceElement[] st = e.getStackTrace();
		for (int i = 0; i < st.length; i++) {
	%>
	<%=st[i]%>
	<%
		}
	%>
</body>
</html>

1. 채팅방을 만들어보자

 

create table talk_room_t(
no number(5),
apple char(4),
banana char(4),
orange char(4)
);
//톡방 만들기
 insert into talk_room_t values(0,'1234','2345','3456');
 
 create table talk_t(
  talk_no number(6),
  room_no number(6),
  content varchar2(123)
 );
 
 create sequence seq_talk;
  //시퀀스 제작
 insert into talk_t values(seq_talk.nextval, 0, 'blabla....');
  //talk_t에 시퀀스 넘버를 받아 값 넣음
 commit;

<talk_login.jsp>

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="EUC-KR"%>
<!DOCTYPE html>
<html>

</head>
<body>
talk_login.jsp<br/>

<%-- POST : 택배, GET : 엽서
	GET 방식 일 떄는 주소 옆에 붙어서가고 POST 방식일 때는 내부에 숨겨서 간다
	-talk_login2.jsp?roomNo=0&pwd=abcd
	
	강사습관 : html을 생성하지 않은 곳은 2를 붙이더라 --%>
<form method = "POST" action = "talk_login2.jsp">
	<input type= "text" name = "roomNo" size = "4"/>
	<input type= "password" name = "pwd" size = "8"/>
	<input type= "submit"/>
	</form>
</body>
</html>

<talk_login2.jsp>

<%@ page import="study3.Util" pageEncoding="EUC-KR"%>
<%

String ctxPath = request.getContextPath();

//문자열 숫자 변환 시에 에러 발생될 수 있다.
int roomNo = Util.parseInt(request.getParameter("roomNo"));
String pwd = request.getParameter("pwd");

if(roomNo == -1 || pwd == null  || "".equals(pwd)){
	response.sendRedirect("/study3/talk_login.jsp");
	
	//sendRedirect 코드 이후의 코드는 의미 없다
	
	return;
}

Exception err = null;

try{
	if(err == null)
		throw new Exception();
}catch(Exception e){
	err = e;
}

if(err != null)
{
	response.sendRedirect(ctxPath + "/error.jsp");
	return;
}
%>

<%--
talk_login2.jsp
see : study3.Util.class

 --%>

 


<TalkRoomVo.jsp>

package study3;

public class TalkRoomVO {
	public Integer getRoomNo() {
		return roomNo;
	}
	public void setRoomNo(Integer roomNo) {
		this.roomNo = roomNo;
	}
	public String getApple() {
		return apple;
	}
	public void setApple(String apple) {
		this.apple = apple;
	}
	public String getBanana() {
		return banana;
	}
	public void setBanana(String banana) {
		this.banana = banana;
	}
	public String getOrange() {
		return orange;
	}
	public void setOrange(String orange) {
		this.orange = orange;
	}
	private Integer roomNo = null;
	private String apple = null;
	private String banana = null;
	private String orange = null;

}

<talk_login2.jsp>

<%@ page import="study3.Util" pageEncoding="EUC-KR" %>
<%@ page import="java.sql.Connection" %>
<%@ page import="java.sql.DriverManager" %>
<%@ page import="java.sql.PreparedStatement" %>
<%@ page import="java.sql.ResultSet" %>
<%@ page import="study3.TalkRoomVO" %>
<%
	
	String ctxPath = request.getContextPath();
	
	//문자열 숫자 변환 시에 에러 발생될 수 있다.
	int roomNo = Util.parseInt(request.getParameter("roomNo"));
	String pwd = request.getParameter("pwd");
	
	if(roomNo == -1 || pwd == null  || "".equals(pwd)){
		response.sendRedirect("/study3/talk_login.jsp");
		return;
		//sendRedirect 코드 이후의 코드는 의미 없다
		
	}
	
	Exception err = null;
	TalkRoomVO vo = null;
	
	try{
			Class.forName("oracle.jdbc.driver.OracleDriver");
			Connection conn = DriverManager.getConnection(
				"jdbc:oracle:thin:@127.0.0.1:1521/XE","HR","HR");
			String sql = "select * from talk_room_t where no = ?";
			PreparedStatement stmt = conn.prepareStatement(sql);
			stmt.setInt(1,roomNo);
			ResultSet rs = stmt.executeQuery();
			
			System.out.println(rs);
			System.out.println(conn);
			if(rs.next()){
				vo = new TalkRoomVO();
				vo.setRoomNo(rs.getInt("no"));
				vo.setApple(rs.getString("apple"));
				vo.setBanana(rs.getString("banana"));
				vo.setOrange(rs.getString("orange"));
			}
			rs.close();
			stmt.close();
			conn.close();
			
	}catch(Exception e){
		err = e;
	}
	System.out.println(vo);
	
	if(err != null)
	{
		response.sendRedirect(ctxPath + "/error.jsp");
		return;
	}
	//해당 방이 없는 경우
	if(vo == null){
		response.sendRedirect(ctxPath + "/talk_login.jsp");
	}
	else if(vo.getApple().equals(pwd)){
		Cookie ck = new Cookie("level", "apple");
		response.addCookie(ck);
		
		Cookie ck2 = new Cookie("roomNo", String.valueOf(roomNo));
		response.addCookie(ck2);
		
		response.sendRedirect(ctxPath + "/talk_view_apple.jsp");
	}
	else if(vo.getBanana().equals(pwd)){
		Cookie ck = new Cookie("level", "banana");
		response.addCookie(ck);
		
		Cookie ck2 = new Cookie("roomNo", String.valueOf(roomNo));
		response.addCookie(ck2);
		
		response.sendRedirect(ctxPath + "/talk_view_banana.jsp");
	}
	else if(vo.getOrange().equals(pwd)){
		Cookie ck = new Cookie("level", "Orange");
		response.addCookie(ck);
		
		Cookie ck2 = new Cookie("roomNo", String.valueOf(roomNo));
		response.addCookie(ck2);
		
		response.sendRedirect(ctxPath + "/talk_view_orange.jsp");
		
	}
	else{
		response.sendRedirect(ctxPath + "/talk_login.jsp");
	}
	
%>

<%--
talk_login2.jsp
see : study3.Util.class

 --%>

<talk_view_apple.jsp>

<%@ page contentType="text/html;charset=UTF-8" import="study3.Util, study3.TalkVO, java.util.*, java.sql.*" %>

<% String ctxPath = request.getContextPath();

    Cookie[] cks = request.getCookies();
    if(cks == null){
        response.sendRedirect(ctxPath + "/talk_login.jsp");
        return;
    }
    int roomNo = -1;
    String level = null;

    for(int i=0;i<cks.length;i++){
        if(cks[i].getName().equals("level")){
            level = cks[i].getValue();
        }else if (cks[i].getName().equals("roomNo")){
            roomNo=Util.parseInt(cks[i].getValue());
        }
    }

    if(level == null || !level.equals("apple")){
        response.sendRedirect(ctxPath + "/talk_login.jsp");
        return;
    }
    
    
    List<TalkVO> rl = new ArrayList<TalkVO>();
   	Exception err = null;
   	
   	try{
   		Class.forName("oracle.jdbc.driver.OracleDriver");
		Connection conn = DriverManager.getConnection(
			"jdbc:oracle:thin:@127.0.0.1:1521/XE","HR","HR");
   		String sql = "select * from talk_t where room_no = ? order by talk_no desc";
   		PreparedStatement stmt = conn.prepareStatement(sql);
   		stmt.setInt(1, roomNo);
   		ResultSet rs = stmt.executeQuery();
   		
   		while(rs.next()){
   			TalkVO vo = new TalkVO();
   			vo.setTalkNo(rs.getInt("talk_no"));
   			vo.setRoomNo(rs.getInt("room_no"));
   			vo.setContent(rs.getString("content"));
   			rl.add(vo);
   		}
   		
   		rs.close();
   		stmt.close();
   		conn.close();
   		
   	}catch(Exception e){
   		err = e;
   	}
   	
   	if(err != null){
   		response.sendRedirect(ctxPath + "/error.jsp");
   		return;
   	}%>
   
<!DOCTYPE html>
<body>
talk_view_apple.jsp
				<table border ="1" cellspacing = "0" cellpadding="8">
				<%for(TalkVO vo : rl){%><tr>
					<td bgcolor ="hotpink"> <%=vo.getTalkNo()%> </td>
					<td bgcolor = "babypink"> <%=vo.getRoomNo()%> </td>
					<td bgcolor = "skyblue"> <%=vo.getContent()%></td>
				</tr><%}%></table>	
<%= rl %>
</body>
</DOCTYPEhtml><%@ page contentType="text/html;charset=UTF-8" import="study3.Util, study3.TalkVO, java.util.*, java.sql.*" %>

<% String ctxPath = request.getContextPath();

    Cookie[] cks = request.getCookies();
    if(cks == null){
        response.sendRedirect(ctxPath + "/talk_login.jsp");
        return;
    }
    int roomNo = -1;
    String level = null;

    for(int i=0;i<cks.length;i++){
        if(cks[i].getName().equals("level")){
            level = cks[i].getValue();
        }else if (cks[i].getName().equals("roomNo")){
            roomNo=Util.parseInt(cks[i].getValue());
        }
    }

    if(level == null || !level.equals("apple")){
        response.sendRedirect(ctxPath + "/talk_login.jsp");
        return;
    }
    
    
    List<TalkVO> rl = new ArrayList<TalkVO>();
   	Exception err = null;
   	
   	try{
   		Class.forName("oracle.jdbc.driver.OracleDriver");
		Connection conn = DriverManager.getConnection(
			"jdbc:oracle:thin:@127.0.0.1:1521/XE","HR","HR");
   		String sql = "select * from talk_t where room_no = ? order by talk_no desc";
   		PreparedStatement stmt = conn.prepareStatement(sql);
   		stmt.setInt(1, roomNo);
   		ResultSet rs = stmt.executeQuery();
   		
   		while(rs.next()){
   			TalkVO vo = new TalkVO();
   			vo.setTalkNo(rs.getInt("talk_no"));
   			vo.setRoomNo(rs.getInt("room_no"));
   			vo.setContent(rs.getString("content"));
   			rl.add(vo);
   		}
   		
   		rs.close();
   		stmt.close();
   		conn.close();
   		
   	}catch(Exception e){
   		err = e;
   	}
   	
   	if(err != null){
   		response.sendRedirect(ctxPath + "/error.jsp");
   		return;
   	}%>
   
<!DOCTYPE html>
<body>
talk_view_apple.jsp
				<table border ="1" cellspacing = "0" cellpadding="8">
				<%for(TalkVO vo : rl){%><tr>
					<td bgcolor ="hotpink"> <%=vo.getTalkNo()%> </td>
					<td bgcolor = "babypink"> <%=vo.getRoomNo()%> </td>
					<td bgcolor = "skyblue"> <%=vo.getContent()%></td>
				</tr><%}%></table>	
<%= rl %>
</body>
</DOCTYPEhtml>

<게시판삭제, 더하기>

<talk_view_apple.jsp>

<%@ page contentType="text/html;charset=UTF-8" import="study3.Util, study3.TalkVO, java.util.*, java.sql.*" %>

<% String ctxPath = request.getContextPath();


	int roomNo = -1;
	String level = null;
	
    Cookie[] cks = request.getCookies();
    if(cks == null){
        response.sendRedirect(ctxPath + "/talk_login.jsp");
        return;
    }

    for(int i=0;i<cks.length;i++){
        if(cks[i].getName().equals("level")){
            level = cks[i].getValue();
        }else if (cks[i].getName().equals("roomNo")){
            roomNo=Util.parseInt(cks[i].getValue());
        }
    }

    if(level == null || !level.equals("apple")){
        response.sendRedirect(ctxPath + "/talk_login.jsp");
        return;
    }
    
    
    List<TalkVO> rl = new ArrayList<TalkVO>();
   	Exception err = null;
   	
   	try{
   		Class.forName("oracle.jdbc.driver.OracleDriver");
		Connection conn = DriverManager.getConnection(
			"jdbc:oracle:thin:@127.0.0.1:1521/XE","HR","HR");
   		String sql = "select * from talk_t where room_no = ? order by talk_no desc";
   		PreparedStatement stmt = conn.prepareStatement(sql);
   		stmt.setInt(1, roomNo);
   		ResultSet rs = stmt.executeQuery();
   		
   		while(rs.next()){
   			TalkVO vo = new TalkVO();
   			vo.setTalkNo(rs.getInt("talk_no"));
   			vo.setRoomNo(rs.getInt("room_no"));
   			vo.setContent(rs.getString("content"));
   			rl.add(vo);
   		}
   		
   		rs.close();
   		stmt.close();
   		conn.close();
   		
   	}catch(Exception e){
   		err = e;
   	}
   	
   	if(err != null){
   		response.sendRedirect(ctxPath + "/error.jsp");
   		return;
   	}%>
   
<!DOCTYPE html>
<body>
talk_view_apple.jsp

				<table border ="1" cellspacing = "0" cellpadding="8">
					<tr>
						<td width = "80" align = "center">번호</td>
						<td width = "420" align = "center">내용</td>
						<td width = "420" align = "center">&nbsp;</td>
					</tr>
				<%for(TalkVO vo : rl){%><tr>
					<td bgcolor ="hotpink"> <%=vo.getTalkNo()%> </td>
					<td bgcolor = "skyblue"> <%= vo.getContent() %> </td>
					<td><a href = "talk_del2.jsp?talkNo=<%=vo.getTalkNo()%>">삭제 </a></td>
				</tr><%	
				}%></table>	
		<br/>
		<br/>
				
	<form method = "POST" action = "talk_add2.jsp">
		<textarea rows = "7" cols = "40" name = "content"></textarea>
		<br/><input type = "submit">
	
	</form>
<%= rl %>
</body>
</DOCTYPEhtml>

<talk_del2.jsp>

<%@ page import="study3.Util" %>
<%@ page import="java.sql.DriverManager" %>
<%@ page import="java.sql.Connection" %>
<%@ page import="java.sql.PreparedStatement" %>
<%@ page contentType="text/html;charset=UTF-8"%><%
    String ctxPath = request.getContextPath();
    int talkNo = Util.parseInt(request.getParameter("talkNo"));
    int roomNo = -1;
    String level = null;
    Exception err = null;

    Cookie[] cks = request.getCookies();
    if(cks == null){
        response.sendRedirect(ctxPath + "/talk_login.jsp");
        return;
    }

    for (int i = 0; i < cks.length; i++) {
        if(cks[i].getName().equals("level"))
            level = cks[i].getValue();
        else if(cks[i].getName().equals("roomNo"))
            roomNo = Util.parseInt(cks[i].getValue());
    }

    if(level == null || roomNo == -1 || level.equals("apple")){
        response.sendRedirect(ctxPath + "/talk_login.jsp");
        return;
    }

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

        String sql = "delete from talk_t where room_no =? and talk_no = ?";
        PreparedStatement ps = conn.prepareStatement(sql);
        ps.setInt(1, roomNo);
        ps.setInt(2, talkNo);

        ps.executeUpdate();

        ps.close();
        conn.close();

    }catch (Exception e ) { err = e; }

    if(err != null){
    	System.out.println(err);
        response.sendRedirect(ctxPath + "/error.jsp");
        return;
    } else{
        response.sendRedirect(ctxPath + "/talk_view_apple.jsp");
    }
%>
<html>
<body>

</body>
</html>

<talk_add2.jsp>

<%@ page pageEncoding="EUC-KR"%>
<%@ page import= "study3.Util"%>
<%@ page import= "java.sql.*"%>
    
    <%
    request.setCharacterEncoding("UTF-8");
    String ctxPath = request.getContextPath();
	int roomNo = -1;
	String level = null;
	String content = request.getParameter("content");
	
    Cookie[] cks = request.getCookies();
    if(cks == null){
        response.sendRedirect(ctxPath + "/talk_login.jsp");
        return;
    }

    for(int i=0;i<cks.length;i++){
        if(cks[i].getName().equals("level")){
            level = cks[i].getValue();
            
        }else if (cks[i].getName().equals("roomNo")){
            roomNo=Util.parseInt(cks[i].getValue());
        }
    }
    
    if(level == null || roomNo == -1 || level.equals("orange")){
    	response.sendRedirect(ctxPath + "/talk_login.jsp");
    	return;
    }
    
    Exception err = null;
    try {

        Class.forName("oracle.jdbc.driver.OracleDriver");
        Connection conn = DriverManager.getConnection(
				"jdbc:oracle:thin:@127.0.0.1:1521/XE","HR","HR");
		String sql = "insert into talk_t values (seq_talk.nextval, ?,?)";
		
		PreparedStatement stmt = conn.prepareStatement(sql);
		stmt.setInt(1,roomNo);
		stmt.setString(2,content);
		
		stmt.executeUpdate();
		
		stmt.close();
        conn.close();

    }
   	catch(Exception e ){
   		err = e;
   		}
    
    if(err != null){
    	response.sendRedirect(ctxPath + "/error.jsp");
    }
    else if(level.equals("apple")){
    	response.sendRedirect(ctxPath + "/talk_view_apple.jsp");
    }
    else if(level.equals("banana")){
    	response.sendRedirect(ctxPath + "/talk_view_banana.jsp");
    }
    System.out.println(level);
    System.out.println(roomNo);
    %>

<Util.java>

package study3;

public class Util {
	public static int parseInt(String l){
		try{
			int r = Integer.parseInt(l);
			return r;
		}catch(Exception e){
			return -1;
		}
	}
	
	
	public static String h( String l ){
		if(l == null || l.equals("")){
			return l;
		}
		
		try{
    		byte[] bs = l.getBytes("8859_1");
    		l = new String(bs, "UTF-8");
    	}catch(Exception e){
    		
    	}
		return l;
	}

}

 

<talk_view_banana.jsp>

<%@ page contentType="text/html;charset=UTF-8" import="study3.Util, study3.TalkVO, java.util.*, java.sql.*" %>

<% String ctxPath = request.getContextPath();


	int roomNo = -1;
	String level = null;
	
    Cookie[] cks = request.getCookies();
    if(cks == null){
        response.sendRedirect(ctxPath + "/talk_login.jsp");
        return;
    }

    for(int i=0;i<cks.length;i++){
        if(cks[i].getName().equals("level")){
            level = cks[i].getValue();
        }else if (cks[i].getName().equals("roomNo")){
            roomNo=Util.parseInt(cks[i].getValue());
        }
    }

    if(level == null || !level.equals("banana")){
        response.sendRedirect(ctxPath + "/talk_login.jsp");
        return;
    }
    
    
    List<TalkVO> rl = new ArrayList<TalkVO>();
   	Exception err = null;
   	
   	try{
   		Class.forName("oracle.jdbc.driver.OracleDriver");
		Connection conn = DriverManager.getConnection(
			"jdbc:oracle:thin:@127.0.0.1:1521/XE","HR","HR");
   		String sql = "select * from talk_t where room_no = ? order by talk_no desc";
   		PreparedStatement stmt = conn.prepareStatement(sql);
   		stmt.setInt(1, roomNo);
   		ResultSet rs = stmt.executeQuery();
   		
   		while(rs.next()){
   			TalkVO vo = new TalkVO();
   			vo.setTalkNo(rs.getInt("talk_no"));
   			vo.setRoomNo(rs.getInt("room_no"));
   			vo.setContent(rs.getString("content"));
   			rl.add(vo);
   		}
   		
   		rs.close();
   		stmt.close();
   		conn.close();
   		
   	}catch(Exception e){
   		err = e;
   	}
   	
   	if(err != null){
   		response.sendRedirect(ctxPath + "/error.jsp");
   		return;
   	}%>
   
<!DOCTYPE html>
<body>
talk_view_apple.jsp

				<table border ="1" cellspacing = "0" cellpadding="8">
					<tr>
						<td width = "80" align = "center">번호</td>
						<td width = "420" align = "center">내용</td>
					</tr>
				<%for(TalkVO vo : rl){%><tr>
					<td bgcolor ="hotpink"> <%=vo.getTalkNo()%> </td>
					<td bgcolor = "skyblue"> <%= vo.getContent() %> </td>
				</tr><%	
				}%></table>	
		<br/>
		<br/>
				
	<form method = "POST" action = "talk_add2.jsp">
		<textarea rows = "7" cols = "40" name = "content"></textarea>
		<br/><input type = "submit">
	
	</form>
<%= rl %>
</body>
</DOCTYPEhtml>

<talk_view_orange.jsp>

<%@ page contentType="text/html;charset=UTF-8" import="study3.Util, study3.TalkVO, java.util.*, java.sql.*" %>

<% String ctxPath = request.getContextPath();


	int roomNo = -1;
	String level = null;
	
    Cookie[] cks = request.getCookies();
    if(cks == null){
        response.sendRedirect(ctxPath + "/talk_login.jsp");
        return;
    }

    for(int i=0;i<cks.length;i++){
        if(cks[i].getName().equals("level")){
            level = cks[i].getValue();
        }else if (cks[i].getName().equals("roomNo")){
            roomNo=Util.parseInt(cks[i].getValue());
        }
    }

    if(level == null || !level.equals("orange")){
        response.sendRedirect(ctxPath + "/talk_login.jsp");
        return;
    }
    
    
    List<TalkVO> rl = new ArrayList<TalkVO>();
   	Exception err = null;
   	
   	try{
   		Class.forName("oracle.jdbc.driver.OracleDriver");
		Connection conn = DriverManager.getConnection(
			"jdbc:oracle:thin:@127.0.0.1:1521/XE","HR","HR");
   		String sql = "select * from talk_t where room_no = ? order by talk_no desc";
   		PreparedStatement stmt = conn.prepareStatement(sql);
   		stmt.setInt(1, roomNo);
   		ResultSet rs = stmt.executeQuery();
   		
   		while(rs.next()){
   			TalkVO vo = new TalkVO();
   			vo.setTalkNo(rs.getInt("talk_no"));
   			vo.setRoomNo(rs.getInt("room_no"));
   			vo.setContent(rs.getString("content"));
   			rl.add(vo);
   		}
   		
   		rs.close();
   		stmt.close();
   		conn.close();
   		
   	}catch(Exception e){
   		err = e;
   	}
   	
   	if(err != null){
   		response.sendRedirect(ctxPath + "/error.jsp");
   		return;
   	}%>
   
<!DOCTYPE html>
<body>
talk_view_apple.jsp

				<table border ="1" cellspacing = "0" cellpadding="8">
					<tr>
						<td width = "80" align = "center">번호</td>
						<td width = "420" align = "center">내용</td>
					</tr>
				<%for(TalkVO vo : rl){%><tr>
					<td bgcolor ="hotpink"> <%=vo.getTalkNo()%> </td>
					<td bgcolor = "skyblue"> <%= vo.getContent() %> </td>
				</tr><%	
				}%></table>	
		<br/>
		<br/>
<%= rl %>
</body>
</DOCTYPEhtml>

<jsp 문법>

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="EUC-KR"
    isELIgnored = "true"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>

</head>
<body>

	${100 + 100 };
</body>
</html>

//${100 + 100}; 은 서버에서 동작하고 200이라는 결과를 만들어 내어서 응답에 포함시켰따고 봐야한다.

최근 jsp 에서는 간단한 연산을 - ${...} : EL Language 을 이용하여 할 수 있는 기술을 포함

 

-isELIgnored ="true" 가 설정되면 ${100 + 100 }은 EL이 아닌 단순 문자열로 인식한다(무시한다)

 

-실제로 html안은 복잡한 코드보다 단순한 코드가 훨씬 많다 
모든 작업을 EL로 처리가능하면 디자인 속도가 훨씬 빠를 것이다. 

-request.setAttribute 또는 session.setAttribute를 통해서 저장된 값은 키 값을 이용해서 EL에서 사용이 가능하다

정리 : session , request, application 3개 객체는 모두 
void setAttribute(String, Object),
Object getAttribute(String)
void removeAttribute(String) 을 지원한다

 

EL이 반응이 좋아서 확장한 기능인 jstl을 지원하게 되었다

-jstl : 태그를 사용하여 만든 언어

-> SGML 에서 태그를 처음 도입 => 문서를 전산화 할 수 있는 언어를 개발

-> MathML, MusicML, Postscript 등 파생된 서브셋이 엄청 많다 

-> pdf로 발전하여

-> XML, HTML,로 성공하였다

 

태그의 특징

- 최 외곽의 태그는 단 하나만 존재하야 한다

- 태그는 중첩해서 선언하지 않는다

- 속성은 시작태그에 선언한다

- 속성은 KEY = "VALUE" 또는 OR KEY = 'VALUE'

    => 단, ''안에 ''은 못온다

- 하나의 태그에서 속성은 두번 선언하지 않는다

- 시작태그가 있으면 반드시 끝 태그가 있다

 

 


파일업로드 

 

<web.xml>에 서블릿 등록

<servlet> <servlet-name>abcd9</servlet-name> <servlet-class>study3.FileUpServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>abcd9</servlet-name> <url-pattern>/fileup</url-pattern> </servlet-mapping>

 <Test122.jsp>

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="EUC-KR"%>
<!DOCTYPE html>
<html>
<body>

<!--  input type = "file" : 파일을 서버로 업로드 할 때 사용
이때 반드시 enctype = "multipart/form-data" 을 사용한다 

fileup 에 해당하는 서블릿은 cos.jar 파일의 MultipartRequest 를 이용하여 업로드를 처리하는 것이 일반적
-->
	<form method = "POST" action = "fileup" enctype = "multipart/form-data">
		<input type = "text" name = "title" size = "20">
		<input type = "file" name = "apple">
		<input type = "submit">
	</form>
</body>
</html>

<fileUpServlet.jsp>

package study3;

import java.io.IOException;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.oreilly.servlet.MultipartRequest;
import com.oreilly.servlet.multipart.DefaultFileRenamePolicy;

import java.io.InputStream;


public class FileUpServlet extends HttpServlet{
	private ServletContext application = null;
	

	@Override
	public void init(ServletConfig config) throws ServletException {
		application = config.getServletContext();
	}

	@Override
	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
			String l = process2(request);
			System.out.println(l);
	}
	
	/*request : 요청 , 브라우저에서 서버로 전달하는 개념
	 * request.getInputStream() 은 브라우저에서 서버로 전달되는 내용을 볼 수 있다
	 * 이 내용을 재구성하는 기능이 cos.jar 파일의 MultipartRequest 이다.
	 * .*/
	
	public String process(HttpServletRequest request) throws IOException{
		byte[] buf = new byte[1024];
		int len = 0;
		
		StringBuffer sb = new StringBuffer();
			
		InputStream in = request.getInputStream();
		
		while((len = in.read(buf)) != -1){
			sb.append(new String(buf, 0, len));
		}
		in.close();
		return sb.toString();

		
	}
	
	
	public String process2(HttpServletRequest request) throws IOException{
		
		//fileup 디렉터리의 실제 저장 위치(절대 경로) 값을 파악한다.
		String path = application.getRealPath("/WEB-INF/fileup");
		System.out.println(path);
		
		//cos.jar에서 제공되는 클래스
		//DefaultFileRenamePolicy :  이름이 겹칠 때 이름 바꿔서 올린다
		//따라서 올릴 때 이름과 서버에 올려진 이름이 다를 수 있따.
		MultipartRequest mpr = new MultipartRequest(
				request, path, 1024*1024*20, "UTF-8",
				new DefaultFileRenamePolicy());
		
		//업로드한 원래 파일이름
		String ofn = mpr.getOriginalFileName("apple");
		
		//중첩될 경우 이름을 바꾸어 저장하는 이름
		String fsn = mpr.getFilesystemName("apple");
		
		System.out.println(ofn +","+ fsn);
		
		//MultipartRequest 쓰면 request.getParameter 못쓴다. 
        // 대신 MultipartRequest 안의 getParameter 써야 한다.
     // 한글 처리도 내부에서 해주더라 !! ( "UTF-8"로 설정해서 
		String title = mpr.getParameter("title");
		System.out.print(title);
		
		System.out.print(path);
		return null;
		

	}
	

}

filedown

<web.xml>

<servlet> <servlet-name>abcd10</servlet-name> <servlet-class>study3.FileDownServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>abcd10</servlet-name> <url-pattern>/filedn</url-pattern> </servlet-mapping>

<Test123.jsp>

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="EUC-KR"%>
<!DOCTYPE html>
<html>
<body>
<!--  WEB-INF는 브라우저가 접근이 불가능하다 -->
	<a href = "WEB-INF/fileup/user.png">fileDown</a>
	<a href ="filedn?fsn=user.png">fileDown</a>
</body>
</html>

 

<fileDownServlet.jsp>

package study3;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class FileDownServlet extends HttpServlet {

	   @Override
	   protected void service(HttpServletRequest request, HttpServletResponse response) 
	         throws ServletException, IOException {
	      
	      String fsn = request.getParameter("fsn");
	      String ofn = request.getParameter("ofn");
	      
	      if(ofn == null){
	    	  ofn = fsn;
	      }
	      
	      String path = request.getServletContext().getRealPath("/WEB-INF/fileup");
	      
	      
	      /*전송 이전에 어떤 성경의 정보를 전달할 지를 먼저 브라우저에 통보한다 
	       * application/octet-stream 과 같은 것을 MIME TYPE이라고한다
	       * 
	       * 주의 : 반드시 응답이 내보내기 전에 쓰여져야한다*/
	      response.setContentType("application/octet-stream");
	      response.setHeader("content-disposition", "attachment;filename=" + ofn);
	      
	      //서버에 보관중인 파일을 읽어서 브라우저로 내보내는 전송 프로그램
	      InputStream in= new FileInputStream(path +"\\"+ fsn);
	      OutputStream out = response.getOutputStream();
	      
	      byte[] buf = new byte[1024*4];
	      int len = 0;
	      
	      while((len = in.read(buf)) != -1){
	    	  out.write(buf,0,len);
	    	  out.flush();
	      }
	      
	      out.close();
	      
	      in.close();
	   
	   }

	}
반응형

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

제주에서 자바_Week3_4  (0) 2019.08.11
##자바 헷갈리는 이론  (0) 2019.08.01
제주에서 자바_Week3_2  (0) 2019.07.30
제주에서 자바_Week3_1  (0) 2019.07.29
제주에서 자바_Week2_3  (0) 2019.07.25
반응형

1.방명록dao

 

2.서블렛의 한계

단점

-> 동기화 사용

package study3;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class LikeServlet extends HttpServlet{

	int i = 0;
	
	@Override
	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		System.out.println(this.toString());
		/*많은 사람들이 동시에 접속해도 동일한 문자열이 계속 찍힌다 -> 동일한 인스턴스가 재사용되고 있다.
		 * 메모리 관리에는 장점이다
		 * 한꺼번에 많이 들어와도 적게 메모리를 소모한다
		 * */
		PrintWriter out = response.getWriter();
		out.println("<html><body>");
		
		/*왜 synchronized ?
		 * 동시 요청 시 여러개의 쓰레드가 하나의 서블릿 인스턴스를 사용할 수 있다.*/
		synchronized(this){
			i = i+1;
			for(int i = 0 ; i < 20000; i ++){
				out.println(this.i);
				
			}
		}
	
		out.println("</body></html>");
		out.flush();
		out.close();
	}
}

 

 

3.서블렛 여러 기능

<ConfigServlet.java>

package study3;

import java.io.IOException;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ConfigServlet extends HttpServlet{

	@Override
	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		System.out.println("service");
		
		//컨텍스트 경로
		String l = request.getContextPath();
		System.out.println("getContextPath : "  + l);
		
		//ip 주소 다음 나오는 전체 경로
		String m = request.getRequestURI();
		System.out.println("getRequestURI : "  + m);
		
		//접속한 브라우저의 ip 주소값
		String n = request.getRemoteAddr();
		System.out.println("getRemoteAddr : "  + n);
		
		//접속한 브라우저와 운영체제 정보를 담은 문자열이 얻어진다
		//이것을 이용하여 모바일로 접근한 건지 컴으로 접근 한 건지 알수 있고 
		//모바일용 화면과 컴용 화면을 구분하여 제공할 수 도 있다.
		String o = request.getHeader("User-Agent");
		System.out.println("User-Agent : "  + o);
		

		/*getContextPath : /study3
		getRequestURI : /study3/config
		getRemoteAddr : 0:0:0:0:0:0:0:1
		User-Agent : Mozilla/5.0 (Windows NT 6.2; Win64; x64; Trident/7.0; rv:11.0) like Gecko	*/
		
	}

	/*init
service
service
service
service -> 서블릿의 인스턴스는 재활용 된다. 
인스턴스는 재활용을 위해 내부적으로 적재된다 => init
적재되는 시점에 호출되는 함수가 init - 최초 요청 시 에만 호출된다.*/
	@Override
	public void init(ServletConfig config) throws ServletException {
//		String val = config.getInitParameter("apple");
//		System.out.println(val);
		
		/*WEB-INF 폴더의 절대 경로값을 얻어온다
		 * 브라우저가 접근 못하는 폴더가 업로드 파일을 놓기에 가장 적합
		 * 허락받고 (돈내고) 다운 받을 때 FileInputStream 으로 읽어 내보낸다
		 * FileInputStream : 절대 경로를 필요로한다
		 * getRealPath : 유용하게 쓰인다.*/
		ServletContext application = config.getServletContext();
		String path = application.getRealPath("/WEB-INF/");
		System.out.println(path);
		
//		System.out.println("init");
	}
	/*blabla
C:\workspace3\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\study3\WEB-INF\
service*/
}

<LikeServlet.java>

package study3;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class LikeServlet extends HttpServlet{

	int i = 0;
	
	@Override
	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		System.out.println(this.toString());
		/*많은 사람들이 동시에 접속해도 동일한 문자열이 계속 찍힌다 -> 동일한 인스턴스가 재사용되고 있다.
		 * 메모리 관리에는 장점이다
		 * 한꺼번에 많이 들어와도 적게 메모리를 소모한다
		 * */
		PrintWriter out = response.getWriter();
		out.println("<html><body>");
		
		/*왜 synchronized ?
		 * 동시 요청 시 여러개의 쓰레드가 하나의 서블릿 인스턴스를 사용할 수 있다.*/
		synchronized(this){
			i = i+1;
			for(int i = 0 ; i < 20000; i ++){
				out.println(this.i);
				
			}
		}
	
		out.println("</body></html>");
		out.flush();
		out.close();
	}
}

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
	<servlet>
		<servlet-name>abcd5</servlet-name>
		<servlet-class>study3.LikeServlet</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name>abcd5</servlet-name>
		<url-pattern>/like</url-pattern>
	</servlet-mapping>
	
	
	<servlet>
		<servlet-name>abcd6</servlet-name>
		<servlet-class>study3.ConfigServlet</servlet-class>
		<init-param>
			<param-name>apple</param-name>
			<param-value>blabla</param-value>
		</init-param>
	</servlet>
	<servlet-mapping>
		<servlet-name>abcd6</servlet-name>
		<url-pattern>/config</url-pattern>
	</servlet-mapping>
	
	
</web-app>
반응형

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

##자바 헷갈리는 이론  (0) 2019.08.01
제주에서 자바_Week3_3  (0) 2019.07.31
제주에서 자바_Week3_1  (0) 2019.07.29
제주에서 자바_Week2_3  (0) 2019.07.25
제주에서 자바_Week2_2  (0) 2019.07.24
반응형

Day 1

 

1.아파치

아파치 소프트웨어 재단의 오픈소스 프로젝트. 일명 웹서버로 불리며, 클라이언트 요청이 왔을때만 응답하는 정적 웹페이지에 사용
  • 웹서버 = 80번 포트로 클라이언트 요청(POST,GET,DELETE)이 왔을때만 응답함.

  • 정적인 데이터만 처리한다.(HTML,CSS,이미지 등)

2.톰캣

dynamic(동적)인 웹을 만들기 위한 웹 컨테이너, 서블릿 컨테이너라고 불리며, 웹서버에서 정적으로 처리해야할 데이터를 제외한 JSP, ASP, PHP 등은 웹 컨테이너(톰캣)에게 전달한다.
  • WAS(Web Application Server)
  1. 컨테이너, 웹 컨테이너, 서블릿 컨테이너라고 부름
  2. JSP,서블릿처리,HTTP요청 수신 및 응답
  3. 아파치만 쓰면 정적인 웹페이지만 처리하므로 처리속도가 매우 빠르고 안정적이다.

<전반적인 서버 운영>

-톰캣 운영

C:\Users\USER>cd \

C:\>cd apa*

C:\apache-tomcat-8.0.45>cd bin

 

C:\apache-tomcat-8.0.45\conf\server.xml -> 8080 포트 => 8081 로 변경

 

C:\apache-tomcat-8.0.45\bin>startup.bat

 

-> ipconfig 후 ipv4 주소 + 8081  => http://192.168.2.95:8081/

 

  • web은 실제로 파일 다운로드 소켓 프로그램 기본과 같다
    • Client :  웹 브라우저
    • Server : 톰캣(Web Application Server : WAS) 

 

  • 브라우저 => 톰캣 접속 => 서버의 파일 다운받아 보여줌

 

  • 톰캣 서버 하나에는 여러개의 Web Application 이 설치 가능=> context
    • Context가 가져야 하는 것 : 홈 디렉터리, 접근 경로

   C:\StudyHome\ 생성 
   C:\StudyHome\WEB-INF\
   C:\StudyHome\WEB-INF\classes
   C:\StudyHome\WEB-INF\lib

 

클라이언트는 홈 디렉토리 아래의 모든 파일을 다운로드 가능하다

단, WEB-INF는 접근이 불가능하다(내부 설정파일 등을 놓는다)

 

classes : java class 파일을 놓는 곳

lib : 동작에 필요한 jar 파일을 놓는 곳

 

C:\StudyHome\WEB-INF>copy C:\apache-tomcat-8.0.45\webapps\ROOT\WEB-INF\web.xml
        1개 파일이 복사되었습니다.

-> WEB-INF 폴더에 web.xml 파일을 복사해 넣는다.

 

web.xml 이렇게 변경
http://xmlns.jcp.org/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                      http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
  version="3.1"
  metadata-complete="true">

= >기본적인 Context 설정은 되어있다 

=> 이것을 톰캣에 등록해야한다.

 

다시

->C:\apache-tomcat-8.0.45\conf / server.xml에서 변경

<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">
<Context docBase="C:\StudyHome" path="/study" reloadable="true"></Context>

-> 다시 C:\apache-tomcat-8.0.45\bin>startup.bat

 

->StudyHome/test.html 생성

<html>
    <body> HelloWorld : ^^*</body>
</html>

http://192.168.2.95:8081/study/test.html로 연결

 

흐름도

C:\StudyHome\apple\test.html로 복사

http://192.168.2.95:8081/study/apple/test.html

 

-docBase 디렉토리 하위 폴더의 파일은 폴더명을 경로명으로 바꾸어 접속 할 수있다

 

C:\StudyHome\WEB-INF\test.html로 복사

http://192.168.2.95:8081/WEB-INF/test.html

오류 !

-WEB-INF 는 특수한 의미를 갖는다
-> 브라우저에 공개치 않는다 

 

-javaWork 에 클래스를 만들어보자

C:\StudyHome>cd C:\JavaWork

 

HelloWorld2.java를 만들자

package apple;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import java.io.IOException;


public class HelloWorld2 extends HttpServlet{
public void service() throws IOException, ServletException{
}

}

C:\JavaWork>javac -d C:\StudyHome\WEB-INF\classes -classpath servlet-api.jar HelloWorld2.java

 

-HelloWorld2.java를 변경하자 -> 꼭 compile 하기!

-web.xml변경하자

<?xml version="1.0" encoding="ISO-8859-1"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1" metadata-complete="true"> <servlet> <servlet-name>abcd</servlet-name> <servlet-class>apple.HelloWorld2</servlet-class> </servlet> <servlet-mapping> <servlet-name>abcd</servlet-name> <url-pattern>/study01</url-pattern> </servlet-mapping> </web-app>

-다시 서버 돌려보자

http://192.168.2.95:8081/study/study01

 

<tomcat>

29-Jul-2019 12:19:34.131 정보 [main] org.apache.catalina.startup.Catalina.start Server startup in 2683 ms
HelloWorld2 

 

-HelloWorld2 다시 수정

package apple;
import javax.servlet.http.HttpServlet;
import javax.servlet.ServletException;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;

public class HelloWorld2 extends HttpServlet {
@Override
   public void service( HttpServletRequest request, 
      HttpServletResponse response)
      throws IOException, ServletException 
      {
         System.out.println("HelloWorld2");
PrintWriter out = response.getWriter();
out.println(""); out.println("    ");
out.println("HelloWorld 2: T 0 T *");
out.println("    "); out.println("");


out.close();
      }
   }
   

-> 이러고 서버 닫았다가 다시 키면 홈페이지에 out.println("HelloWorld 2: T 0 T *");  찍힌다

 

WEB-INF 사용 연결 방식

-> 서블릭의 동작 흐름

0. WAS 쪽에 적절한 설정이 되어 있다고 가정

1. 브라우저에서 /study/study01 으로 요청이 들어온다

2. /study 로 경로를 설정한 Context 있나?

3. 2.에서 찾은 contetxt 의 docBase 폴더 (C:\StudyHome) 아래의 /WEB-INF/web.xml찾음

4. url-pattern 중 / study01에 해당하는 설정 -> servlet-mapping 아래에 -> 서블릿 abcd라는 것을 지명하고 있음
    -서블릿은 서버쪽에서 동작하는 것

5. abcd로 이름 붙여진 서블릿 클래스가 있나? apple.HelloWorld2

6. apple.HelloWorld2 을 찾아 -> 인스턴스 생성 -> 오버라이딩 하는 service 함수호출한다

7. System.out.println ("HelloWorld2"); 은 서버쪽에서 찍힌다.

8. PrintWriter out = response.getWriter(); 를 이용하여 내보내는 것은 요청으로 들어온 브라우저 쪽으로 내보내진다

9. 요청했던 브라우저는 응답으로 전달된 내용을 받아 화면에 출력한다

 

<HelloWorld2.java> 변경한다
package apple;
import javax.servlet.http.HttpServlet;
import javax.servlet.ServletException;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;

public class HelloWorld2 extends HttpServlet {
@Override
   public void service( HttpServletRequest request, 
      HttpServletResponse response)
      throws IOException, ServletException 
      {
         System.out.println("HelloWorld2");
try{
Class.forName("oracle.jdbc.driver.OracleDriver");
}
catch(Exception e){
//에러가 난 정보를 역추적해서 출력해준다
e.printStackTrace();
}


PrintWriter out = response.getWriter();
out.println(""); out.println("    ");
out.println("HelloWorld 2: T 0 T *");
out.println("    "); out.println("");


out.close();
      }
   }
   

-ojdbc.jar => 현재 컴파일 하고 있는 StudyHome > WEB-INF > lib 폴더 안에 복사 붙여넣기 

   -> oracle db와 톰캣을 함께 사용할 수 있게 된다.

 

<HelloWorld2.java> 또 바꿔..

 

package apple;
import javax.servlet.http.HttpServlet;
import javax.servlet.ServletException;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;


public class HelloWorld2 extends HttpServlet {
@Override
   public void service( HttpServletRequest request, 
      HttpServletResponse response)
      throws IOException, ServletException 
      {
         System.out.println("HelloWorld2");
try{
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);
conn.close();
}
catch(Exception e){
e.printStackTrace();
}


PrintWriter out = response.getWriter();
out.println(""); out.println("    ");
out.println("HelloWorld 2: T 0 T *");
out.println("    "); out.println("");


out.close();
      }
   }
   

-> 컴파일 하고 서버 돌리면 톰캣에 요렇게 찍힘

Context.reload Reloading Context with name [/study] is completed
HelloWorld2
oracle.jdbc.driver.T4CConnection@6b77a082
package apple;
import javax.servlet.http.HttpServlet;
import javax.servlet.ServletException;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import java.sql.*;

public class HelloWorld2 extends HttpServlet {
@Override
   public void service( HttpServletRequest request, 
      HttpServletResponse response)
      throws IOException, ServletException 
      {
         System.out.println("HelloWorld2");
String theTime = null;
try{
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 SYSDATE FROM DUAL";
ResultSet rs = stmt.executeQuery(sql);

if(rs.next()) {
theTime = rs.getString(1);
}
rs.close();

stmt.close();
conn.close();
}
catch(Exception e){
e.printStackTrace();
}


PrintWriter out = response.getWriter();
out.println(""); out.println("    ");
out.println("HelloWorld 2: T 0 T *" + theTime);
out.println("    "); out.println("");


out.close();
      }
   }
   

-> 이렇게하고 서버 실행하면 

HelloWorld 2: T 0 T *2019-07-29 14:28:26.0

<이클립스 다이나믹 프로젝트>

-프로젝트 -> context로 인식 -> src를 서버와 연결(add and remove) -> xml 변경 후


<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1"> <servlet> <servlet-name>abcd</servlet-name> <servlet-class>study2.HelloWorld3</servlet-class> </servlet> <servlet-mapping> <servlet-name>abcd</servlet-name> <url-pattern>/study2</url-pattern> </servlet-mapping> </web-app>

-> .java에서 Run as tomcat 서버로 돌리면 완성

 

<HelloWorld3.java>

 

package study2;

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

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class HelloWorld3 extends HttpServlet {

   @Override
   public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      // TODO Auto-generated method stub

      List ls = new ArrayList();
      try {
         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 no, gul, THE_THIME FROM bangmyung_t";
         ResultSet rs = stmt.executeQuery(sql);

         while (rs.next()) {
            BangMyungVO vo = new BangMyungVO();
            vo.setNo(rs.getInt(1));
            vo.setGul(rs.getString(2));
            vo.setTheTime(rs.getString(3));
            ls.add(vo);
         }
         rs.close();
         stmt.close();
         conn.close();
      } catch (Exception e) {
         e.printStackTrace();
      }
      response.setContentType("text/html; charset=euc-kr");
      PrintWriter out = response.getWriter();
      out.println("");       out.println("   ");
      for (BangMyungVO vo : ls) {
         out.println(vo.getNo() + "\t" + vo.getGul() + "\t" + vo.getTheTime());
      }
      out.println("   ");       out.println("");
      out.close();
   }

}
<BangMyungVO.java>

package study2;

public class BangMyungVO {
public Integer getNo() {
return no;
}
public void setNo(Integer no) {
this.no = no;
}
public String getGul() {
return gul;
}
public void setGul(String gul) {
this.gul = gul;
}
public String getTheTime() {
return theTime;
}
public void setTheTime(String theTime) {
this.theTime = theTime;
}
private Integer no = null;
private String gul = null;
private String theTime = null;
}

<test_01.html>


<!DOCTYPE html> <head> <body> test_01.html <!-- cellspacing="0" : 셀 간 간격 cellpadding="12" : 셀의 벽과 내용과의 간격 border="1" : 경계줄의 굵기 bgcolor="#ccddee" 배경색, 각각 16진수이고 앞 두자리 : red, 다음 두자리 : green, 마지막 두자리 : blue => RGB 값을 섞은 값 rowspan="3", colspan="2" : 엑셀에서의 셀 병합과 같은 개념 rowspan은 상하, colspan은 좌우 셀과 병합한다. <font size = "20px" face = "Impact">apple</font> : 브라우저에 깔린 글꼴만 가능 align ="left| center | right" : 내용물의 좌우 정렬 속성을 정한다 width : 셀의 폭을 결정함 같은 오와 열에 있는 것들은 자동으로 지정된 크기에 맞춰진다(일일이 모든 칸에 크기를 줄 필요가 없다) --> <table border="0" cellspacing="2" cellpadding="12"> <tr bgcolor="#aabbcc"> <td width = "400px" rowspan="2"><font size = "20px" face = "Impact">apple</font></td> <td width = "250px">banana</td> </tr> <tr> <td bgcolor="#ccddee">kiwi</td> </tr> <tr> <td colspan="2" bgcolor="#ccddee" align="center">kiwi</td> </tr> </table> </body> </html>



apple banana
kiwi
kiwi



 

반응형

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

제주에서 자바_Week3_3  (0) 2019.07.31
제주에서 자바_Week3_2  (0) 2019.07.30
제주에서 자바_Week2_3  (0) 2019.07.25
제주에서 자바_Week2_2  (0) 2019.07.24
제주에서 자바_Week2_1  (0) 2019.07.22
반응형

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
반응형

Day 3

1. 데이터 베이스 설계 프로세스 

  1. 업무 분석
    • 명사, 동사 업무 정확하게 기술
    • 업무 파악에 도움되는 어떤 형태의 자료도 확보
    • 가능한 UI를 그려 가며 인터뷰 진행(설계에 결정적인 영향 끼침)
    • 경험이 중요
  2. 엔티티 도출 (Entity)
    • 추상 명사 중에서 PK로 구분되어지는 것이 Entity 가 된다
    • 기록될 만한 가치가 있는 정보인지 판별
    • PK : 단일 필드의 특징이 있어야 한다
      • Primary key (기본키)
        • 레코드를 구분하는 기준으로 사용되는 필드(들)
        • 예 ) 주민번호 , 사번, 군번,...
        • 주민번호처럼 두개의 필드가 결합해서 PK를 이룰 수도 있다
        • 3가지 성격
          • ND (NO DUPLICATE) : 중복되어서는 안된다
          • NN( NOT NULL) : 생략되어서는 안된다
          • NC (NO CHANGE) : 가급적 변경되어서는 안된다.
    • 엔티티 : ERD에서 사각형으로 표현
      • 예 ) 회원, 글, 과목, 학생
  3. 관계 도출(Relation) 
    • 엔티티들 사이에서 동사가 어울리게 존재 가능 -> 기록할 만한 가치가 있다면 그것이 관계
    • 예 ) 회원은 글을 쓴다(쓴다) - 학생은 과목을 수강한다(수강한다)
    • 3가지 종류
      • 1대1 대응 : Be 동사에 해당하는 관계 or 상속관계
        • ex) 사병은 군인이다 / 장교는 군인이다 / 군인은 군번을 구분된다
      • 1대다 대응 : 
        • 회원은 글을 쓴다.
      • 다대다 대응
        • 학생은 과목을 수강하고 -> 회원은 글을 읽는다 -> 추천한다
    • 관계의 물리적인 구현 방법
      • 일대일 대응 : 조상의 PK를 자손이 PK 이자 FK로 참조한다
      • 일대다 대응 : 다 쪽에서 일 쪽의 PK를 FK로 참조한다
      • 다대다 대응: 새로운 테이블 생성 -> 그 PK는 양쪽의 PK를 참조하는 FK를 결합하여 구성
  4. 속성(Attribute) 파악
    • 일반 명사 중 자료형과 값으로 표현될 수 있는 것들
      • 예) 성적, 글쓴 시간, 이름, 전화번호, 주소 ---
    • 엔티티 , Relation 에 1:1로 매핑하는 곳에 배치한다
    • 실제 구현시 필드에 해당
  5. ERD 구성
    • 2가지 종류 : 두가지 다 그릴 줄 알아야한다. 
      • 분석에 가까운 형태
      • 구현에 가까운 형태
    • 엔티티는 사각형, 관계는 마름모 
      관계는 화살표 OR 실선 (도착쪽이 PK)
      PK는 꽉찬 사탕 막대기 , 그 외 필드는 텅빈 사탕 막대기
      NOT NULL 필드는 굵은 글씨로 표기한다
    • 그릴때 용이한 많은 툴이 있다(유료)
      Microsoft Visio
    • 정규화 vs 비정규화
정규화 비정규화
More Table , Less Column Less Table, More Column
속도 느림 속도 빠름
테이블 구조 안정적 테이블 구조 자주 변경될 여지 O
자료 중복저장 허용 X(성적 있으면 등수 자동) 자료의 중복저장 허용O(속도를 위해 등수 필요)

=> 정규화를 중심으로 적절한 비정규화를 추구하는게 방향  / 경험이 가장 중요하다

ER 다이어그램 예시

6. FK (Foreign Key) :외래키

  • 다른 테이블의 PK로 쓰이는 필드를 내쪽에서 참조해서 쓰는 필드(들)
  • 성적 테이블에 stid , subid - 성적 테이블의 stid는 학생테이블에 쓰이는 의미를 가져다가 쓴다. "
    -> 성적테이블의 stid의 10101은 학생테이블 stid의 10101과 동일한 의미이다

7. 비디오 가게 만들기

비디오 가게 ER 다이어그램

8. 정규화

mysql> select stid, name, (kor1 + eng1 + mat1)/3 as avg from score2t;
+-------+-----------+---------+
| stid  | name      | avg     |
+-------+-----------+---------+
| 10101 | 홍길동    | 76.6667 |
| 10102 | 고길동    | 93.3333 |
| 10103 | 이기자    | 76.6667 |
| 10104 | 박기자    | 73.3333 |
| 10105 | 김영삼    | 63.3333 |
| 10106 | 김대중    | 66.6667 |
+-------+-----------+---------+
6 rows in set (0.00 sec)
  • 정규화
    • Less Column  : 테이블당 필드의 개수가 적다 - 5 ~ 12개
    • More Table : score2t 가 한개가 되는 걸 우리는 3개를 만들었다
    • 필드와 데이터의 중복 저장을 허용안한다(비디오점의 대여 여부) 
  • 비정규화 : More Column, Less Table 
    • 필드와 데이터의 중복 저장을 허용한다(속도 문제)

대부분 정규화를 기본으로 해서 적절한 비정규화를 도입한다.

#테이블의 껍데기만 만드는 것
mysql> create table student_xt as
    -> select stid, name, addr from score2t where 0 = 1;
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0
#테이블에 select 결과를 입력하는 것mysql> insert into student_xt select stid, name, addr from score2t where 1 = 1;
Query OK, 6 rows affected (0.02 sec)
Records: 6  Duplicates: 0  Warnings: 0

mysql> select * from student_xt;
+-------+-----------+-----------+
| stid  | name      | addr      |
+-------+-----------+-----------+
| 10101 | 홍길동    | 역삼동    |
| 10102 | 고길동    | 개포동    |
| 10103 | 이기자    | 역삼동    |
| 10104 | 박기자    | 한남동    |
| 10105 | 김영삼    | 홍제동    |
| 10106 | 김대중    | 한남동    |
+-------+-----------+-----------+
6 rows in set (0.02 sec)

 

#score_xt //하나도 흘리지 않고 새로운 테이블에 옮겨갈 때

mysql> create table score_xt as
    -> select stid, 'KOR1' as subid, kor1 as score from score2t where 0 =1;
Query OK, 0 rows affected (0.23 sec)
Records: 0  Duplicates: 0  Warnings: 0
mysql> insert into score_xt select stid, 'KOR1', kor1 as score from score2t where 1= 1;
Query OK, 6 rows affected (0.00 sec)
Records: 6  Duplicates: 0  Warnings: 0

mysql> insert into score_xt
    -> select stid, 'ENG1', eng1 as score from score2t where 1=1;
Query OK, 6 rows affected (0.00 sec)
Records: 6  Duplicates: 0  Warnings: 0

mysql> insert into score_xt
    -> select stid, 'MAT1', mat1 as score from score2t where 1=1;
Query OK, 6 rows affected (0.00 sec)
Records: 6  Duplicates: 0  Warnings: 0
mysql> select * from score_xt;
+-------+-------+-------+
| stid  | subid | score |
+-------+-------+-------+
| 10101 | KOR1  |    60 |
| 10102 | KOR1  |    90 |
| 10103 | KOR1  |    70 |
| 10104 | KOR1  |    80 |
| 10105 | KOR1  |    50 |
| 10106 | KOR1  |    60 |
| 10101 | ENG1  |    80 |
| 10102 | ENG1  |    90 |
| 10103 | ENG1  |    90 |
| 10104 | ENG1  |    70 |
| 10105 | ENG1  |    60 |
| 10106 | ENG1  |    80 |
| 10101 | MAT1  |    90 |
| 10102 | MAT1  |   100 |
| 10103 | MAT1  |    70 |
| 10104 | MAT1  |    70 |
| 10105 | MAT1  |    80 |
| 10106 | MAT1  |    60 |
+-------+-------+-------+
18 rows in set (0.00 sec)

#비정규화 된 설계에서 정규화 된 설계로 옮길 수도 있고

정규화된 설계에서 비정규화 된 설계로 옮길 수도 있어야 한다. 

 

9. JOIN -> 서브쿼리와 유사

studentt : stid (pk) <- scoret : stid(fk)

 

-대부분의 join은 pk - fk 사이에서 일어난다 

 

mysql>select * from studentt INNER JOIN scoret ON studentt.stid = scoret.stid;
//studentt에 있는 pk(stid)를 참조 받아 두 테이블을 조인시킴
+-------+-----------+-----------+-------+-------+-------+
| stId  | name      | addr      | stId  | subId | score |
+-------+-----------+-----------+-------+-------+-------+
| 10101 | 홍길동    | 역삼동    | 10101 | KOR1  |   100 |
| 10101 | 홍길동    | 역삼동    | 10101 | ENG1  |   100 |
| 10101 | 홍길동    | 역삼동    | 10101 | MAT1  |   100 |
| 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 |
| 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 |
+-------+-----------+-----------+-------+-------+-------+

- INNER JOIN : PK - FK 데이터가 일치하는 레코드를 짜매준다. 

 mysql>SELECT name, addr, score From studentt INNER JOIN scoret ON studentt.stid = scoret.stid WHERE subid = 'MAT1';
//join을 이용하면 흩어진 데이터를 통합해서 보여지게 할 수 있다 (서브 쿼리도 가능 , 헌대 성능이 틀리다) 
-> 해서 같은 결과를 만들되 성능이 향상되게 만드는 것이 SQL 튜닝의 영역
Q. subjectt , scoret를 inner join해서 10101 국어1 90..이런식으로 나오게
mysql> select stid,name,score from subjectt INNER JOIN scoret ON subjectt.subid = scoret.subid;

+-------+---------+-------+
| stid  | name    | score |
+-------+---------+-------+
| 10101 | 국어1   |   100 |
| 10101 | 영어1   |   100 |
| 10101 | 수학1   |   100 |
| 10102 | 국어1   |    90 |
| 10102 | 수학1   |    90 |
| 10102 | 영어1   |   100 |
| 10103 | 국어1   |    70 |
| 10104 | 국어1   |    80 |
| 10105 | 국어1   |    50 |
| 10106 | 국어1   |    60 |
| 10103 | 영어1   |    90 |
| 10104 | 영어1   |    70 |
| 10105 | 영어1   |    60 |
| 10106 | 영어1   |    80 |
| 10103 | 수학1   |    70 |
| 10104 | 수학1   |    70 |
| 10105 | 수학1   |    80 |
| 10106 | 수학1   |    60 |
+-------+---------+-------+
18 rows in set (0.00 sec)
mysql> select stid,name,score, subjectt.subid from subjectt INNER JOIN scoret ON subjectt.subid = scoret.subid;
//같은이름의 subid 가져오려면 어디서 가져와야하는지 명시 해야한다.
+-------+---------+-------+-------+
| stid  | name    | score | subid |
+-------+---------+-------+-------+
| 10101 | 국어1   |   100 | KOR1  |
| 10101 | 영어1   |   100 | ENG1  |
| 10101 | 수학1   |   100 | MAT1  |
| 10102 | 국어1   |    90 | KOR1  |
| 10102 | 수학1   |    90 | MAT1  |
| 10102 | 영어1   |   100 | ENG1  |
| 10103 | 국어1   |    70 | KOR1  |
| 10104 | 국어1   |    80 | KOR1  |
| 10105 | 국어1   |    50 | KOR1  |
| 10106 | 국어1   |    60 | KOR1  |
| 10103 | 영어1   |    90 | ENG1  |
| 10104 | 영어1   |    70 | ENG1  |
| 10105 | 영어1   |    60 | ENG1  |
| 10106 | 영어1   |    80 | ENG1  |
| 10103 | 수학1   |    70 | MAT1  |
| 10104 | 수학1   |    70 | MAT1  |
| 10105 | 수학1   |    80 | MAT1  |
| 10106 | 수학1   |    60 | MAT1  |
+-------+---------+-------+-------+

 

//subjectt -> y로 scoret -> x로 각각 줄여서 쓰면 이렇게 가능

mysql> select stid, name, score, y.subid FROM scoret as x INNER JOIN subjectt as y ON y.subid = x.subid;
+-------+---------+-------+-------+
| stid  | name    | score | subid |
+-------+---------+-------+-------+
| 10101 | 국어1   |   100 | KOR1  |
| 10101 | 영어1   |   100 | ENG1  |
| 10101 | 수학1   |   100 | MAT1  |
| 10102 | 국어1   |    90 | KOR1  |
| 10102 | 수학1   |    90 | MAT1  |
| 10102 | 영어1   |   100 | ENG1  |
| 10103 | 국어1   |    70 | KOR1  |
| 10104 | 국어1   |    80 | KOR1  |
| 10105 | 국어1   |    50 | KOR1  |
| 10106 | 국어1   |    60 | KOR1  |
| 10103 | 영어1   |    90 | ENG1  |
| 10104 | 영어1   |    70 | ENG1  |
| 10105 | 영어1   |    60 | ENG1  |
| 10106 | 영어1   |    80 | ENG1  |
| 10103 | 수학1   |    70 | MAT1  |
| 10104 | 수학1   |    70 | MAT1  |
| 10105 | 수학1   |    80 | MAT1  |
| 10106 | 수학1   |    60 | MAT1  |
+-------+---------+-------+-------+
18 rows in set (0.00 sec)
mysql> SELECT stid, avg(score) as avg FROM scoret group by stid;
+-------+----------+
| stid  | avg      |
+-------+----------+
| 10101 | 100.0000 |
| 10102 |  93.3333 |
| 10103 |  76.6667 |
| 10104 |  73.3333 |
| 10105 |  63.3333 |
| 10106 |  66.6667 |
+-------+----------+
6 rows in set (0.00 sec)

//서브쿼리를 사용해 JOIN 할 수 있다.

mysql> SELECT * from (SELECT stid, avg(score) as avg FROM scoret group by stid) AS x INNER JOIN studentt AS y ON y.stid = x.stid;
+-------+----------+-------+-----------+-----------+
| stid  | avg      | stId  | name      | addr      |
+-------+----------+-------+-----------+-----------+
| 10101 | 100.0000 | 10101 | 홍길동    | 역삼동    |
| 10102 |  93.3333 | 10102 | 고길동    | 개포동    |
| 10103 |  76.6667 | 10103 | 이기자    | 역삼동    |
| 10104 |  73.3333 | 10104 | 박기자    | 한남동    |
| 10105 |  63.3333 | 10105 | 김영삼    | 홍제동    |
| 10106 |  66.6667 | 10106 | 김대중    | 한남동    |
+-------+----------+-------+-----------+-----------+
6 rows in set (0.00 sec)

10. 외부조인(OUTER JOIN)

mysql> SELECT * FROM subjectt INNER JOIN scoret ON subjectt.subid = scoret.subid;
//일단 subjectt 와 scoret를 조인
+-------+---------+-------+-------+-------+
| subId | name    | stId  | subId | score |
+-------+---------+-------+-------+-------+
| KOR1  | 국어1   | 10101 | KOR1  |   100 |
| ENG1  | 영어1   | 10101 | ENG1  |   100 |
| MAT1  | 수학1   | 10101 | MAT1  |   100 |
| 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 |
| 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 |
+-------+---------+-------+-------+-------+
18 rows in set (0.00 sec)
mysql> INSERT INTO subjectt values('PHY1', '물리');

//이렇게 물리가 추가 된다고 해도 성적데이터가 없으니 짜매어줄 대상이 없다

//회원가입이 되어도 글 쓴게 없으면 조인 걸어도 나타나지 않는다

//-> 한쪽 테이블에서만 보여지고 짜매지지 않는 경우라도 한 건 보여지게 만드는 형태의 조인이 OUTER JOIN이다

// 부족함(NULL 로 채움) 이 나타나는 반대편을 명시한다(LEFT)

mysql> SELECT * FROM subjectt LEFT OUTER JOIN scoret ON subjectt.subid = scoret.subid;
+-------+---------+-------+-------+-------+
| subId | name    | stId  | subId | score |
+-------+---------+-------+-------+-------+
| KOR1  | 국어1   | 10101 | KOR1  |   100 |
| ENG1  | 영어1   | 10101 | ENG1  |   100 |
| MAT1  | 수학1   | 10101 | MAT1  |   100 |
| 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 |
| 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  | NULL  |  NULL |
+-------+---------+-------+-------+-------+
19 rows in set (0.00 sec)

//count(*) 는 레코드의 갯수를 센다. 

//count(score) 은 해당 필드의 null 이 아닌 데이터의 갯수를 센다

mysql> SELECT subjectt.subid, count(score) FROM subjectt LEFT OUTER JOIN scoret ON subjectt.subid = scoret.subid GROUP BY subjectt.subid;
+-------+--------------+
| subid | count(score) |
+-------+--------------+
| ENG1  |            6 |
| KOR1  |            6 |
| MAT1  |            6 |
| PHY1  |            0 |
+-------+--------------+
4 rows in set (0.00 sec)

11. CONSTRAINT - 물리적인 제약 조건을 필드에 걸어준다 

-> 제약 조건 : CHECK, UNIQUE, PRIMARY KEY, FOREIGN KEY 4가지를 주로 쓴다 .

 

-> score 값을 (0 - 100) 사이의 값만 허용해야한다

mysql>ALTER TABLE scoret ADD CONSTRAINT CHECK_scoret_score CHECK (score >= 0 AND score <= 100);
mysql>insert into scoret valus ('10101', 'PHY1', 80);
ERROR 1264 (22003): Out of range value for column 'score' at row 1

 

지울떄는

mysql>ALTER TABLE scoret DROP CONSTRAINT CHECH_scoret_score;

 

-CHECK CONSTRAINT 는 WHERE 절의 조건을 이용하여 제약을 걸 수 있다. 

(IN, NOT IN, = != ... 을 사용할 수 있다

mysql> ALTER TABLE subjectt ADD CONSTRAINT PK_subjectt_subid
    -> PRIMARY KEY(subid);
Query OK, 0 rows affected (0.03 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> INSERT INTO subjectt VALUES('KOR1','국어');
ERROR 1062 (23000): Duplicate entry 'KOR1' for key 'PRIMARY'

-참조 무결성 : PK 쪽에서 쓰여진 데이터만 FK 쪽에서 쓰여질 수 있다

  • 회원 가입 해야 글 쓴다
  • 회원 등록 해야 예약한다
  • 등록된 아이템만 대여 가능하다 ...

#PRIMARY (subjectt) 쓰인적 있기 때문에 -> FOREIGN KEY부분에서 잘 쓸 수 있음

mysql> ALTER TABLE scoret ADD CONSTRAINT FX_scoret_subid
    -> FOREIGN KEY(subid) REFERENCES subjectt(subid);
Query OK, 20 rows affected (0.05 sec)
Records: 20  Duplicates: 0  Warnings: 0

mysql> INSERT INTO scoret VALUES ('10101', 'XXXX', 50);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`study`.`scoret`, CONSTRAINT `FX_scoret_subid` FOREIGN KEY (`subId`) REFERENCES `subjectt` (`subId`))

 

12. UNIQUE CONSTRAINT  : NULL 허용하는데 중복은 안된다 -> 테이블 분리할 때 사용

다대다로 만들고 -> UNIQUE 걸어서 -> 일대일처럼 동작

 

mysql> create table study05t(
    -> id int not null
    -> );
Query OK, 0 rows affected (0.02 sec)
mysql> ALTER TABLE study05t ADD CONSTRAINT UQ_study05t_id UNIQUE(id);
Query OK, 0 rows affected (0.03 sec)
Records: 0  Duplicates: 0  Warnings: 0

#일대일 상황에서 테이블 분리하는 방법 

-일단 다대다로 생각하고 테이블을 생성한다

-pk 중 하나에 unique constraint를 건다

-> 다대다 => 일대일로 바뀐다 .

 

#constraint 지우는 법

mysql> ALTER TABLE study05t DROP INDEX UQ_study05t_id;
Query OK, 1 row affected (0.04 sec)
Records: 1  Duplicates: 0  Warnings: 0

문제

짜장면집 결제 DB

중요한 핵심

반응형

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

제주에서 자바_Week3_1  (0) 2019.07.29
제주에서 자바_Week2_3  (0) 2019.07.25
제주에서 자바_Week2_1  (0) 2019.07.22
제주에서 자바_Week1  (0) 2019.07.20
4. 클래스  (0) 2019.05.29
반응형
# https://coding-factory.tistory.com/ 에서 그림 인용 

Day 1

1. 입력스트립(Input Stream) & 출력 스트림(Output Stream) 

- 자바 데이터는 스트림(Stream) 통해 입출력.

-스트림 ; 단일방향으로 연속적으로 흘러가는 것 

    => 순서대로 읽고, 순서대로 내보냄 / byte 단위로 전송

-프로그램 기준 데이터가 들어오면 입력 스트림 , 데이터가 나가면 출력 스트림

프로그램 기준 스트림

-Java.io 패키지 : 파일 시스템의 정보를 얻기 위한 file 클래스와 데이터 입출력하기 위한 다양한 입출력 스트림 클래스 제공

 Java.io 패키지의 주요 클래스

설명 

 File

 파일 시스템의 파일 정보를 얻기 위한 클래스 

 Console 

 콘솔로부터 문자를 입출력하기 위한 클래스 

 InputStream / OutputStream

 바이트 단위 입출력을 위한 최상위 입출력 스트림 클래스 

 FileInputStream / FileOuputStream

 바이트 단위 입출력을 위한 하위 스트림 클래스

 DataInputStream / DataOutputStream

 ObjectInputStream / ObjectOutputStream

 PrintStream

 BufferedInputStream / BufferedOutputStream

 Reader / Writer

 문자 단위 입출력을 위한 최상위 입출력 스트림 클래스

 FileReader / FileWriter

 문자 단위 입출력을 위한 하위 스트림 클래스

 InputStreamReader / OutputStreamWriter

 PrintWriter

 BufferedReader / BufferedWriter

 

  • 바이트 단위 입출력 스트림 : 그림, 멀티미디어, 문자 등 모든 종류의 데이터들 주고 받음
  • 문자 단위 입출력 스트림 : 오로지 문자만 주고 받을 수 있게 함

-inputStream : 바이트 기반 입력 스트림의 최상위 클래스(추상 클래스)

  • 모든 바이트 기반 입력 스트림은 이 클래스를 상속받아 만들어짐
  • FileInputStream
  • BufferedInputStream
  • DataInputStream

 메서드

설명 

 read()

입력 스트림으로부터 1바이트를 읽고 읽은 바이트를 리턴합니다. 

 read(byte[ ] b)

 입력 스트림으로부터 읽은 바이트들을 매개값으로 주어진 바이트 배열b에 저장하고 실제로 읽은 바이트 수를 리턴합니다.

 read(byte[] b, int off, int len)

입력 스트림으로부터 len개의 바이트만큼 읽고 매개값으로 주어진 바이트 배열 b[off]부터 len개까지 저장합니다. 그리고 실제로 읽은 바이트 수인 len개를 리턴합니다. 만약 len개를 모두 읽지 못하면 실제로 읽은 바이트 수를 리턴합니다. 

 close()

사용한 시스템 자원을 반납하고 입력스트림을 닫습니다. 

 

-OutputStream : 바이트 기반 출력 스트림의 최상위 클래스(추상 클래스) / 모든 바이트 기반 출력 스트림 클래스는 이 클래스를 상속받아 만들어짐

  • FileOutputStream : 파일에 저장하는 방법 제공
  • PrintStream
  • BufferedOutputStream
  • DataOutputStream

 메서드

설명 

 write(int b)

 출력 스트림으로부터 1바이트를 보냅니다.(b의 끝 1바이트) 

 write(byte[ ] b)

 출력 스트림으로부터 주어진 바이트 배열 b의 모든 바이트를 보냅니다.

 write(byte[ ] b, int off, int len)

 출력 스트림으로 주어진 바이트 배열 b[off]부터 len개까지의 바이트를 보냅니다. 

 flush() 

 버퍼에 잔류하는 모든 바이트를 출력합니다. 

 close()

 사용한 시스템 자원을 반납하고 출력 스트림을 닫습니다. 
package Lecture.Week2;

import java.io.*;

public class Test04 {
    public static void main(String[] args) throws IOException {
        InputStream in = new FileInputStream("a.dat" );
        OutputStream out = new FileOutputStream("b.dat");

        //복사 : dir *.dat 로 확인하고 type b.dat로 확인하고..
//        while(true){
//            int r = in.read();
//            if(r == -1){//더이상 읽을 것이 없을 때
//                break;
//            }
//            out.write(r);
//        }
//        out.close();
//        in.close();


        //엄청 많이 씀 -> 외우세용
        int r = 0;
        byte[] buf= new byte[1024*8];
        while(( r = in.read(buf)) != -1 ){// 더 읽을게 남아있다.
            out.write(buf, 0, r);
        }
        out.close();
        in.close();
    }
}

 

이를 데코레이터 패턴으로 이해하면 

-> out 이 가리키는 대상은
FileOutputStream("d.dat")에 저장하되
ObjectOutputStream 에서 제공하는 방법을 사용하게 된다.

ObjectOutputStream 은 writeInt writeDouble writeUTF 등을 제공
-> 전송 시에 안깨진다.
* ObjectOutputStream 은 writeInt WriteDouble writeUTF 등을 제공 -> 전송

 

*OutputStream InputStream : 전송단위 byte
* Reader Writer : 전송단위 char : 문자로 된 데이터 전송용

* char : 2바이트 , 유니코드 지원
* 유니코드 : 모든 글자를 다 포용하지 못한다
* -웬만한 건 글자는 포용한다 , 한글 영문 중국어 아랍어 일본어
* 확장 가능한 가변 길이를 가지는 문자체제 도입 UTF - 8.

*OutputStreamWriter InputStreamReader 는 char 입출력을 byte 입출력으로 전환해 줍니다
* 2byte -> 1byte로 바꿔줌*

 

 

 

 2. 자바 네트워크에 대한 이해

  • 네트워크란?
    • 다른 장치로 데이터를 이동시킬 수 있는 컴퓨터들 , 주변 장치들의 집합
    • 네트워크의 연결된 모든 장치들을 노드라고 한다
    • 복잡한 레이어의 대표적인 모델이 OSI 7계층
    • TCP / IP 모델 사용
  • IP 주소
    • 모든 호스트는 인터넷 주소(Host, IP 주소) 라 불리는 유일한 32비트 숫자로 구성된 주소 체계 이용
    • 32비트의 주소 체계를 IPv4 주소라고한다 -> 극복 IPv6
    • IP주소를 도메인이름으로 바꾸어 주는 시스템  : DNS
  • 포트 & 프로토콜
    • 포트 
      • 물리적 포트 
      • 논리적 포트
    • 프로토콜
      • 클라이언트와 서버간의 통신 규약
      • TCP / UDP
  • TCP / UDP
    • TCP / IP계층 모델은 4계층 구조(애플리케이션, 전송, 네트워크, 데이터 링크 계층)
    • 전송 계층에서 사용하는 프로토콜 TCP / UDP 
      • TCP (transmission Control Protocol) : 신뢰할 수 있는 프로토콜 / 데이터 상대 측까지 제대로 전달되었는지 확인 메시지를 주고 받음으로써 데이터의 송수신 상태를 점검
      • UDP(user datagram protocol) : 신뢰할 수 없는 프로토콜 / 데이터 보내기만 하고 제대로 전달되었는지 확인 하지 않음

3. TCP 통신 / Socket 프로그래밍

  • TCP 통신 방식 : 소켓 프로그래밍의 하나 / 스트림 통신 프로토콜 / 양쪽 소켓이 연결 상태여야만 가능 -> 연결 지향 프로토콜
    • 수신,  송신 측이 미리 연결 맺고 연결된 순서대로 데이터 교환해야함
    • Java.net 패키지에 관련 클래스들 미리 준비 해놓음
  • 소켓? 
    • 네트워크 끝 부분 / 실제 데이터가 어떻게 전송되는 지 상관하지 않고 read/write 인터페이스 제공
    • 네트워크 계층과 전송 계층이 캡슐화
    • TCP / IP 계층의 TCP를 지원하기 위해 Socket, ServerSocket 클래스 제공
    • 클라이언트 : socket 객체 생성, tcp 서버와 연결 시도
    • 서버 : SocketServer 객체 생성 , TCP 연결을 청취하여 클라이언트와 서버 연결
  • 소켓 스트림 

  • TCP 소켓은 java.net.Socket 클래스 의미
    • Socket 클래스 생성자
      • 예외 처리 2개
        • 호스트를 찾을 수 없거나, 서버의 포트가 열려있지 않는 경우 (UnknownHostException 예외) 발생
        • 네트워크 실패, 방화벽 때문에 서버 접근 할 수 없을 때 (IOException 예외) 발생
생성자 설명
Socket(Inet(Address address, int port) InetAdderss 객체와 port 이용하여 socket 객체를 생성한다
Socket(String host, int port)  host, port를 이용하여 socket객체를 생성한다.
  • Socket 클래스의 주요 메서드 
반환형 메서드 설명
void close() 소켓 객체를 닫는다
InetAddress getInetAddress() 소켓 객체를 InetAddress 객체로 반환한다
InputStream getInputStream() 소켓 객체로부터 입력할 수 있는 InputStream 객체를 반환한다
InetAddress getLocalAddress() 소켓 객체의 로컬 주소를 반환한다.
int getPort() 소켓 객체의 포트를 반환한다
boolean isClosed() 소켓 닫혀있으면 true, 아니면 false 반환
isConnected() 소켓 객체가 연결되어 있으면 true, 연결되어 있지 않으면 false를 반환
void setSoTimeout(int timeout) 소켓 객체의 시간을 밀리 세컨드로 설정
  • 소켓 이용한 입출력 스트림 생성
    • 두 개의 네트워크 사이에서 바이트 스트림 통신 제공
    • 바이트를 읽기 위한 메서드와 쓰기 위한 메서드 제공
    • 두 가지 메서드를 이용하여 클라이언트와 서버간에 통신할 수 있다.
java.io.InputStream getInputStream() throws IOException; 
java.io.OutputStream getOutputStream() throws IOException;

Socket socket = new Socket(“211.238.132.50”,4000); 
InputStream in = socket.getIputStream(); 
OutputStream os = socket.getOutputStream();
  • 소켓 정보 : 로컬 ip주소와 포트를 알 수 있는 메서드와 socket 으로 연결된 호스트의 ip 주소와 포트를 알 수 있는 메서드 제공
  • TCP Server Socket
    • 클라이언트의 TCP 연결을 받기 위해서 java.net.ServerSocket 클래스의 객체를 생성
    • ServerSocket 클래슨느 네트워크 통신을 수행하기 위해 자신을 바로 사용 X 
      -> 클라이언트의 TCP 요청에 대한 Socket 객체를 생성하는것 
    • accept() 메서드 : 클라이언트의 TCP 요청 있을 때 까지 블로킹되는 메서드
    • 클라이언트 TCP 요청 -> ACCEPT 메서드-> TCP 소켓 반환
    • 일반적으로 accept() 메서드는 무한루프 처리하게 됨
    • ServerSocket 클래스의 생성자
      • 기존의 tcp 포트 번호가 사용중이라면 IOException 발생
생성자  설명
ServerSocket(int port) port 이용하여 ServerSocket 객체 생성
  • ServerSocket 클래스 주요 메서드 
    • accept() 가 제일 중요
반환형 메서드 설명
Socket accept() 클라이언트의 소켓 객체가 생성되면 서버가 클라이언트와 통신할 수 있는 소켓 객체를 반환
void close() 서버소켓 객체 닫음
int getLocalPort() 서버소켓 객체가 청취하고 있는 포트번호 반환
getSoTimeout() 서버소켓 클래스의 accept() 메서드가 유효할 수 있는 밀리 세컨드로 반환
boolean isClosed() 서버 소켓 객체의 닫힌 상태를 반환
void setSoTimeout(int timeout) 서버 소켓 클래스의 accept() 메서드가 유효할 수 있는 시간을 밀리 세컨드로 설정
package Lecture.Week2;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
//서버

/*대기 하는 쪽 : 서버
* 찾아 가는 쪽 : 클라이언트
* 먼저 서버가 구동한다. => 포트번호로 묶고 구동해야한다.(1123)
* accept : 대기하다가 클라이언트가 찾아오면 소켓을 생성해서 리턴
* 클라이언트가 찾아가기 위해 ?ip, port번호
* 잘 찾아가면 소켓 생성
* 속 성공 시 두 소켓은 전혀 다른 것이지만 서로 통신할 수 있게 된다. */
public class Test06S {
    public  static void main(String[] args) throws Exception{
        ServerSocket svr = new ServerSocket(1123);
        System.out.println("before accept");

        Socket skt = svr.accept();
        System.out.println("after accept");

        InputStream in = new FileInputStream("a.txt");
        OutputStream out = skt.getOutputStream();

        int r = 0;
        while(( r = in.read()) != -1 ) {
            out.write(r);
            out.flush();//소켓으로 넘어가야함
        }

        out.close();
        in.close();


        System.out.println(r);
        out = new FileOutputStream("copy.txt");
        in = skt.getInputStream();
        r = 0;
        while((r = in.read())!= -1){
            out.write(r);
        }
        skt.close();

        svr.close();
    }
}

서버 & 서버 소켓 이용한 간단한 에코 프로그램

4. 예외 처리 (try - catch) : 사용자의 잘못된 조작, 개발자의 잘못된 코딩으로 인해 발생하는 프로그램 오류

 예외 구문

이유 

ArithmeticException

정수를 0으로 나눌경우 발생 

ArrayIndexOutOfBoundsExcetion

배열의 범위를 벗어난 index를 접근할 시 발생

ClassCastExcetion

변환할 수 없는 타입으로 객체를 반환 시 발생 

NullPointException 

 존재하지 않는 레퍼런스를 참조할때 발생 

IllegalArgumentException

잘못된 인자를 전달 할 때 발생 

IOException

입출력 동작 실패 또는 인터럽트 시 발생 

OutOfMemoryException 

메모리가 부족한 경우 발생  

NumberFormatException 

문자열이 나타내는 숫자와 일치하지 않는 타입의 숫자로 변환시 발생 

  • 예외 처리 코드 
try{
    //에러가 발생할 수 있는 코드
    throw new Exception(); //강제 에러 출력 
}catch (Exception e){
    //에러시 수행
     e.printStackTrace(); //오류 출력(방법은 여러가지)
     throw e; //최상위 클래스가 아니라면 무조건 던져주자
}finally{
    //무조건 수행
} 

문제

1. 점수 관리 프로그램

package HW7_프로그램만들기;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Scanner;
class Score {
    int Student_num;
    int score;
    Score(int Student_num, int score) {
        this.Student_num = Student_num;
        this.score = score;
    }
}
public class Test087 {
    static LinkedList<Score> l2 = null;
    static int Student_num = 0;
    static int score = 0;
    static Scanner scan;
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        scan = new Scanner(System.in);
        String l = null;
        while (true) {
            System.out.println("[ M E N U ]");
            System.out.println("1. 새 자료");
            System.out.println("2. 자료 입력");
            System.out.println("3. 파일로 저장");
            System.out.println("4. 파일에서 불러오기");
            System.out.print("> ");
            l = br.readLine();
            if (l.equals("1")) {
                l2 = new LinkedList<Score>();
                System.out.println("# 새롭게 리스트를 만들거나 초기화하였습니다.");
            } else if (l.equals("2")) {
                if (l2 == null) {
                    System.out.println("# 리스트 인스턴스가 없습니다. 1번을 선택하여 생성해주세요.");
                } else {
                    System.out.print("학번 : ");
                    Student_num = scan.nextInt();
                    System.out.print("점수 : ");
                    score = scan.nextInt();
                    l2.add(new Score(Student_num, score));
                    System.out.println("# 리스트에 학번이 " + Student_num + "인 학생의 점수를 추가했습니다.");
                }
            } else if (l.equals("3")) {
                BufferedWriter bw = new BufferedWriter(new FileWriter("scores.txt"));
                for (int i = 0; i < l2.size(); i++) {
                    bw.write((i + 1) + "번 째 학생 정보");
                    bw.newLine();
                    bw.write("Student_num: " + l2.get(i).Student_num);
                    bw.newLine();
                    bw.write("score: " + l2.get(i).score);
                    bw.newLine();
                    System.out.println("# 성적리스트를 파일로 저장하였습니다.");
                }
                bw.close();
            } else if (l.equals("4")) {
                l2 = new LinkedList<Score>();
                BufferedReader br2 = new BufferedReader(new FileReader("scores.txt"));
                String str = null;
                int r = 0;
                boolean flag = false;
                String[] s = null;
                int s_num = 0;
                int sc = 0;
                while ((str = br2.readLine()) != null) {
                    if (r % 3 == 1) {
                        s = str.split(": ");
                        s_num = Integer.parseInt(s[1]);
                        flag = true;
                        r++;
                        continue;
                    }
                    if (flag) {
                        flag = false;
                        s = str.split(": ");
                        sc = Integer.parseInt(s[1]);
                        l2.add(new Score(s_num, sc));
                    }
                    r++;
                }
                System.out.println("# 저장파일을 불러왔습니다.");
            } else if (l.equals("quit")) {
                System.out.println("# 프로그램을 종료합니다.");
                break;
            }
            if (l.equals("quit"))
                break;
        }
        br.close();
    }
}

2. mp3파일 소켓 저장

<Client>

package Task.Week2;

import java.io.*;
import java.net.Socket;
/*1. 서버에 접속할 소켓생성 CCC
2. 서버의 InputStream을 받아오기
- 서버의 data를 1 byte씩 받아 온다. (InputStream)
3. 저장할 파일에 연결
4. InputStream을 통해 받아온 data를 1 byte씩파일에 작성
- Data가 글자가 아닌 byte이므로 1 byte씩 저장 (FileOutputStream)
5. 연결 해제
*/

public class Client {
    public static void main(String[] args) {
        try(
                Socket skt = new Socket("127.0.0.1", 1123);
                ObjectOutputStream oos = new ObjectOutputStream(skt.getOutputStream());
                InputStream is = skt.getInputStream();
                ObjectInputStream ois = new ObjectInputStream(is);

        ){
            oos.writeUTF("music.mp3");
            oos.flush();
            int status = ois.readInt();
            System.out.println(status);
            if(status == 200){
                System.out.println("파일 받기");
                OutputStream file = new BufferedOutputStream(new FileOutputStream("music2.mp3"));
                int r = 0;
                while((r = is.read()) != -1){
                    System.out.println("파일 수신 준비");
                    file.write(r);
                }
            }else{

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

<Server>

package Task.Week2;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

/*Server writeread SSSS
objectinput
1. 클라이언트에서의 접속을 받아 소켓을 생성해줄 서버소켓 생성
2. 클라이언트의 요청에 의해 소켓 생성
3. 클라이언트의 OutputStream을 받아오기
4. 음악파일에 연결
5. 음악파일을 1 byte씩 읽어 (readInt )클라이언트에 전송
- 음악파일에서 1 byte씩 가져왔으므로 Client에도 1 byte씩 보내주어야 함 (FileInputStream, OutputStream)
6. 전송이 끝나면 연결 해제
*/
public class Server {
    public static void main(String[] args) {

        System.out.println("Before accept()");
        try(
                ServerSocket svr = new ServerSocket(1123);
                Socket skt = svr.accept();
                ObjectInputStream ois = new ObjectInputStream(skt.getInputStream());
                OutputStream os = skt.getOutputStream();
                ObjectOutputStream oos = new ObjectOutputStream(os);
        ){

            System.out.println("After accept()");
            String title = ois.readUTF();
            File f = new File(title);
            boolean b = f.exists();
            System.out.println(b);
            if(b){
                oos.writeInt(200);
                oos.flush();

                InputStream file = new BufferedInputStream(new FileInputStream(title));
                int r = 0;
                while((r =file.read()) != -1){
                    System.out.println("파일 전송 준비");
                    os.write(r);
                    os.flush();
                }
                file.close();
                //파일이 길이를 리턴한다. (long 형 자료에 주의)
                System.out.println(f.length());
            }else{
                oos.writeInt(404);
                oos.flush();
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

Day 2

1. package Lecture.Week2;

public class Test11 {
public static void main(String[] args){
String l = "HelloWorld";
String t = l.substring(2,5);
String r = "HellWorld";
String t1 = l.substring(2,5);

System.out.println( r== l ); //StringPool형태로 나와서 -> false
/*""로 생성한 String은 POOl을 쓴다. 포인터가 비교 가능 , 그 외의 경우(substring) 은 pool쓴다는 보장이 없다
* 그떄는 equals로 비교한다.*/
System.out.println("llo" == t);//""로 비교하면 틀리게 나올수도 있따 -> false
System.out.println("llo".equals(t)); //true

int r2 = Integer.parseInt("100");
System.out.println( r2 == 100);//true
/*문자열을 숫자로 변환시에 : Double.parseDouble() 있음*/

String tl = "10101,100";
int idx = tl.indexOf(",");
System.out.println(tl.substring(0,idx));
System.out.println(tl.substring(idx + 1)); //아래 것보다 더 메모리 향상에 도움이 됨 . 아래는 몇개의 배열이 될 지 모르니까 / , 하나 정도 있을때 좋음

String[] ls = tl.split(",");//,가 여러 개 있는 경우 이 방법이 편함
System.out.println(ls[0]);
System.out.println(ls[1]);
}
}

/*false
false
true
true
10101
100
10101
100*/

2. 데이터베이스 (Mysql

데이터베이스를 먼저 구축 -> 안에 테이블 생성 

mysql> show databases;
mysql> create database study;
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| study              |
| test               |
+--------------------+
5 rows in set (0.00 sec)
mysql>use study; //사용하는 데이터베이스로 변경
mysql> create table study01t( //study01t 생성
    -> id int not null,              //자료형 ; int(4byte)
    -> score tinyint not null
//자료형 : tinyint(1byte)
    -> );
Query OK, 0 rows affected (0.01 sec)
mysql>drop table study01t; //테이블 지우기
mysql>insert into study01t values (10101, 100);//테이블에 값 입력
mysql>insert into study01t values(10102, 90);
mysql> select * from study01t;
+-------+-------+
| id         | score |
+-------+-------+
| 10101 |   100 |
| 10102 |    90 |
| 10103 |    80 |
+-------+-------+
3 rows in set (0.00 sec)
mysql>insert into study01t (score, id) //입력시 순서 바꾸어서 입력할 수 있다
     -> values(90, 10104);
Query OK, 1 row affected (0.00 sec)
mysql> select * from study01t; 
+-------+-------+ 
| id         | score | 
+-------+-------+ 
| 10101 |   100 | 
| 10102 |    90 | 
| 10103 |    80 | 
| 10104 |    90 | 
+-------+-------+ 
4 rows in set (0.00 sec)

-테이블에 있어야하는 개념 

  •   필드 (Field) - 컬럼
    • 자료형을 지정한다(int, tinyint)
    • 같은 자료형의 같은 의미의 값이 와야한다
  • 레코드(Record) - ROW
    • 입력의 단위 
    • 데이터들이 연관되어진 묶음

=> 이 두가지 개념이 있어야 테이블이라고 할 수 있다.

테이블 구성 요소

mysql> delete from study01t where id = 10101;  //where 조건을 만족하는 레코드를 없앤다.
Query OK, 1 row affected (0.01 sec)
mysql> select * from study01t; 
+-------+-------+ 
| id    | score | 
+-------+-------+ 
| 10102 |    90 | 
| 10103 |    80 | 
| 10104 |    90 | 
+-------+-------+ 
3 rows in set (0.00 sec)
mysql> delete from study01t where id <10104; 
Query OK, 2 rows affected (0.00 sec)
mysql> select * from study01t; 
+-------+-------+ 
| id    | score | 
+-------+-------+ 
| 10104 |    90 | 
+-------+-------+ 
1 row in set (0.00 sec)
mysql> delete from study01t;  //조건을 주지 않으면 다 지운다.
Query OK, 1 row affected (0.01 sec)
mysql> delete from study01t where 0 = 1; //모든 레코드가 만족하지 않아 지워지지 않음
mysql> delete from study01t where 1 = 1; //모든 레코드가 만족하니까 모두 지워짐
mysql> update study01t set score=90 where id = 10101; //조건만족 하는 것만 업데이트 해줌
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0
mysql> update study01t set score = score - 10 where id = 10101; //수식 연산 조건도 가능 , 기존의 값 사용 가능 
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0
mysql> update study01t set score = id - 10000 where id = 10101;  //같은 레코드의 다른 필드의 값을 가져와서도 변경 가능
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from study01t;
+-------+-------+
| id      | score |
+-------+-------+
| 10101 |   101 |
| 10102 |    90 |
| 10103 |    80 |
| 10104 |    90 |
+-------+-------+
4 rows in set (0.00 sec)
mysql> update study01t set score = id - 10000 where id != 10101;  
Query OK, 3 rows affected (0.00 sec)
Rows matched: 3  Changed: 3  Warnings: 0

mysql> select * from study01t;
+-------+-------+
| id    | score |
+-------+-------+
| 10101 |    80 |
| 10102 |   102 |
| 10103 |   103 |
| 10104 |   104 |
+-------+-------+
4 rows in set (0.00 sec)
mysql> update study01t set id = 0, score = 0 where id = 10101; //두 칼럼이 변경 시에는 "," 사용
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from study01t;
+-------+-------+
| id    | score |
+-------+-------+
|     0 |     0 |
| 10102 |   102 |
| 10103 |   103 |
| 10104 |   104 |
+-------+-------+
4 rows in set (0.00 sec)
mysql> select score+5, id from study01t  //select는 데이터를 가공해서 보여줄 수있다.
    -> where id != 0;  
+---------+-------+
| score+5 | id    |
+---------+-------+
|     107 | 10102 |
|     108 | 10103 |
|     109 | 10104 |
+---------+-------+
3 rows in set (0.00 sec)
mysql> select score + 5 as sungjuk, id from study01t where id != 0; //컬럼 이름 바꿔서 출력 하지만 실제로 바뀐 것 아니라 보여지는 거만 바꾸어짐 
+---------+-------+
| sungjuk | id    |
+---------+-------+
|     107 | 10102 |
|     108 | 10103 |
|     109 | 10104 |
+---------+-------+
3 rows in set (0.00 sec)
mysql> select score , score as sungjuk from study01t; //하나의 칼럼을 여러번 출력해도 무방하다.
+-------+---------+
| score | sungjuk |
+-------+---------+
|     0 |       0 |
|   102 |     102 |
|   103 |     103 |
|   104 |     104 |
+-------+---------+
4 rows in set (0.00 sec)

mysql> create table study02t(
    -> id char(5) not null,
    -> name varchar(10) null
    -> );
Query OK, 0 rows affected (0.02 sec)
 insert into study02t values('a0001', 'abcd'); //문자열 : ''로 감싼다. char or varchar 자료형 
//char : 고정길이 문자열 (학번, 주민번호) / 처리속도가 훨씬 빠름
-> 'a01' 넣어도 무조건 5자리 차지 (낭비 각오) 
//varchar : 길이를 최대값까지 설정해주지만 가변적이다 //처리 속도가 조금 느림
-> 'apple'을 넣으면 5자리만 공간 사용 , (낭비 적다)
mysql> select concat(id, '*') from study02t;
//oracle  : 'a01 *'
+-----------------+
| concat(id, '*') |
+-----------------+
| a0001*          |
| a0001*          |
| a0001*          |
+-----------------+
3 rows in set (0.00 sec)
mysql> select * from Studentt where addr = '역삼동'; //역삼동에 사는 모든 학생들 검색
mysql> select * from Studentt where addr LIKE '역%'; //역으로 시작하는 문장 검색
mysql> select * from Studentt where addr LIKE '%삼동'; //삼동으로 끝나는 문장 검색
mysql> select * from studentt
    -> where substr(addr, 1,2) = '역삼';

+-------+-----------+-----------+
| stId  | name      | addr      |
+-------+-----------+-----------+
| 10101 | 홍길동    | 역삼동    |
| 10103 | 이기자    | 역삼동    |
+-------+-----------+-----------+
2 rows in set (0.00 sec)
mysql> select substr(addr, 1,2) from studentt;  //부분 문자열 추출 가능
+-------------------+
| substr(addr, 1,2) |
+-------------------+
| 역삼              |
| 개포              |
| 역삼              |
| 한남              |
| 홍제              |
| 한남              |
+-------------------+
6 rows in set (0.00 sec)
mysql> select length(addr) from studentt;  //글자 길이 .utf-8인 경우 한글은 3바이트 
+--------------+
| length(addr) |
+--------------+
|            9 |
|            9 |
|            9 |
|            9 |
|            9 |
|            9 |
+--------------+
6 rows in set (0.00 sec)

#aggregate functions : 5가지 => 딱 하나의 결과만 나옴

min / max / count / avg /  sum

mysql> select * from scoret where subid = 'KOR1';
+-------+-------+-------+
| stId  | subId | score |
+-------+-------+-------+
| 10101 | KOR1  |    60 |
| 10102 | KOR1  |    90 |
| 10103 | KOR1  |    70 |
| 10104 | KOR1  |    80 |
| 10105 | KOR1  |    50 |
| 10106 | KOR1  |    60 |
+-------+-------+-------+
6 rows in set (0.00 sec)

mysql> select min(score) from scoret where subid = 'KOR1'; //국어점수 최소값 1개
+------------+
| min(score) |
+------------+
|         50 |
+------------+
1 row in set (0.00 sec)

## studentt , subjectt , scoret 는 얽혀있다 -> 여러개의 테이블이 연관 관계를 가지고 데이터베이스를 구성한다

 

mysql> select * from scoret where subid ='KOR1'
    ->  and stid IN( select stid from studentt where addr LIKE '역삼%');
//여러개 나오는 결과를 이용할 떄 IN , NOT IN 을 사용한다
//하나의 쿼리의 결과를 이용해서 다른 쿼리를 돌릴 수 있다 : 서브쿼리: ( ) 로 묶여 있는것
+-------+-------+-------+
| stId  | subId | score |
+-------+-------+-------+
| 10101 | KOR1  |    60 |
| 10103 | KOR1  |    70 |
+-------+-------+-------+
2 rows in set (0.00 sec)
mysql> select * from scoret where subid = 'KOR1' and
    -> score <= (select avg(Score) from scoret where subid =  'KOR1');
//유일한 서브쿼리의 결과와 비교는 비교연산자를 쓴다 
//서브쿼리는 반드시 괄호로 묶어 주어야 한다.
//국어 점수가 평균(68.666)이 안되는 학생 
+-------+-------+-------+
| stId  | subId | score |
+-------+-------+-------+
| 10101 | KOR1  |    60 |
| 10105 | KOR1  |    50 |
| 10106 | KOR1  |    60 |
+-------+-------+-------+
3 rows in set (0.00 sec)
mysql> select avg(score) from scoret where subid =  'MAT1' and stid in (select stid from studentt where name like '김%');  //김씨 성을 가진 학생들의 수학 평균
+------------+
| avg(score) |
+------------+
|    70.0000 |
+------------+
1 row in set (0.00 sec)
mysql> update scoret set score = score - 5 where subid = 'ENG1' and stid in ( select * from (select stid from scoret where subid = 'ENG1' and score <= 70) AS X); // 영어 70점 이하의 점수를 받은 학생들의 성적을 -5하라

"AGGREAGATE FUNCTION 은 GROUP BY , HAVING 과 연동된다"

mysql> select stid, avg(score) from scoret group by stid; //stid에 동일한 값을 가진 레코드를 짜매어 평균낸 결과
+-------+------------+
| stid  | avg(score) |
+-------+------------+
| 10101 |    76.6667 |
| 10102 |    93.3333 |
| 10103 |    76.6667 |
| 10104 |    73.3333 |
| 10105 |    63.3333 |
| 10106 |    66.6667 |
+-------+------------+
6 rows in set (0.00 sec)

 select stid, avg(score) form scoret group by stid where avg(score) <=75; error 

-> 왜 ? where은 통계처리에 우선한다.

   해서 having은 통계처리 이후에 동작한다. 


select stid, avg(score) from scoret group by stid having avg(score) <= 75;
 "" 서브쿼리는 크게 3종류로 나뉜다 . ""
   1. where 절의 서브쿼리
   2. from 절의 서브쿼리 ( inline view )
   3. select 절의 서브쿼리 ( 엄청난 결과 / 엄청난 부담 )
   
from 절의 서브쿼리 : select 결과를 마치 table처럼 보면 된다. 

select stid, avg(score) as xx from scoret group by stid;
+-------+------+
| stid  | xx   |
+-------+------+
| 10101 |   77 |
| 10102 |   93 |
| 10103 |   77 |
| 10104 |   72 |
| 10105 |   62 |
| 10106 |   67 |
+-------+------+ 


select stid, round(avg(score), 2) as xx from scoret group by stid;
+-------+-------+
| stid  | xx    |
+-------+-------+
| 10101 | 76.67 |
| 10102 | 93.33 |
| 10103 | 76.67 |
| 10104 | 71.67 |
| 10105 | 61.67 |
| 10106 | 66.67 |
+-------+-------+
//round(): 반올림 하기

select * from ( select stid, round(avg(score), 2) as xx
from scoret group by stid) where xx <= 75;
mysql> create view score2v as
    -> select stid, round(avg(score), 2) as xx from
    -> scoret group by stid;
Query OK, 0 rows affected (0.01 sec)

mysql> select * from score2v;
+-------+-------+
| stid  | xx    |
+-------+-------+
| 10101 | 76.67 |
| 10102 | 93.33 |
| 10103 | 76.67 |
| 10104 | 73.33 |
| 10105 | 63.33 |
| 10106 | 66.67 |
+-------+-------+
6 rows in set (0.00 sec)

# 뷰는 실제로 데이터가 존재하는 테이블이 아니라 테이블 데이터를 이용해서 만들어진 하나의 결과 화면일 뿐 이다.

# 뷰를 대상으로 수정 삭제는 무의미 하다.

 

mysql> select stid, name, (select avg(score) from scoret) as avg from studentt;
+-------+-----------+---------+
| stid  | name      | avg     |
+-------+-----------+---------+
| 10101 | 홍길동    | 75.0000 |
| 10102 | 고길동    | 75.0000 |
| 10103 | 이기자    | 75.0000 |
| 10104 | 박기자    | 75.0000 |
| 10105 | 김영삼    | 75.0000 |
| 10106 | 김대중    | 75.0000 |
+-------+-----------+---------+
6 rows in set (0.00 sec)

 

mysql> select x.stid, x.name from studentt as x; //studentt 가 너무 기니까 x로 바꾸어 쓴다
mysql> select studentt.stid, studentt.name from studentt;  //테이블명.컬럼명 식 
+-------+-----------+
| stid  | name      |
+-------+-----------+
| 10101 | 홍길동    |
| 10102 | 고길동    |
| 10103 | 이기자    |
| 10104 | 박기자    |
| 10105 | 김영삼    |
| 10106 | 김대중    |
+-------+-----------+
mysql> select x.stid, x.name, (select avg(score) from scoret where stid = x.stid) as avg from studentt as x;
+-------+-----------+---------+
| stid  | name      | avg     |
+-------+-----------+---------+
| 10101 | 홍길동    | 76.6667 |
| 10102 | 고길동    | 93.3333 |
| 10103 | 이기자    | 76.6667 |
| 10104 | 박기자    | 73.3333 |
| 10105 | 김영삼    | 63.3333 |
| 10106 | 김대중    | 66.6667 |
+-------+-----------+---------+
6 rows in set (0.00 sec)
mysql> select x.stid, x.avg from(select stid, avg(score) as avg from scoret group by stid)as x;
+-------+---------+
| stid  | avg     |
+-------+---------+
| 10101 | 76.6667 |
| 10102 | 93.3333 |
| 10103 | 76.6667 |
| 10104 | 73.3333 |
| 10105 | 63.3333 |
| 10106 | 66.6667 |
+-------+---------+

 

create table temp01t as
->select stid, avg(score) as avg from 
->scoret group by stid;
+-------+---------+

| stid  | avg     |
+-------+---------+
| 10101 | 76.6667 |
| 10102 | 93.3333 |
| 10103 | 76.6667 |
| 10104 | 73.3333 |
| 10105 | 63.3333 |
| 10106 | 66.6667 |
+-------+---------+
6 rows in set (0.00 sec)
mysql> select x.stid, x.avg,(select count(*)+1 from temp01t where avg > x.avg) as rank from temp01t as x;  //등수
+-------+----------+------+
| stid  | avg      | rank |
+-------+----------+------+
| 10101 | 100.0000 |    1 |
| 10102 |  93.3333 |    2 |
| 10103 |  76.6667 |    3 |
| 10104 |  73.3333 |    4 |
| 10105 |  63.3333 |    6 |
| 10106 |  66.6667 |    5 |
+-------+----------+------+

서브쿼리가 여섯명의 등수를 구할 떄 쿼리가 6*6으로 36번이나 돌아야한다 . 만약 1000명이라면? 말이안됨

-> 임시 테이블을 만들자

mysql> select * from temp02t order by rank;
+-------+----------+------+
| stid  | avg      | rank |
+-------+----------+------+
| 10101 | 100.0000 |    1 |
| 10102 |  93.3333 |    2 |
| 10103 |  76.6667 |    3 |
| 10104 |  73.3333 |    4 |
| 10106 |  66.6667 |    5 |
| 10105 |  63.3333 |    6 |
+-------+----------+------+
6 rows in set (0.00 sec)

mysql> select * from temp02t order by rank desc;
+-------+----------+------+
| stid  | avg      | rank |
+-------+----------+------+
| 10105 |  63.3333 |    6 |
| 10106 |  66.6667 |    5 |
| 10104 |  73.3333 |    4 |
| 10103 |  76.6667 |    3 |
| 10102 |  93.3333 |    2 |
| 10101 | 100.0000 |    1 |
+-------+----------+------+
6 rows in set (0.00 sec)

-임시테이블과 뷰는 흩어진 데이터에서 자신이 원하는 데이터로 가공할 수 있는 방법 제공(비정형 데이터에서 정형화 된 데이터를 만들어 낸다)

-뷰는 오버헤드가 있지만 데이터 변경을 즉각 반영한다 / 임시테이블은 오버헤드가 적지만, 데이터의 변경을 즉각 반영 못함

-select 서브쿼리는 오버헤드가 크다 (1000명의 등수를 처리하는 결과를 1000명이 동시 열람하면 100만건의 쿼리가 동작하는 셈 -> group by 오버헤드 포함) 

-임시 테이블은 이런 부담을 극적으로 줄여준다

 

mysql> create table study3t(
    -> no int not null auto_increment primary key,
    -> theTime datetime not null
    -> );
mysql> insert into study3t values(default, now());
Query OK, 1 row affected (0.01 sec)

mysql> select * from study3t;
+----+---------------------+
| no | theTime             |
+----+---------------------+
|  1 | 2019-07-23 17:16:05 |
|  2 | 2019-07-23 17:16:16 |
+----+---------------------+
2 rows in set (0.00 sec)

now() : 현재 시간 => 입력 시 datetime 자료형 쓴다.

//datetime 자료형에 들어있는 값은 연산이 가능하다.

 

mysql> select no, date_add(theTime, INTERVAL 1 MONTH) from study3t;
+----+-------------------------------------+
| no | date_add(theTime, INTERVAL 1 MONTH) |
+----+-------------------------------------+
|  1 | 2019-08-23 17:16:05                 |
|  2 | 2019-08-23 17:16:16                 |
+----+-------------------------------------+
2 rows in set (0.00 sec)
mysql> select no, date_add(theTime, INTERVAL 4 DAY) from study3t;
+----+-----------------------------------+
| no | date_add(theTime, INTERVAL 4 DAY) |
+----+-----------------------------------+
|  1 | 2019-07-27 17:16:05               |
|  2 | 2019-07-27 17:16:16               |
+----+-----------------------------------+
2 rows in set (0.00 sec)

mysql> select no, date_add(theTime, INTERVAL 4 HOUR) from study3t;
+----+------------------------------------+
| no | date_add(theTime, INTERVAL 4 HOUR) |
+----+------------------------------------+
|  1 | 2019-07-23 21:16:05                |
|  2 | 2019-07-23 21:16:16                |
+----+------------------------------------+
2 rows in set (0.00 sec)

//날짜 데이터를 다룰 때 연산의 필요성이 없으면 char 쓴다.

mysql> create table study04t(
    -> no int not null auto_increment primary key,
    -> theTime char(19) not null
    -> );
Query OK, 0 rows affected (0.02 sec)

mysql> insert into study04t values (default, now());
Query OK, 1 row affected (0.01 sec)

mysql> select * from study04t;
+----+---------------------+
| no | theTime             |
+----+---------------------+
|  1 | 2019-07-23 17:27:03 |
+----+---------------------+
1 row in set (0.00 sec)
반응형

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

제주에서 자바_Week2_3  (0) 2019.07.25
제주에서 자바_Week2_2  (0) 2019.07.24
제주에서 자바_Week1  (0) 2019.07.20
4. 클래스  (0) 2019.05.29
3. 참조 타입  (0) 2019.05.28
반응형

Day 1

1. 8가지 자료형

Byte Short Int Long Float Double
8bit 16bit 32bit 64bit 32bit 64bit

- byte , short , int, long은 정수의 값을 가져다 저장할 수 있는 자료형

- 작은 타입 => 큰 타입 (자동 변환)

- 큰 타입 => 작은 타입 (강제 변환 -> X : 에러)

- (기본) 같은 타입형 변수만 연산 가능

 

2. 변수 : 값을 저장하는 기억공간

- 자료형 : 변수 선언

- 대입 : 값을 저장

 

문제

1. 연 6.6퍼 이자율에 초기금 100만원을 100년간 묵힐 때

public class Test1{
	pulblic static void main(String[] args){
    	double money = 1000000; //초기금
        double rate = 0.066; //이자율
        for( int i = 0; i < 100; i++){
        	money += money *  rate;
        }
        
        System.out.println((int)money);
    }
}

2. 연 6.6% 이자율의 복리 (매 100만원 적금)

public class Test2{
	public static void main(String[] args){
    	int addMoney = 1000000; //매 적금
        double money = 0; // 초기금
        double rate = 0.066;
        for(int i = 0; i < 100; i++){
        	money += addMoney;
            money += money * rate;
        }
        System.out.println(money);
        long endTime = System.currentTimeMiilis();
    }
}

Day 2

※코드 잘 짜는 법 

- 잘 쪼갠다 

- 자신의 보폭을 잘 파악한다

- 반복문 정리 => 일단 늘어놓고 정리 

 

1. Java

-선언 , 대입, 연산

  • 클래스에서 변수, 함수 선언 가능
  • 클래스에서 변수, 함수 호출 연산, 초기화 등등 불가능
class Apple{
	int i ;
    i = 100; //error
    int add(int i, int j){
    	return 100;
    }
    add(); //error
}

- 참조형 변수

  • Apple t = new Apple(); => 클래스를 선언하고 new를 이용하여 instance를 가리킴
class Apple{
    int i;
    int add(int i, int j){ return 100;};
}
public class Test023 {
    public static void main(String[] args) {
        Apple t = new Apple(); //에러 x -> 참조형 변수(포인터)
        t.i = 100; // t가 가리키는 인스턴스가 가지고 있는 변수 i
        System.out.println(t.add(100,20)); //t가 가리키는 인스턴스가 가지고 있는 함수
    }
}

2. 요약

  • 클래스를 선언하여 인스턴스를 만듬 => 이 떄, new 사용
  • 클래스 내부 (멤버 함수(멤버 변수)) 
  • 클래스 - 인스턴스 - new  : 멤버 변수,  멤버 함수존재 
  • 인스턴스가 만들어지는 시점멤버변수 메모리 할당
  • 함수 호출 시점에 로컬변수가 메모리 할당
  • 참조형 변수 는 인스턴스를 가리키는 용도 / 클래스 이름으로 선언
  • 자료형 변수 는 자바의 기본 8개 자료형
  • 자료형 변수에서 대입 ( i = t ) -> t의 값을 복사해서 i에 대입
  • 참조형 변수에서 대입 ( i = t ) -> t가 가리키는 대상을 i가 가리킴
  • 생성자 함수 는 클래스의 멤버 함수  => 주로 멤버변수를 초기화 하는데 사용 (constructor)
  • 인스턴스가 생성될 때 생성자 함수가 생성됨

전반적인 설명

 

 

문제

1. 단리, 복리 가능한 C프로그래밍 (매 100만원 적금)

#include <stdio.h>
float danri(float money, int year, float rate){
    int i;
    float totalMoney, mainMoney;
    totalMoney = 0;
    mainMoney = 0;
    for (i=0; i<year; i++){
        mainMoney += money;
        totalMoney += mainMoney * rate + money;
    }
    return totalMoney;
}

float bokri(float money, int year, float rate){
    float moneyStart;
    int i;
    moneyStart = 0;
    for (i=0; i<year; i++){
        moneyStart += money;
        moneyStart += moneyStart * rate;
    }
    return moneyStart;
}

int main(){
    float (*fp)( float, int, float);
    float r;
    fp = danri;
    r = fp( 100.0, 100, 0.066);
    printf("%f\n", r);
    fp = bokri;
    r = fp( 100.0, 100, 0.066);
    printf("%f\n", r);
    return 0;
}

Day 3

1. 객체지향 3대 속성

- 상속성 : 클래스를 상속해서 클래스를 만든다

- 은닉성 : 감추고 싶은 건 감출 수 있다

- 다형성 : 하나의 심볼(이름)이 여러 실체에 매핑될 수 있다.

class A {
    int apple = 10;
}
//클래스 B는 클래스 A를 상속하여 만들었음을 명시.
// A에서 선언한 멤버변수는 멤버함수를 내려받겠다.
class B extends A{
    int add(int i, int j){return  100;}
}
public class Test27 {
    public static void main(String[] args) {
		B t = new B();
        System.out.println(t.apple);
    }
}

 

2. 클래스 : 설계도 정의해 놓은 것 

- 할 수 있는 것 : 참조형 변수 선언 / 인스턴스 생성 / 상속받아 클래스 선언

 

3. 생성자

<특징>

- return 타입 X 

- 클래스명 (매개 변수) {.....} 로 동작

- 인스턴스  생성시점 호출

- 함수 아님 .. 인스턴스 멤버 변수를 초기화 시킬 때 주로 사용

class Apple4{
    int data = 0;
    // return이 존재하지 않는 함수를 서브루틴이라 한다.
    //리턴타입을 void로 한다.
    void print(){
        System.out.println(this.data);
    }
}
public class Test28 {
    public static void main(String[] args) {
	    Apple t = new Apple();
        t.data = 10;
        t.print();
        Apple l = new Apple();
        l.data = 20;
        l.print();
    }
}

//출력 : 10 20 

this : 멤버 함수 안에서 자신이 소속된 인스턴스에 대한 포인터 

 

4.Java로 리스트 만들기

연결리스트

 

class Node{ //외워라!
    int data = 0; //  대입은 원래 불가능하나 선언과 동시에 대입은 가능함
    Node next = null; //가리키고 싶지않다.

    Node( int i , Node n){ //생성자 일반적 예시
        this.data = i;
        this.next = n;
    }
}
public class Test5 {
    public static void main(String[] args) {
        Node head = new Node(0,null);		//Step 1
        Node tail = head;

        tail.next = new Node(10, null);			//Step 2
        tail = tail.next;

        tail.next = new Node(20, null);			//Step 3
        tail = tail.next;

        for( Node t =head.next ; t !=null ; t=t.next){		//Step 4
            System.out.println(t.data);
        }
    }
}
/*
    모든 참조형 변수에는 null 이라는 값이 대입 가능 : 가리키는 인스턴스 없다.
    -어떻게 돌아가는지 상황파악을 그림으로 설명 가능할 것.
    >> 출력 : 10 20
 */

- 객체 상태 변화

Node flow

연결리스트 클래스화

class Node{
    int data = 0;
    Node next = null;
    Node( int i , Node n){
        this.data = i;
        this.next = n;
    }
}
class LinkedList {
    Node head = null;
    Node tail = null;
    public LinkedList() {
        this.head = new Node(0, null);
        this.tail = this.head;
    }
    void add(int i){
        tail.next = new Node(i, null);
        tail = tail.next;
    }
    public void print() {
        for (Node t = head.next; t !=null; t=t.next) {
            System.out.println(t.data);
        }
    }
}
public class Test29 {
    public static void main(String[] args) {
       LinkedList l = new LinkedList();  //Step 1
       l.add(10);  //Step 2
       l.add(20);  //Step 3
       l.print();

    }
}//>> 출력 : 10 20 

- 객체 상태 변화

LinkedList Flow

5. Java 상속

class A{
    A(){
        System.out.println("A constructor");
    }
}
class BB extends A{
    B() {
        System.out.println("B constructor");
    }
}
public class Test31 {
    public static void main(String[] args) {
        new B();
    }
}//>> A constructor B constructor

=> 왜? A constructor B constructor 이렇게 출력이 될까?

     >> 생성자는 상속이 되지 않고 호출 되는 것이기 때문(멤버 함수가 아니라서)

-상속관계가 존재 시 조상 클래스 , 자손 클래스 자손의 인스턴스를 생성하면 조상의 생서자가 먼저 호출, 자손의 생성자가 호출된다

>>> 이 때 인스턴스는 2번 생성되는 것 처럼 보이지만 하나가 생성되고 조상과 자손을 호출한다.

class A{
    void print(){
        System.out.println("A print");
    }
}
class B extends A{
    void print(){
        System.out.println("B print"); // method overriding
        super.print();// 부모의 함수를 호출하고 싶을때
    void print2(){
        System.out.println("B print2");
    }
}
public class Test32 {
    public static void main(String[] args) {
        B t = new B();      //자손 B호출
        t.print();
        A t2 = new A();         //조상 A 호출
        t2.print();
        A t3 = new B();        //자손 B 호출
        t3.print();
        //조상에서 선언된 멤버함수, 멤버변수만 호출 가능
        //t3.print()2;     -------> 에러남
        //B t4 = (B) new A();//에러남 캐스팅되지않음
		//t4.print();   //다운캐스팅은 일반적으로 불가
        B t4 = (B) t3;   //이 경우 다운캐스팅이됨
        t4.print();         //JVM이 무슨형인지 추리할수 있기때문
    }
}//결과값 : B print A print A print B print A print

6. Method overriding : 조상클래스에서 선언한 멤버 함수 재정의

- 각 인스턴스에서 정의된 method로 사용(변수는 오버라이딩 X) 

- Super 을 이용하여 자손 클래스에서 조상 method 이용가능

오버라이드 개념

 7. 접근 제어자 

  상속 외부 호출 내가 쓰기
Private X X O
protected O X O
public O O O

- 클래스 안의 멤버함수와 멤버 변수 앞에 붙임

- java 의 protected => 같은 패키지 내에선 접근 가능 / 다른 패키지 내에선 접근 불가

- 접근자 안적어? => friendly로 (같은 패키지로는 public / 다른 패키지는 private)

 

=> 때문에 Getter을 이용하여 자신의 값을 호출하게 만듬

class A{
    private int data =100;
	public int getData(){ return data;}
}
class B extends A{
    private int data =200;
    public int getData(){return data;}
}
public class Test{
    public void static main(String[] args){
        A t = new B();
        System.out.println(t.getData());
    }
}//결과값 : 200

-B 클래스의 getData가 호출이되서 혼란이 방지됨

-조상에서 getXXX 함수가 보이면 그런 변수가 있는줄 알고 xXX 변수는 피해간다

-이 경우 getData()로 부모클래스의 data를 부르려고 하면 getData()가 오버라이딩 되어있기 때문에 접근이 힘들어진다.

 

8. 추상클래스 : 선언되었지만 구현되어 있지 않은 메소드

abstract class A{
    public abstract void print();
}
abstract class B{}
class C extends B{}
abstract class D extends C{}
public class Test1 {
    public static void main(String[] args) {
//      A t = new A();
        A t = null;
    }
}

-abstract 메소드가 하나라도 선언되어 있으면 그 메소드 가진 클래스는 반드시 abstract 클래스로 정의

-abstract 클래스는 인스턴스를 만들 수 없다

-참조형 변수 선언이 가능하다

-상속 또한 가능하다

abstract class A{
    public abstract void print();
}
abstract class B extends A{}  //  <------- abstract class - abstract class
class C extends A{			// <------abstract 클래스가 아닌 클래스가 상속받으려면 구현해줘야 함
    @Override
    public void print() {
         System.out.println("hi");
    }
}
public class Test1 {
    public static void main(String[] args) {
        A t = new C();   // <------ 조상의 함수를 호출한 경우 , 자손의 함수가 호출, 오버라이딩 된 구현부가 호출
        t.print();
    }
}

<단리, 복리 추상 클래스로 구현>

abstract class Bank{
    public abstract double calc(double money, int years, double rate);
    public void print(){
        double r = calc(100, 100, 0.066);
        System.out.println(r);
    }
}
class BokriBank extends Bank{
    @Override
    public double calc(double money, int years, double rate) {
        return 59665.1234 * subCalc();
    }
    private int subCalc(){return 3;}
}
class DanriBank extends Bank{
    @Override
    public double calc(double money, int years, double rate) {
        return 760.0 + money();
    }
    private int money(){return 100;}
}
public class Test2 {
    public static void main(String[] args) {
        Bank bk = new BokriBank();
        bk.print();
        Bank bk2 = new DanriBank();
        bk2.print();
    }
}

9. 인터페이스 

interface ICalc{
    public void print(); //인터페이스 안에는 모두 추상자료형이여야함
}
interface IUnknown{}
class Apple{}
class Calc extends Apple implements ICalc, IUnknown{
    @Override
    public void print() {
        System.out.println("A");
    }
}

public class Test3 {
    public static void main(String[] args) {
        ICalc ic = new Calc();
        ic.print();
    }
}

-일종의 추상 클래스 => 변수 선언, 상속 당할 수 있음 => 다만, 인스턴스 생성 불가

-인터페이스 상속해서 클래스를 선언될 때는 implements 이용

-다중 상속 가능, 클래스 상속과 인터페이스 동시 상속 가능

 

문제

<인터페이스 사용한 Decorator pattern>

interface IGreet {
    public String greet();
}
class MerciGreet implements IGreet{
    @Override
    public String greet() {
        return "Merci";
    }
}
class HelloGreet implements IGreet{
    @Override
    public String greet() {
        return "hello";
    }
}
abstract class GreetDeco implements IGreet{
    protected IGreet ig = null;

    public GreetDeoo(IGreet ig) {
        this.ig = ig;
    }
}
// 자손의 생성자에서 조상의 생성자 중 매개변수 있는 생성자를 호출 원하면 supoer로 지정.
class StarDeco extends GreetDeoo{
    public StarDeco(IGreet ig) {
        super(ig);
    }
    @Override
    public String greet() {
        return "" + ig.greet() + "*";
    }
}
class SharpDeco extends GreetDeoo{
    public SharpDeco(IGreet ig) {
        super(ig);
    }
    @Override
    public String greet() {
        return "" + ig.greet() + "#";
    }
}
public class Test4 {
    public static void main(String[] args) {
        IGreet ig= new SharpDeco(new StarDeco(new HelloGreet()));
        System.out.println(ig.greet());
    }
}//hello*#

=> 추가 상식 : interface는 public 명시 안해도 컴파일시 자동으로 추가해줌


Day 4

1. 메소드 오버로딩 : 하나의 클래스 안에 이름은 같은데 매개변수 형태가 다른 함수 여러 개 공존 가능

class Temp{//하나의 클래스 안에 이름은 같은데 매개변수 형태가 다른 함수 여러 개 공존가능
	public void print(){};
    public void print(int i){
    	System.out.println(1);
    };
    
    public void print(double i){
    	System.out.println(2);
    };
	public void print(int i, int j){
        System.out.println(3);
    };
}
public class Test40 {
    public static void main(String[] args) {
        Temp t= new Temp();
        t.print();
//        float j = 3.14;     큰타입 Double(3.14) -> 작은타입 float(j)로 바로 변환 x
        float i = (float) 3.14; //방법 1  강제형변환
        float j = 3.14f; //방법2  float = float
        t.print(j);// 매개변수가 딱 맞지 않으면 가장 가깝게 자동형변환 되는것을 찾아서 호출
    }//>>결과 : 2
}

 

- 멤버 함수에는 오버라이딩 이라는 개념이 있지만, 멤버 변수에는 오버라이딩 개념이 없음

class A{
    int i = 100;
}
class B extends A{
    int i = 200;
    void print(){};
}
public class Test40 {
    public static void main(String[] args) {
        A t1 = new B();
        System.out.println(t.i);
        //t 포인터가 가리키는 인스턴스를 감싸는 B클래스 인스턴스를 t2가 가리킨다.
        B t2 = (B)t;
        t2.print();
        System.out.println(t2.i); //갑자기 i값이 변하므로 private해주는게 좋음
    }
}

##요약

  • 형변환 시 예기치 못한 변수의 변화가 생길 수 있으므로 같은 이름으로 하는 것은 금지
  • 클래스 안에 올 수 있는 것
    -변수 선언(멤버 변수) , 함수 선언(멤버 함수)
    • 실행 하면  main이 먼저 올라오고
    • static으로 선언되면 클래스가 메모리에 올라올 때 인스턴스가 생성되기 전에 메모리 할당
  • 자바 실행 환경은 클래스가 필요해지면 클래스 파일을 메모리에 올린다 -> 후에 인스턴스 생성 가능
    • static 멤버는 클래스 로딩 시에 메모리를 할당, 무조건 유일하다
    • non-static 멤버는 인스턴스가 생성 될 때 메모리를 할당받음 , 인스턴스마다 따로따로 존재
  • 인스턴스가 100번 생성되도 클래스는 설계도이니 최초에 한번만 올라옴 / 이 때 스태틱은 전역변수처럼 1개만 올라옴
class Temp{
  static int i = 100;
  static void print(){
      System.out.println(i);
  }
  void func(){
      System.out.println("hi");
  }
  static class Temp2{
      private int i = 3;
      public void getI(){
      }
      static void print(){
          System.out.println("hi");
      };
  }
}
public class Test40 {
    public static void main(String[] args) {
        int j = Temp.i;
        Temp t = new Temp();
        t.func();
        Temp.print();
        Temp.Temp2.print();
    }
}// static 멤버는 클래스명. 심볼 형태로 접근 >> 결과 : hi 100 hi

-static 멤버 함수 안에서는 non-static한 멤버 함수, 멤버 변수에 접근 할 수 없다 (메모리에 아직 안올라와 있기 때문에)

-abstract 클래스는 인스턴스를 생성할 수 없다.

 

복습

  • class
  • instance
  • 로컬변수 함수가 호출될 때 메모리할당
  • 멤버변수 클래스내에 선언된 변수 인스턴스가 생성될떄 메모리 할당(static이 아닌경우)
  • 매개변수 일종의 로컬변수로 함수호출시 생성
  • 참조형변수 인스턴스를 가리키기위한 용도 : class 이름으로 선언
  • 자료형변수 byte short int long float double boolean char
  • 생성자함수 인스턴스가 생성될떄 호출 되는 함수, 주로 멤버변수를 초기화하는데 사용
  • extends 인터페이스 외 클래스 상속 1개만가능
  • implements 인터페이스 상속
  • interface(abstract만 가지고 있는 클래스)
  • abstract class(하나의 abstract method가 있는경우 무조건)
  • abstract method(선언은 되었지만 구현은 없는경우)
  • overriding( 부모로부터 상속)
  • overloading( 같은 이름의 메소드 다른 매개변수)
  • 자료형변수_캐스팅 : 큰 형태에서 작은형태 x 작은 형태에서 큰형태 o
  • 참조형 변수_캐스팅 (큰박스가 작은박스를 감싸는 모양)
  • 자료형 변수의 대입 : 오른쪽의 값을 복사해서 왼쪽에 대입
  • 참조형 변수의 대입 : 오른쪽이 가리키는 대상이왼쪽을 가리킴
  • private : 나만쓸수있음
  • public : 나쓸수있고 참조형변수도되고 자손도가능
  • protected : 나쓸수있고 자손도가능
  • friendly(default) : 같은패키지에서는 public 다른패키지에서는 private
  • A t = new B() 조상의 참조형 변수로 자손을 만드는것은 가능하고, 조상의 함수를 호출한 경우 자손의 함수가 호출되므로 오버라이딩 된 구현부가 호출이됨

2. 자바 배열

public class Test5{
	public static void main(String[] args){
    	int[] i = new int[]{1,2,3,4}; //new 사용했으므로 자바의 배열은 인스턴스
        //int[] i = {1,2,3,4}로 축약해서 사용할 수 있다.
        for(int j : i){ //i = 참조형 변수
        	System.out.println(j);
        }
        System.out.println(i.length); //그래서 멤버 변수를 가지고 있음
    }
}//배열 : 동일한 형태의 기억장소가 연속으로 할당된 기억공간 >>>결과 : 1 2 3 4 4

for문 구현할 시에는 

for(int j = 0; j < i.length; j++){
	if(j == 2){
    	break; //break는 반복문 탈출 , continue는 이하의 코드는 수행을 건너 뛰고 반복을 계속
    }
    System.out.println(i);
}

3. Object class

-자바의 기본적으로 제공되는 클래스

-자바,lang 패키지에 소속된 클래스는 import 없이 사용 가능

public class Test048 {
    public static void main(String[] args) {
        Object t = new Temp();
        System.out.println(t.toString());// toString()은 Object에 선언되었고, 상속되었다.
        Object t2 = new Temp();
        System.out.println(t2.toString());
    }
}>>결과값 : Temp@460141958  Temp@1163157884

-조상 클래스를 지정하지 않으면 object로부터 상속받는다

-object는 모든 클래스의 조상

-object는 어떤 타입의 인스턴스도 가르킬 수 있다.

-toString()은 오브젝트.클래스에 선언되어 있다.

 

4. Getter Setter

-멤버 함수는 private 권장 / 값을 읽을 때는 getter함수 제작

-인스턴스 내 변수값 일기 전용 -> getter만 만듬

-인스턴스 내 변수값 바꾸고 싶을 때는 -> setter를 쓰는 것 

class Temp{
    private Object data = null;
    public Object getData(){
        return data;
    }
    public void setData(Object obj){
        this.data = obj;
    }
}//오브젝트 클래스 getter / setter

주의점

class Temp{
    private int data = 100;
    public int getData(){
        return data;
    }
}
class Temp2 extends Temp{
    private int data = 200;
    public int getData(){
        return data;
    }
}
public class Test048 {
    public static void main(String[] args) {
        Temp t = new Temp();
        System.out.println(t.getData());
        Temp t2 = new Temp2();
        System.out.println(t2.getData());
        Temp2 t3 = new Temp2();
        System.out.println(t3.getData());
    }
}//결과값 : 100 200 200

5. String 클래스

-StringPool : 자바에서 String클래스를 유일하게 new 없이 ""로 인스턴스 가능

public class Test048 {
    public static void main(String[] args) {
        String t = "HelloWorld";
        String t2 = "HelloWorld";
        System.out.println(t == t2);
        System.out.println(t.equals(t2));
        System.out.println(t.hashCode());
        System.out.println(t2.hashCode());
    }//>>결과값 : true true 439329280 439329280

-""를 만나면 VM은 StringPool을 뒤져서 없으면 만들고, 있으면 재활용

-HTML 내용을 String으로 만들고 재활용 하는 쪽이 메모리 관리에 유용하다

 

-String으로 캐스팅

class Temp{
    private Object data = null;
    public Object getData(){
        return data;
    }
    public void setData(Object obj){
        this.data = obj;
    }
}
class Temp2{
    private String data = null;
    public String getData(){
        return data;
    }
    public void setData(String obj){
        this.data = obj;
    }
}
public class Test048 {
    public static void main(String[] args) {
        Temp2 t2 = new Temp2();
        t2.setData("HelloWorld"); //스트링만 인스턴스로 저장 할 수 있음 (스트링은 상속불가)
        String l2 = t2.getData();  //casting 불필요

        Temp t = new Temp();
        t.setData("HelloWorld"); //모든 인스턴스로 저장할 수 있음
        String l = (String) t.getData();   //캐스팅 필요 
    }
}

6. Generic : 인스턴스 내부의 자료형을 동적으로 지정할 수 있음.

- Object + 구체적 자료형 결합

-<   > 안에 지정 가능한 타입은 참조형 변수 타입이어야 한다.(자료형 안됨)

- System.out.print로 호출하면 자동으로 toString이 호출되도록 약속되어 있다.

class Temp< T extends Object>{
    private T data = null;
    public T getData(){return data;}
    public void setData(T data){this.data = data;}
}
public class Test048 {
    public static void main(String[] args) {
        Temp<String> t = new Temp<String>();//참조형 변수만 가능, String, integer, double
        t.setData("HelloWorld");
        System.out.println(t.getData());

        Temp<Object> t2 = new Temp<Object>();
        t2.setData("HelloWorld");
        String l2 = (String) t2.getData();
        System.out.println(t2.getData());
    }
}//>> 결과값 : HelloWorld HelloWorld

-Integer : int 클래스

-Double : double 클래스 있음

public class Test054 {
    public static void main(String[] args) {
        Object ob = new Integer(100);
        Object ob2 = new Double(3.14);

        int i = ((Integer) ob).intValue();
        //왜 ? 함수 호출을(Integer)ob는 toString으로 String값이 넘어옴
        System.out.println(i);

        double j = ((Double)ob2).doubleValue();
        System.out.println(j);
    }
}

 

7. AutoBoxing 

Integer i = 100;
Object t = 200; //object 변수에서도 autoboxing 동작함 , JDK 1.5에서 추가
System.out.println(i.getClass().getName());
System.out.println(t.getClass().getName());
//결과값 : java.lang.Integer java.lang.Integer

-Integer i = 100; => Integer i = new Integer(100); 로 컴파일러가 자동으로 바꿔줌

-값을 wrapper 클래스에 대입하는 코드는 자동으로 인스턴스 생성하여 값을 감싸줌 : Auto boxing

 

8.AutoUnboxing

Integer i = 100; //Integer i = new Integer(100);로 자동 줄바꿈
int j = i;  //i.intValue();
System.out.println(j);//>> 결과 100

Object t = 200;
int k = t; //error => object타입으로 오토박싱된 인스턴스는 언박싱되지 않는다 
//t.intValue()로 호출할 수 없다 -> JDK 1.5에서 추가됨

 

#근데 공부하다 보니 캐스팅과 박싱의 차이는 뭘까가 궁금해짐

-캐스팅은 단순히 타입 a -> 타입 b 

-박싱은 원시 타입(boolean, char) -> 참조 타입(string, file)

-char 주워담아서 박싱하면 스트링 되고 , 스트링 박스를 언박싱하면 char가 된다

 

9. Command Pattern

interface ICalc{
    public int execute(int i);
}

class AddCalc implements ICalc{
    private int data;
    public AddCalc(int data) {
        this.data = data;
    }

    @Override
    public int execute(int i) {
        return i+data;
    }
}
//쓰임 당하는 입장에서 쓰는 쪽에게 어떤 의견 제시하는 통로 필요 : 어노테이션
// 이것을 체계화 한 것이 1,5 이후에 도입된 Annotation 개념이 된다.
interface PrintStarts{} //어노테이션 인터페이스의 조상뻘 개념

class MinusCalc implements ICalc, PrintStarts{
    private int data;
    public MinusCalc(int data) {
        this.data = data;
    }
    @Override
    public int execute(int i) {
        return i-data;
    }
}
public class Test054 {
    public static void main(String[] args) {
        ICalc i = new AddCalc(3);
        int r = 5;
        r = i.execute(r);
        System.out.println(r);

        ICalc[] ls = new ICalc[5];
        ls[0] = new AddCalc(2);
        ls[1] = new MinusCalc(3);
        ls[2] = new AddCalc(6);
        ls[3] = new MinusCalc(1);
        ls[4] = new AddCalc(7);

        int y = 10;
        for (int j = 0; j < ls.length; j++) {
            y = ls[j].execute(y);
            if(ls[j]instanceof PrintStarts){
                System.out.print("**");
            }
            System.out.println(y);
        }
    }
}
/*
일반적으로 자료값은 변수로, 동작은 함수로 만든다.
동작을 하나의 인스턴스로  수행하게 하는 경우가 있다.
- 이런 설계기법을 Command Pattern이라고 한다.
리스트같은데 인스턴스들을 저장하여 매크로처럼 사용 할 수 있다.
 */

10. Build

class Temp1{
    int data = 0;
    // 아래 코드의 t와 this가 가리키는 대상은 같다.
    // 따라서 t.add(10)은 10을 더한 후에 t로 바꿔 쓸 수 있다.
    // StringBuffer의 append에서 볼 수 있다.
    Temp1 add (int i){
        data += i;
        return this;
    }
}
public class Test057 {
    public static void main(String[] args) {
        Temp1 t = new Temp1();
        t.add(10).add(10).add(100);
        System.out.println(t.data);
    }
}//결과 : 120

11. String Buffer Class

public class Test057 {                                   
    public static void main(String[] args) {         
        StringBuffer sb = new StringBuffer();             
        sb.append("apple");       
        sb.append("banana");        
        String l = sb.toString();       
        System.out.println(l);                                                                       
        System.out.println("apple" + "banana");
        //코드는 컴파일러가 new StringBuffer().append("apple").append("banana").toString
        //방식으로 한줄마다 new StringBuffer가 동작하지만 위의 코드는 한번만 동작
    }                     
}//applebanana applebanana

12.String vs StringBuffer Test

public class Test057 {
    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < 100000; i++) {
            sb.append("apple");
        }//StringBuffer : 하나의 인스턴스
        long end = System.currentTimeMillis();
        System.out.println(end - start);
        start = System.currentTimeMillis();
        String st = new String("");
        for (int i = 0; i < 100000; i++) {
            st += "apple";
        }//String : 다수의 인스턴스
        end = System.currentTimeMillis();
        System.out.println(end - start);
    }
}//결과값 : 8 11645 //StringBuffer가 훨씬 좋음

-java -verbosegc 클래스 이름 통해 가비지 콜렉터 과정을 볼 수 있음

-메모리가 부족할 때 메모리를 비우고 확보하는 일 모니터링

 

13.String

-SubString();

String l = "HelloWorld";
System.out.println(l.substring(2,5)); //llo

 -indexOf(); : 만약 없는 문자열 찾을 때는 -1 리턴/ 문자열 안의 부분 문자열 위치를 리턴

String l = "HelloWorld";
System.out.println(l.indexOf("or")); //>>6

-starsWidth(); / endsWidth(); 시작이나 끝 문자열이 매개변수값과 같으면 true 아니면 false

String l = "HelloWorld";
System.out.println(l.startsWith("Hell"));
System.out.println(l.endsWith("ld")); //true true

-toCharArray(); : String을 char 배열로

String l = "HelloWorld";
char[] ch = l.toCharArray();
for (int i = 0; i < ch.length; i++) {
	System.out.println(ch[i]);
    }//결과값 : H e l l o W o r l d

문제

배열의 최대값 구하기

public class Test045 {
    public static void main(String[] args) {
        int[] i = new int[]{4,9,6,5};
        int max = i[0];
        for (int j = 1; j < i.length; j++) {
            if(max < i[j]){
                max = i[j];
            }
        }
        System.out.println(max);
    }
}//>>9

제너릭 연결리스트

package node;
class Node<T>{
    T data = null;
    Node<T> next = null;
    Node(T i, Node<T> n){
        data = i;
        next = n;
    }
}
class LinkedList<X>{
    private Node<X> head = null;
    private Node<X> tail = null;
    public LinkedList() {
        this.head = new Node<>(null, null);
        this.tail = head;
    }
    public LinkedList<X> add(X input){
        tail.next = new Node<>(input, null);
        tail = tail.next;
        return this;
    }
    public void print(){
        for(Node<X> n = head.next; n != null; n = n.next){
            System.out.println(n.data);
        }
    }
}
public class MyLinkedList {
    public static void main(String[] args) {
        LinkedList<String> ll= new LinkedList<>();
        ll.add("test").add("this").add("how");
        ll.print();
        LinkedList<Integer> l2 = new LinkedList<>();
        l2.add(3).add(2);
        l2.print();

    }
}

String의 indexOf와 동일한 동작 하게

package index;

class Finder{
    public static int indexOf(char[] operand, char[] operator) {
        int odLenth = operand.length;
        int otLenth = operator.length;
        int idx = -1;
        for (int remainder = odLenth - otLenth;  remainder >= 0; remainder--) {
            if(operand[remainder] == operator[0]){
                for(int i=1; otLenth-1 >= i; i++){
                    if(operand[remainder+i] == operator[i]){
                        if(i == otLenth-1){
                            idx = remainder;
                            break;
                        }
                    }else {
                        break;
                    }
                }
            }
        }
        return idx;
    }
}
public class MyIndexOf {
    public static void main(String[] args) {
        int idx = Finder.indexOf("Hedoerrdwld".toCharArray(), "sdadsadsadorw".toCharArray());
        System.out.println(idx); 
    }
}

Day 5

1. Casting :  instanceOf 키워드를 이용해서 알 수 있다.

-Casting Error : t가 가르키고있는 B라는 인스턴스가 존재해야만 캐스팅이 가능해짐

class A{
}
class B extends A {
    public void print() {
        System.out.println(100);
    }
}
public class Test061 {
    public static void main(String[] args) {
        A t= new A();
        if*
        B t2 = (B) t;
        t2.print();
    }
}
//결과값 : Exception in thread "main" java.lang.ClassCastException: 
javaclass.A cannot be cast to javaclass.B at javaclass.Test061.main(Test061.java:16)

-instanceof : 캐스팅 에러 미리 방지

 A t= new A();
//(B)t 이것이 가능하면 true/ 아니면 false
if (t instanceof B){
	B t2 = (B) t;
    t2.print();    
}

-boolean : 비교연산 값을 리턴 

-거의 모든 연산은 같은 자료형 끼리 가능

-double간의 연산 비교는 정확하지 않는다.

public class Test061 {
    public static void main(String[] args) {
       boolean i = true;
       boolean j = false;
        System.out.println(10 < 5);
        System.out.println(10 / 3); // 나머지를 뺀 몫이 나옴
        System.out.println(10 % 3); //나머지를 구하는 연산자
        System.out.println(10.0 / 3);
        System.out.println(3.33333333 * 3 == 10.0);
        System.out.println(3.3333333333333335 * 3== 10.0); //Double 연산은 값을 보장할 수없다. 오차발생
    }// c는 정수값 0 은 false, 0이아닌 모든 정수는 true
}// if(100)참
//결과값 : false 3 1 3.3333333333333335 false true

2.Package

-클래스의 묶음, 파인 맨 위에 지정

-한 파일안에 선언한 모든 클래스는 지정된 패키지 속함

-패키지를 지정하지 않으면 Unnamed 패키지에 소속, 사용시 제약이 많음

- javac -d . Test061.java

대상폴더아래 패키지이름으로 폴더생기고, 그 아래에 class파일이 들어간다.

package javaclass;

public class Test061 {
 public int print(){
     return 200;
 }   
 public int print2(int i ){
     return 300 * i;
 }
 public static int print3(){
     return 100;
 }// 패키지가 지정된 클래스 컴파일 : javac -d [폴더위치] Test061.java
}

3.import

-다른 패키지 클래스는 반드시 명시

-만일 그래도 못찾으면 class 를 명시해야한다. 

javac -classpath C:\A\ Test061.java

-실행 : java -classpath .;C:\A\ Test061

     -> 현재 폴더 명시해줘야함

-classpath 옵션을 안주면 -classpath . 이 자동으로 붙는다.

-Test 061A의 멤버변수가 접근되는지 살펴본다 : protected, friendly(default) -> 다른패키지에서 접근 x

-Static한건 클래스가 로딩될떄 메모리에 할당 non-Static한건 인스턴스가 생성될떄 메모리에 할당

-클래스로딩은 딱 한번만일어나므로 Static한건 딱 한개만 존재함

-Static Initializer:  클래스가 로딩되는 시점에 실행되고 클래스를 강제로 로딩하려면 Class.forName("클래스명");함수를 이용한다.

package practice;

import javaclass.Test061;

public class Test064 {
    public static void main(String[] args) {
        Test061 t = new Test061();
        t.print();
    }
}
package temp;

public class Test066A{
	//static initializer라 한다. 클래스가 로딩되는 시점에 호출됩니다.
	static{
		System.out.println("Test066A loaded");
	}
	public int print(){return 200;}
	public int print2(int i){return 300*i;}
	public static int print3(){return 100;}
} // C:\a\ 아래에 컴파일하자. javac -d c:\A\ Test066A.java
public class Test066{
	public static void main(String[] args) throws Exception{
		//클래스를 찾아내서 해당 클래스를 강제로 메모리에 로딩시킨다.
		//찾아낸 코드의 static initializer가 동작하게됨
		Class<?> cls = Class.forName("temp.Test066A");
		/* Class : 로딩된 클래스의 관리자 역할을한다.
		   cls.newInstance() : cls가 관리하는 temp.Test066A의 인스턴스를 생성한다.
		   obj.getClass().getName() : obj가 가리키는 인스턴스를 생성시킨 클래스 명 //임포트없이도 다른 패			 키지의 인스턴스를 생성 할 수 있음
		*/
		Object obj = cls.newInstance(); //new를 쓰지않고 인스턴스를 만드는방법

		System.out.println( obj.getClass().getName());
	}
}

 

import java.lang.reflect.Method;

public class Test066_2{
    public static void main(String[] args) throws Exception{
     Class<?> cls = Class.forName("temp.Test066A");
     Object obj = cls.newInstance();

     /* getMethods() : 클래스안에서 선언된 함수에 대한 포인터들을 추출한다.
     
      */
     Method[] mtds = cls.getMethods(); //함수 포인터
        for (int i = 0; i < mtds.length; i++) {
            System.out.println(mtds[i]);
        }
    }
}
/*결과값 : Test066A loaded
public int temp.Test066A.print()
public int temp.Test066A.print2(int)
public static int temp.Test066A.print3()
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public java.lang.String java.lang.Object.toString()
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()*/
package javaclass;

import java.lang.reflect.Method;

public class Test066_3 {
    public static void main(String[] args) throws Exception{
        Class<?> cls = Class.forName("temp.Test066A");
        Object obj = cls.newInstance();
// Method는 C의 함수포인터의 역할을 한다.
//        cls.getMethods()는 모든 멤버함수의 포인터를 넘긴다.
//        cls.getMethod(...) : 단하나의 멤버함수의 포인터를 넘기다.
//        ...에는 함수이름, 매개뱐수의 형태를 명시한다.
//       Method mtd = cls.getMethod("print");
        Method mtd = cls.getMethod("print2", int.class);
        System.out.println(mtd);
        Object r = mtd.invoke(obj, 20);
        System.out.println(((Integer)r).intValue());
    }
}
/*결과값 : Test066A loaded
public int temp.Test066A.print2(int)
6000*/
package javaclass;

import java.lang.reflect.Method;

public class Test066_3 {
    public static void main(String[] args) throws Exception{
        Class<?> cls = Class.forName("temp.Test066A");
//        Object obj = cls.newInstance();
// Method는 C의 함수포인터의 역할을 한다.
//        cls.getMethods()는 모든 멤버함수의 포인터를 넘긴다.
//        cls.getMethod(...) : 단하나의 멤버함수의 포인터를 넘기다.
//        ...에는 함수이름, 매개뱐수의 형태를 명시한다.
//       Method mtd = cls.getMethod("print");
        Method mtd = cls.getMethod("print3");
        System.out.println(mtd);
        Object r = mtd.invoke(cls);
        System.out.println(((Integer)r).intValue());
    }
}

/*결과값 : Test066A loaded
public static int temp.Test066A.print3()
100*/

4.annotation

  • 클래스나 method에 붙임
  • 클래스가 컴파일되거나 런될때, annotation의 유무나 annotation 설정된 값을 통하여 클래스가 좀더 다르게 실행
    • 설정파일처럼 설정하는 경우도
  • 사용자 annotation 
    • annotation 정의
    • annotation를 class에서 사용
    • annotation을 이용해 실행
package temp;

public class Test067 {
    @PrintStars
    public int print(){
        return 100;
    }
}// javac -d C:\a\ -classpath C;\A\ Test067.java  -> import할 파일 위치

-----------------------------------------------------------------------------------
package temp;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface PrintStars {
}
-----------------------------------------------------------------------------------
package javaclass;

import temp.PrintStars;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

public class Test067_2 {
    public static void main(String[] args) throws Exception {
        Class<?> cls = Class.forName("temp.Test067");
        Object obj = cls.newInstance();
        Method mtd = cls.getMethod("print");
        Annotation anot = mtd.getAnnotation(PrintStars.class);
        Object r= mtd.invoke(obj);
        if(anot.toString().equals("@temp.PrintStars()")){
            System.out.println("**");
        }
        System.out.println(((Integer)r).intValue());
        System.out.println(anot);
        System.out.println(mtd);
    }
}// javac Test067_2.java 컴파일시
//java -classpath C:\A\;. Test067_2     //내가 실행시킬 위치는 뒤  불러올거는 클래스패스 뒤, 여러개 불러올거면 ;로구분

/*결과값 : **
100
@temp.PrintStars()
public int temp.Test067.print()*/

5.java.util.*

-List

  • arraylist : 내부 배열 이용 , 속도 빠름, 중간 삭제 수정 힘듬
  • LinkedList : node 이용, 속도 느림, 중간 삭제 수정 쉬움(포인터만 바꿔주면됨)
  • list 특징 : 1. 중복 허용 2. 순서 유 3. stack, queue 유용
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
//ArrayList 속도가 빠르다. 내부적으로 배열을 사용
//배열을 사용하기때문에 속도는 빠른데, 중간중간 삭제가일어나면 비효율적이다.
//LinkedList Node를 이용하기에 단순하게 쌓는 속도는 느리다.
//중간에 추가 삭제가 빈번한 경우에는 용이하다.
// 둘 다 List를 상속한다. List를 상속받은 클래스는 특징이 존재한다.
// - 중복되는 걸 허용한다.검색시에 들어간 순서대로 나온다.(순서대로 보관한다.)->스택이나 큐 만드는데 용이하다.
public class Test068 {
    public static void main(String[] args) {
        List<String> l = new LinkedList<>();
        l.add("apple");
        l.add("banana");
        l.add("orange");
        l.add("kiwi");

        for (String t : l) {
            System.out.println(t);
        }
    }
}//결과값 : apple banana orange kiwi

-Set

  • treeset : 트리를 이용해 검색 속도가 list보다 월등
  • hastset : 해쉬 알고리즘을 이용해 기억 장소 할당
  • set 특징 : 1. 중복 허용 x 2.순서 x
package javaclass;

import java.util.Set;
import java.util.TreeSet;
// Set 인터페이스를 상속받은 것 : TreeSet, HashSet
// 공통특징 : 순서 개념이 없다. 중복을 허용하지 않는다.
// 저장할때 용이 -> 검색속도가 List보다 월등함
// TreeSet : 트리를 이용하여 보관, HashSet은 Hash알고리즘을 이용
public class Test069 {
    public static void main(String[] args) {
        Set<String> l = new TreeSet<>();
        l.add("apple");
        l.add("banana");
        l.add("orange");
        l.add("kiwi");
        l.add("apple"); //중복된값

        for (String t : l) {
            System.out.println(t);
        }
    }
//결과값 : banana orange apple kiwi

-향상된 for문의 표준 검색 방법

Iterator<String> it = l.iterator();
        while (it.hasNext()) {
            String next =  it.next();
            System.out.println(next);
        }

//iterator를 이용한 삭제
package javaclass;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;
// Set 인터페이스를 상속받은 것 : TreeSet, HashSet
// 공통특징 : 순서 개념이 없다. 중복을 허용하지 않는다.
// 저장할때 용이 -> 검색속도가 List보다 월등함
// TreeSet : 트리를 이용하여 보관, HashSet은 Hash알고리즘을 이용
public class Test069 {
    public static void main(String[] args) {
        Set<String> l = new HashSet<>();
        l.add("apple");
        l.add("banana");
        l.add("orange");
        l.add("kiwi");
        l.add("apple"); //중복된값

        Iterator<String> it = l.iterator();
        while (it.hasNext()) {
            String next =  it.next();
            if(next.indexOf("an") != -1){
                it.remove();
            }
            System.out.println(next);
        }
    }
}

-Map

  • map 특징 : 1.순서 x 2.중복 x(덧 씌워짐)
package javaclass;

import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

//map도 순서개념이 없으며 반드시 key = value 형태로 저장되야함 사전과 같은 형태
//put에 함수로 저장, get 함수로 key에 해당하ㅏ는 value를 뽑아낸다.
//list, Set, Map 형태로 뭔가 저장하는 형태를 흔히 Collection이라고 한다.
public class Test070 {
    public static void main(String[] args) {
        Map<String, String> map = new Hashtable<>();
        map.put("apple", "사과");
        map.put("banana", "바나나") ;
        map.put("orange", "오렌지") ;
        map.put("kiwi", "키위") ;
        map.put("banana", "브내으너") ;

         String value = map.get("apple");
        System.out.println(value);

        Set<String> keys = map.keySet();
        Iterator<String> it = keys.iterator();
        while (it.hasNext()) {
            String next = it.next();
            String v = map.get(next);
            System.out.println(next+ ", " + v);
        }

        System.out.println(map);
    }
}/*
결과값 : 사과
banana, 브내으너
apple, 사과
orange, 오렌지
kiwi, 키위
{banana=브내으너, apple=사과, orange=오렌지, kiwi=키위}
*/

-Math.random();

package javaclass;

public class Test071 {
    public static void main(String[] args) {
        for (int i = 0; i < 20; i++) {
            double d = Math.random(); // 0부터 1까지의 소수값을 랜덤하게 출력한다.

            int a = (int) (d * 100); // 0~100까지
            System.out.println(a);
        }
    }
}

-Throw

    -각종 에러는 클래스로 구형

    -코드 수행시 에러가 발생하면 해당 예외클래스의 인스턴스를 throw해버린다

    -예외는 함수 수행 시에 발생되고, 함수에 그 사실을 명시

    -생성된 예의처리 못할 시 프로그램 종료

package javaclass;

class TempException extends RuntimeException{}
public class Test074{
    public static void main(String[] args) {
        int i = 0;
        if(i==0){
            throw new TempException();
        }
        System.out.println(0);
    }
}
package javaclass;

//연료 고갈이라는 에러를 클래스로 명시
class FuelException extends Exception{}
// Exception이 깐깐하다 : 컴파일이 안된다....
// 함수 안에서 에러가 발생 할 수 있다면 그 사실을 선언부에 명시해야 컴파일된다.
public class Test074{
    public void carDrive(int fuel) throws FuelException{ //thorws로 연료고갈이 생길수 있음을 명시
        if(fuel == 0){
            throw new FuelException();
        }
        System.out.println("gogo");
    }
    public static void main(String[] args) {
        Test074 t = new Test074();
        //throws FuelException으로 선언된 함수를 호출할 때는 반드시 에러가 발생할 수 이는 영역을 try{...}로 감싸준다.
        //try에는 반드시 1개이상의 catch가 있어야한다.
        //에러가 발생되면 에러 인스턴스를 throw한다.
        //catch(FuelException e)에 있는 e 변수가 발생된 에러 인스턴스를 가리 킬 수 있으면 catch에 딸린{...} 영역이 동작한다.
        //...에는 에러를 수습 할 수 있는 코드가 들어가는것이 바람직하다.
        //catch (Exception e)써도 됨 상속받기 떄문에 
        try {
            t.carDrive(100);
        } catch (FuelException e) {
            System.out.println("견인차를 불러라");
        }
    }
}
package javaclass;

class FuelException extends Exception{
    public void solve(){
        System.out.println("견인차를 불러라");
        //에러 처리
    }
}
public class Test074{
    public void carDrive(int fuel) throws FuelException{ 
        if(fuel == 0){
            throw new FuelException();
        }
        System.out.println("gogo");
    }
    public static void main(String[] args) {
        Test074 t = new Test074();
        try {
            t.carDrive(100);
        } catch (FuelException e) {
            e.solve();
        }
    }
}

문제

1. 복권 뽑기 1

public static int[] randomArray(int i, int max) {
        Set<Integer> si = new HashSet<>();
        while(si.size() < i){
            si.add((int)(Math.random()* max));
        }
        Object[] arr = si.toArray();
        int[] result = new int[i];
        int start = 0;
        for(Object obj : arr){
            result[start] = (int) obj;
            start++;
        }
        return result;
    }

2. 복권 뽑기2

   public static int[] randomArray2(int i, int max){
        int[] total = new int[max+1];
        int[] result = new int[i];
        for (int j = 0; j <= max; j++) {
            total[j] = 0;
        }
        int counter =0;
        while (counter < i) {
            int rand = (int) (Math.random() * max);
            if(total[rand] == 0){
                result[counter] = rand;
                counter ++;
                total[rand] = 1;
            }
        }
        return result;
    }

3.리스트 출력

    public static String collectionString(List<String> ls) {
        String result;
        if(ls.isEmpty()){
            return "[]";
        }else {
            StringBuilder sb = new StringBuilder();
            sb.append("[");
            int start= 1;
            int end = ls.size();
            for(String t : ls){
                sb.append("'");
                sb.append(t);
                sb.append("'");
                if(start == 1 && end ==1){
                    start++;
                    continue;
                }
                start++;
                if(start > end) {
                    break;
                }else {
                    sb.append(",");
                }
            }
            sb.append("]");
           result = sb.toString();
        }
        return result;
    }
}
// 2가지 이상의 다른 방법으로 구현 1가지는 collection 금지
public class Test072_HW {
    public static void main(String[] args) {

        int[] rl = HW.randomArray2(10, 100);
        for (int i = 0; i < rl.length; i++) {
        System.out.println(rl[i]);
        }

        List<String> ls = new ArrayList<>();
        ls.add("apple");
        ls.add("banana");
        ls.add("orange");
        ls.add("kiwi");
        String l = HW.collectionString(ls);
        System.out.println(l);
    }
}

첫 주 끝.. 알고리즘 꼭 다시 풀어보기 / 자동차 패키지 만들어보기 !

반응형

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

제주에서 자바_Week2_2  (0) 2019.07.24
제주에서 자바_Week2_1  (0) 2019.07.22
4. 클래스  (0) 2019.05.29
3. 참조 타입  (0) 2019.05.28
2. 조건문 & 반복문  (0) 2019.05.27
반응형

1. 모듈 :  변수, 함수, 클래스 등을 모아 놓은 파일 / 모듈에 정보를 한번만 정의해두면 여러 프로그램에서 가져다 씀.

# calculator.py
# calculator 모듈
 
# 합
def sum(x, y):
    return x + y
 
# 차이
def difference(x, y):
    return x - y
  
# 곱
def product(x, y):
    return x * y
 
# 제곱
def square(x):
    return x * x
 
----------------------------------------
# test.py
 
# calculator.py에서 sum 함수 불러오기
from calculator import sum
 
print(sum(35))  >> 8
 
#calculator.py에서 모든 함수 
from calculator import *
cs



2. randit / uniform 함수

randit : 두 정수 사이의 어떤 랜덤한 정수(난수)를 리턴시켜주는 함수

uniform : random이라는 모듈 안에 정의되어 있는, 두 수 사이의 랜덤한 소수(난수)를 리턴시켜주는 함수

from random import uniform
 
# a <= N <= b인, 랜덤한 소수(난수) N의 값을 리턴시켜준다.
= uniform(01)
print(x)
cs


3. input함수

사용자로부터 값을 입력받는 함수

name = input("이름을 입력하세요: ")
print("Hello " + name)
 
>> Hello 
cs


input 함수 통해 숫자 입력 받으려고 한다면

= int(input("첫 번째 정수: "))
= int(input("두 번째 정수: "))
print("두 정수의 합: %d" % (x + y))
 
>>3
>>4
>>7
cs


반응형

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

List & Tuple  (0) 2020.01.05
swap  (0) 2020.01.04
5. 제어문  (0) 2019.05.22
4. 추상화 심화  (0) 2019.05.08
3. 추상화  (0) 2019.04.06

+ Recent posts