ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 22-09-26_jsp(2)
    카테고리 없음 2022. 9. 26. 18:16

    --

    오전 마지막시간에logging framework를 사용하기 시작함

     

     

    예네는 리모콘 역할을 함 (Facade Pattern....역할)

     

     

    아래에 보면 써 있는

    jcl

    jacarta commons library??? 그런 거의 ㅜ줄임말이래요

    jcl은 apache.commons.logging의 줄임말이다(아파치 재단의 자카르타 프로젝트). jcl은 엄밀히 말하면 로거가 아니다. 로깅을 하는일을 하지 않는다. 로깅 라이브러리가 아니라 로깅 추상화 라이브러리다. 아래 링크 참조

    https://yangbongsoo.gitbook.io/study/undefined/log

     

    로그는 반드시 필요한 내용만 찍자 - 양봉수 블로그

    Story10 로그는 반드시 필요한 내용만 찍자

    yangbongsoo.gitbook.io

    리모콘들..

     

    Hierarchy 통해서 어디서 왔는지 의존관계 볼 수 있는데, 

     

     

     

    이릏게 하면 우리가 쓰던 common logging이 사용중이던 dependencies 목록에서 없어짐

     

    우리에게 결정권이 있는게 아니라

    framework에게 결정권이 있다는걸 보여주는 게, 설정파일에 대한 것... 설정파일이 있잖아요?

    이런건데, 이게 왜 여기에있고 이게 무슨의미인지 알아보자

     

    --

    아파치 홈페이지로 가봅시다

     

    https://logging.apache.org/log4j/2.x/manual/configuration.html

     

    Log4j – Configuring Log4j 2

    Configuration Inserting log requests into the application code requires a fair amount of planning and effort. Observation shows that approximately 4 percent of code is dedicated to logging. Consequently, even moderately sized applications will have thousan

    logging.apache.org

    여기 configuration에 들어와서 보면

     

    이부분에

     

    읽어보면

     

    설정파일(classpath)에 저 이름(log4j2.xml)으로 넣어두면 사용할 수 있다고 함

     

    이제 위의 코드를 복사해서

    <?xml version="1.0" encoding="UTF-8"?>
    <Configuration status="WARN">
      <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
          <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
        </Console>
      </Appenders>
      <Loggers>
        <Root level="error">
          <AppenderRef ref="Console"/>
        </Root>
      </Loggers>
    </Configuration>

     

    우리가 만들어뒀던 xml에 코드를 바꿔줍시다.

     

    이렇게 바꿔서 daoimpltest를 다시 해보자. level을 debug로 설정해보고

     

    이렇게 debug들 출력됨 

     

    코드를 자세히 보면 이런 것들이 있는데, 여기에 level에 출력되던게 [DEBUG] 였고

     

    logger에 출력되던게 

    이런 것들임

    저 익숙한 애들 보이는데

     

     

     

    우리가 사용하는 쿼리문 이런거 다 보여주져

     

    -

    자 이제 logging이란..뭔가 기록하는건데요

    1) 어디에 기록을 할 거냐 ->appender : 어디에 기록할지 장소. , 동시에 여러개 설정할 수 있음. (Appenders, 복수설정가능)

    2) 어떤 형식으로 기록할거냐 --> PatternLayout : 

    3) 무엇을 기록할거냐 --> 메세지, logger 옆에 모든 것...

    이런거

     --뭘 어디에 어떻게, 그리고 누가? 기록할거냐

    4) 누가 기록할거냐 : loggers

    저놈에 의해 기록됨

    그리고 마지막으로

    5) level : logging event 등급 (error, debug....종류들이 있음. )

    appender : 로그 기록 매체
    layout : 로그 형식 (매체)
    message : 설정(파일)에 포함되지 않음.
    logger : 로그 메시지를 로깅 프레임워크에 전달하는 전달자(로그를 기록하는 당사자)
    level : 로깅 이벤트 등급 (debug < info < warn < error < fatal )

    근데 이거 좀 레벨이 극단적이죠. 너무 많이 나오거나, 너무 안나오거나. 

    왜냐면, logger를 하나만 써서 그래요. 

     

    여기 로그에 보면

    똑같죠? 그리고 ' . ' 으로 나뉘죠? 계층구조가 있다는건데요  쟤를 복사해보고요

     

    <?xml version="1.0" encoding="UTF-8"?>
    <!-- appender : 로그 기록 매체 -->
    <!-- layout : 로그 형식 -->
    <!-- message : 설정에 포함하지 않음. -->
    <!-- logger : 로그 메시지 전달자 -->
    <!-- level : 로깅 이벤트 등급. debug < info < warn <error < fatal -->
    <Configuration status="WARN">
      <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
          <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
        </Console>
      </Appenders>
      <Loggers>
      	<Logger name="kr.or.ddit.member.dao.MemberDAO.selectMemberList" level="debug">
      		<AppenderRef ref="Console"/>
      	</Logger>
        <Root level="error">
          <AppenderRef ref="Console"/>
        </Root>
      </Loggers>
    </Configuration>

    이렇게 써보면 (Logger를 하나 추가해줬습니다. )

     

    양이 확 줄었어요

     

    그런데 똑같은 메세지가 두번 나오네여? 중복이예요

    그러면

    역시 홈페이지에 설명서가 다있거든요 열어서 확인해봅니다

    여기보면 

    두번 나오면

    이 속성 additivity="false" 로 설정해주면 된대요

     

     

     

    칼같이 적용해서 이렇게 추가해주면

     

    중복이 짠 없어지죠

     

    그리고  어차피 같은 패키지 구조에서의 반복이니까

    이 뒤에 패키지들을 생략해주면 

    다른것들도 잘나오죠. 

     

     

    그런데 이제 member 말고 prod 등도 쓸 수 있으니까.

     

    ddit 까지만 써줍니다. 그래도 똑같이 나옴. 

    이정도 레벨으로 설정해줍시다

     

     

     

    --

     

    이제 필드에서 system.out.println을 못 쓴다고 했는데요. 안써야 하는거예요

     

    ???왜

     

    ??못들음

     

     

    --

    네 다음....

    이케 추가해주고요

    주석에 있는것처럼, 하나 만들어서 열심히 재활용 할 거예요, 그래서 상수(final static)으로 만들었어요

     

    이런 식으로 추가해줄거예요

    ** 여기서 기록할 때 이런 모양을 쓰는데, 중괄호를 활용해서

    log.info("prodList : {}", member.getProdList());

    이렇게 하면 컨캣 연산자 '+' 를 안써도 저 빈칸에 콤마 뒤의 데이터를 중괄호 안에 넣는다는 뜻이니까 이렇게 써도 되어요

     

    --

     

    이제 outLine view를 같이 보면서 할거예요

     

    좌측 OutLine에 보면 뭐가 생겼다 없어졌다 하죠

    여기 이렇게 Logger 주석처리하면 사라지면서 에러나는데 어노테이션 추가하면 또 잘되요 옆에 outline에 보면 다시 생기죠

    하도 반복되고 잘쓰이니까 lombok에서 이미 추가해놨어요

     

    --

    다 저렇게 수정하고 실행하면

    잘 나오죠. 근데 뭐가 어딘지 모르겠져

    콘솔에 중간에 logger를 보면 어디서 실행되었는지 알 수 있져

     

    근데 불필요한게 너무많아요. 빼야죠

    시간? 의미없어. 어떤 스레드에서 실행되었는지? 안봐도 돼요

     

    형식을 바꿔야 해요

     

    형식을 정하는 레이아웃이 

    <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>

    이렇게 있네요 이게 무슨 의미인지 알아야죠

     

    홈페이지에 다시 보면

     

    이런게 있어요 Appenders와 Layouts가 있네요

     

    https://logging.apache.org/log4j/2.x/manual/appenders.html

     

    Log4j – Log4j 2 Appenders

    facility String The facility is used to try to classify the message. The facility option must be set to one of "KERN", "USER", "MAIL", "DAEMON", "AUTH", "SYSLOG", "LPR", "NEWS", "UUCP", "CRON", "AUTHPRIV", "FTP", "NTP", "AUDIT", "ALERT", "CLOCK", "LOCAL0",

    logging.apache.org

    Appender를 먼저 봅시다. 

     

    이 log라는거는 

    저장할때 콘솔에다가만 기록하면, 콘솔이 종료되자마자 휘발되서 날아가는 데이터죠

     

    근데 여기에 보면

     

    이런것들도있어요

    JDBC로 기록해서 appender에서 위치를 정해서 파일로 저장해두면 파일을 가지고 통계도 낼 수 있고 활용할 수 있겠져

    그럼 휘발성 데이터가 아니게 되는 거예요

     

    이제 layouts도 보면

    https://logging.apache.org/log4j/2.x/manual/layouts.html

     

    Log4j – Log4j 2 Layouts

    facility String The facility is used to try to classify the message. The facility option must be set to one of "KERN", "USER", "MAIL", "DAEMON", "AUTH", "SYSLOG", "LPR", "NEWS", "UUCP", "CRON", "AUTHPRIV", "FTP", "NTP", "AUDIT", "ALERT", "CLOCK", "LOCAL0",

    logging.apache.org

     

    이런 결과가 나오는 패턴들이 있대요

    이 Patterns에 데이터별로 표시형식이 있어요. 참고해서 수정하면 됩니다ㅏ..

    이걸 다 외울 생각을 하는 것보다, 이런 것들을 홈페이지에서 보고 활용하시면 됩니다. 

     

    이런식으로 표시되어있던거져

    저 t를 L (Line)으로 쓰면

     

    몇 번째 라인에서 출력되고 있는지. 위치를 보기도 좋겠죠. 

     

          <PatternLayout pattern="%-5level %logger{1.}[%L] - %msg%n"/>

    이렇게 수정해주면

     

    쪼금 쓸만해졌죠

     

     

    --

    이제 Log4jdbc를 적용해볼거예요

     

    여기에 가봅시다

    https://log4jdbc.brunorozendo.com/

     

    Log4jdbc-log4j2

    This project was imported from https://code.google.com/archive/p/log4jdbc-log4j2/ Original License: Apache License 2.0 log4jdbc-log4j2 is a modification of log4jdbc to natively use Log4j 2 (or SLF4J as usual), that supports JDBC 4.1 to JDBC 3, includes all

    log4jdbc.brunorozendo.com

    여기보면 지원내용, 설치... 등등 있어요 잘 보세요

     

     

    하지만 우리는 메이븐을쓰져?

    mvnrepository에 갈거예요

    여기에서 검색해서

    최신버전을

    추가해줍니다

     

    다시 홈페이지를 읽어보자

    1,2단계 까지 하고

    3단계에 보면 앞에다가

     jdbc:log4

    이렇게 넣어주라는거예요

    기존의 빨강 url이 있으면

    jdbc:log4 이거를 넣어서

    아래의 파랑 url처럼 바꿔주라는거예요

     

     

    이릏게 적용하라는 말이고요

     

    브라우저에 방법 나와있으니 따라서 하시면 되세여

    (수업들으면서 치기 벅차서 대강 적었기에..)

     

     

    3.2. Change the driver used

    Set your JDBC driver class to net.sf.log4jdbc.sql.jdbcapi.DriverSpy in your application 

     

     

     

    네 저렇게 다 순서대로 설정 해주시면 됩니다..

    이렇게

    이하생략

     

     

    --

    자 그러면 이제 예제를 가지고 놀아봅시다

    이제 이놈들 보면 아래에 예제가 몇 개 있쬬

     

    우리는

    jdbc.sqltiming

    이걸 한번 써봅시다

     

     

    --

    이렇게 해주시고요

    daoimpltest 해보면

    이렇게 실행시간도 나오고 기타등등이예요

     

     

    -못들음

     

    --

    근데 log 레벨이 낮아서 쓸모없는것들도 나오네요

    레벨을 조금 높여주시면

    쓸모있는것만 나와여

     

     

    이번엔

    jdbc.resultsettable

    이걸 써봅시다

     

    <?xml version="1.0" encoding="UTF-8"?>
    <!-- appender : 로그 기록 매체 -->
    <!-- layout : 로그 형식 -->
    <!-- message : 설정에 포함하지 않음. -->
    <!-- logger : 로그 메시지 전달자 -->
    <!-- level : 로깅 이벤트 등급. debug < info < warn <error < fatal -->
    <Configuration status="WARN">
      <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
          <PatternLayout pattern="%-5level %logger{1.}[%L] - %msg%n"/>
        </Console>
      </Appenders>
      <Loggers>
      	<Logger name="kr.or.ddit" level="info" additivity="false">
      		<AppenderRef ref="Console"/>
      	</Logger>
      	<Logger name="jdbc.sqltiming" level="debug" additivity="false">
      		<AppenderRef ref="Console"/>
      	</Logger>
      	<Logger name="jdbc.resultsettable" level="debug" additivity="false">
      		<AppenderRef ref="Console"/>
      	</Logger>
        <Root level="error">
          <AppenderRef ref="Console"/>
        </Root>
      </Loggers>
    </Configuration>

     

    이렇게 그러면

     

    wow 표로 나와요

     

    요런식으로 적용하실수가 있다 그말이예요

     

    ===

     

    이제 다음은 뭘 해볼거냐면요

    우리가 관리하는 도메인에 상품을 추가해볼거예요, 실전예제에요

     

    다 해봅시다

    package 만들어주고, folder 만들어 주고요

     

    mapper 파일 만들어 주고, namespace설정해 준 뒤에 (저거 prodDAO로 오타났는데 ProdDAO고 고쳤어요)

     

     

    configuration 파일에 mapper를 기록해줍니다. 

     

    이제 dao interface, impl..... 등등 만들어서 완성해봅시다. 

     

    과제1)

    조회계열의 두개 메서드 완성해보기 (select, selectList ) 

    이에 대한 test case도 완성해보기

     

     

    ------

    --// 상품아이디, 상품명, 판매가, 구매가, 마일리지.  + 상품분류명, 거래처명
    
    SELECT PROD_ID, PROD_NAME, PROD_PRICE
        ,PROD_COST, PROD_MILEAGE
        ,BUYER_NAME
        ,LPROD_NM
    FROM PRODVIEW;
    
    
    
    
    --//상품 전체 정보 + 분류명, 거래처명, 상품 구매자 목록 (구매자 아이디, 구매자명, 지역, 이메일)
    
    WITH CARTVIEW AS(
        SELECT DISTINCT CART_MEMBER, CART_PROD
        FROM CART
    ), CARTMEMBER AS(
        SELECT CART_PROD, MEMBER.*
        FROM CARTVIEW INNER JOIN MEMBER ON (CART_MEMBER = MEM_ID)
    )
    SELECT PROD.*, CARTMEMBER.*
    FROM PROD LEFT OUTER JOIN CARTMEMBER ON(PROD_ID = CART_PROD)
    WHERE PROD_ID = 'P101000001';

     

    ---

    코드 및 테스트 결과

     

    Configuration.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd" >
    <configuration>
    	<properties resource="kr/or/ddit/mybatis/DBInfo.properties" />
    	<settings>
    		<setting name="mapUnderscoreToCamelCase" value="true"/>
    	</settings>
    	<typeAliases>
    		<package name="kr.or.ddit.vo"/>
    	</typeAliases>
    	<environments default="dev">
    		<environment id="dev">
    			<transactionManager type="JDBC" />
    			<dataSource type="POOLED">
    				<property name="driver" value="${driverClassName}"/>
    				<property name="url" value="${url}"/>
    				<property name="username" value="${user}"/>
    				<property name="password" value="${password}"/>
    				<property name="poolMaximumActiveConnections" value="${maxTotal}"/>
    				<property name="poolMaximumIdleConnections" value="${maxIdle}"/>
    				<property name="poolTimeToWait" value="${maxWait}"/>
    			</dataSource>
    		</environment>
    	</environments>
    	<mappers>
    		<mapper resource="kr/or/ddit/mybatis/mapper/Member.xml"/>
    		<mapper resource="kr/or/ddit/mybatis/mapper/Prod.xml"/>
    	</mappers>
    </configuration>

    .

     

    prod.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="kr.or.ddit.prod.dao.ProdDAO">
    
    	<resultMap type="ProdVO" id="prodListMap" autoMapping="true">
    		<id property="prodId" column="PROD_ID"/>
    		<!-- 컬럼 하나를 담을수있는X, 무엇을 담을지 타입을 정해주고, 밑에 쿼리문에 없으면
    		에러나니까 autoMapping하기. -->
    		<association property="buyer" javaType="BuyerVO" autoMapping="true" />
    	</resultMap>
    	<resultMap type="ProdVO" id="prodMap" autoMapping="true" extends="prodListMap">
    		<collection property="memberList" ofType="MemberVO" autoMapping="true">
    			<!-- 중복여부 판단하는 식별자 id, primary key라서, 이에따른 equal메서드가 구현되어서 -->
    			<id property="memId" column="MEM_ID"/>
    		</collection>
    	</resultMap>
    	
    	<select id="selectProdList" resultMap="prodListMap">
    		SELECT PROD_ID, PROD_NAME, PROD_PRICE
    		    , PROD_COST, PROD_MILEAGE
    		    , BUYER_NAME
    		    , LPROD_NM
    		FROM PRODVIEW
    	</select>
    	
    	<select id="selectProd" parameterType="string" resultMap="prodMap" >
    		WITH CARTVIEW AS(
    		    SELECT DISTINCT CART_MEMBER, CART_PROD
    		    FROM CART
    		), CARTMEMBER AS(
    		    SELECT CART_PROD, MEMBER.*
    		    FROM CARTVIEW INNER JOIN MEMBER ON(CART_MEMBER = MEM_ID)
    		)
    		SELECT
    		    PRODVIEW.*
    		    , CARTMEMBER.*
    		FROM PRODVIEW LEFT OUTER JOIN CARTMEMBER ON(PROD_ID = CART_PROD)
    		WHERE PROD_ID = #{prodId}
    	</select>
    </mapper>

    ProdVO.java

    package kr.or.ddit.vo;
    
    import java.io.Serializable;
    import java.util.List;
    import java.util.Set;
    
    import com.fasterxml.jackson.annotation.JsonIgnore;
    
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.EqualsAndHashCode;
    import lombok.NoArgsConstructor;
    import lombok.ToString;
    
    @ToString(exclude = {"prodDetail"})
    @EqualsAndHashCode(of = {"prodId"})
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class ProdVO implements Serializable{
    	private String prodId;
    	private String prodName;
    	private String prodLgu;
    	
    	private String lprodNm;
    	
    	private String prodBuyer;
    	private Integer prodCost;
    	private Integer prodPrice;
    	private Integer prodSale;
    	private String prodOutline;
    	@JsonIgnore
    	private transient String prodDetail;
    	private String prodImg;
    	private Integer prodTotalstock;
    	private String prodInsdate;
    	private Integer prodProperstock;
    	private String prodSize;
    	private String prodColor;
    	private String prodDelivery;
    	private String prodUnit;
    	private Integer prodQtyin;
    	private Integer prodQtysale;
    	private Integer prodMileage;
    	
    	private BuyerVO buyer; // has A
    	
    	private Set<MemberVO> memberList; // has Many
    }

     

    ProdDAO.java

    package kr.or.ddit.prod.dao;
    
    import java.util.List;
    
    import org.apache.ibatis.annotations.Param;
    
    import kr.or.ddit.vo.ProdVO;
    
    /**
     * 상품 관리 Persistence Layer
     *
     */
    public interface ProdDAO {
    	public int insertProd(ProdVO prod);
    	public ProdVO selectProd(@Param("prodId") String prodId);
    	public List<ProdVO> selectProdList();
    	public int updateProd(ProdVO prod);
    //	public int deleteProd(String prodId);
    }

    ProdDAOImpl.java

    package kr.or.ddit.prod.dao;
    
    import java.util.List;
    
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    
    import kr.or.ddit.mybatis.CustomSqlSessionFactoryBuilder;
    import kr.or.ddit.vo.ProdVO;
    
    public class ProdDAOImpl implements ProdDAO {
    	
    	private SqlSessionFactory sqlSessionFactory =
    			CustomSqlSessionFactoryBuilder.getSqlSessionFactory();
    
    	@Override
    	public int insertProd(ProdVO prod) {
    		// TODO Auto-generated method stub
    		return 0;
    	}
    
    	@Override
    	public ProdVO selectProd(String prodId) {
    		// 상품 전체 정보 + 분류명, 거래처명, 상품 구매자 목록(아이디, 구매자명, 지역, 이메일)
    		try(
    			SqlSession sqlSession = sqlSessionFactory.openSession();
    		){
    			ProdDAO mapper = sqlSession.getMapper(ProdDAO.class);
    			return mapper.selectProd(prodId);
    		}
    	}
    
    	@Override
    	public List<ProdVO> selectProdList() {
    		// 상품아이디, 상품명, 판매가, 구매가, 마일리지. + 분류명, 거래처명, 해당 상품의 구매자수
    		try(
    			SqlSession sqlSession = sqlSessionFactory.openSession();
    		){
    			ProdDAO mapper = sqlSession.getMapper(ProdDAO.class);
    			return mapper.selectProdList();
    		}
    	}
    
    	@Override
    	public int updateProd(ProdVO prod) {
    		// TODO Auto-generated method stub
    		return 0;
    	}
    
    }

     

    ProdDAOImplTest.java

    package kr.or.ddit.prod.dao;
    
    import static org.junit.Assert.*;
    
    import java.util.List;
    
    import org.junit.Test;
    
    import kr.or.ddit.vo.ProdVO;
    import lombok.extern.slf4j.Slf4j;
    
    @Slf4j
    public class ProdDAOImplTest {
    	
    	ProdDAO dao = new ProdDAOImpl();
    
    	@Test
    	public void testInsertProd() {
    		fail("Not yet implemented");
    	}
    
    	@Test
    	public void testSelectProd() {
    		ProdVO prod = dao.selectProd("sdfasdasdf");
    		assertNull(prod);
    		prod = dao.selectProd("P101000001");
    		assertNotNull(prod);
    		log.info("prod: {}", prod);
    	}
    
    	@Test
    	public void testSelectProdList() {
    		List<ProdVO> prodList = dao.selectProdList();
    		log.info("prodList: {}", prodList);
    	}
    
    	@Test
    	public void testUpdateProd() {
    		fail("Not yet implemented");
    	}
    
    }

     

    테스트하면

    이렇게 잘 나옴

     

    ----

    예제 확장..

     

     

    이제 추가로 count 해서 숫자도 넣어주자

    --//상품아이디, 상품명, 판매가, 구매가, 마일리지
    --// + 분류명, 거래처명, 해당 상품의 구매자수(MEM_COUNT)

     

    쿼리문 먼저 써봅시다.

     

    https://galid1.tistory.com/609

     

    Mysql - 집계함수와(sum, count) Group query 사용법 (GROUP BY, HAVING)

    mysql group by를 쓰는 곳과 사용법 이번 시간에는 Group query 라고 불리우는 SQL의 Group by , Having 절에 대해서 알아보겠습니다. xxxxxxxxxx mysql> select * from citykorea; +------+------------+--------..

    galid1.tistory.com

    --//상품아이디, 상품명, 판매가, 구매가, 마일리지
    --// + 분류명, 거래처명, 해당 상품의 구매자수(MEM_COUNT)
    
    WITH CARTCNT AS(
        SELECT CART_PROD, COUNT(DISTINCT CART_MEMBER) MEM_COUNT
        FROM CART
        GROUP BY CART_PROD
    )
    SELECT PROD_ID, PROD_NAME, BUYER_NAME, LPROD_NM
        , NVL(MEM_COUNT, 0) MEM_COUNT
    FROM PRODVIEW LEFT OUTER JOIN CARTCNT ON (PROD_ID = CART_PROD);

    COUNT했음

     

    중첩 쿼리도 쓸거예요

    중첩 쿼리

    1. FROM절 : INlINE VIEW
    2. WHERE절 : SUB QUERY
    3. SELECT절 : SCALA QUERY

     

    SCALA QUERY를 써봅시다.

     

    ---

    SCALA DATA  값만 존재, 크기와 방향이 없다. 즉 차원(Dimention)이 없다
    VECTOR DATA 차원을 가짐 (2차원배열처럼), length가 있다는건 크기를 갖고 있다는거고, 방향도 갖고 있는 데이터
    SCALA QUERY 크기, 방향이 없는 상태에서,  record 하나, column 하나가 있을 때 사용 가능. 하나의 값만 조회됨
           

     

     

     

    --중첩쿼리
    --3. SELECT절 : SCALA QUERY
        SELECT PROD_ID, PROD_NAME, PROD_PRICE
    		    , PROD_COST, PROD_MILEAGE
    		    , BUYER_NAME
    		    , LPROD_NM
                , (
                    SELECT COUNT(DISTINCT CART_MEMBER)
                    FROM CART
                    WHERE PROD_ID = CART_PROD
                ) MEM_COUNT
        FROM PRODVIEW;

     

    --

    layered architecture 이용해서 응집력 높였을 때의 장점. --> 수정할 일이 줄어들음  ... 유지보수가 편리

     

     

    -------------------

    다음문제예요

     

    이건 제가 풀었어요

    --1. 회원중에서 지금까지 구매기록이 없는 회원의 기본 정보 조회
    SELECT MEMBER.*, CART_QTY
    FROM MEMBER LEFT OUTER JOIN CART ON (MEM_ID = CART_MEMBER)
    WHERE CART_QTY IS NULL;
    
    
    --2. 회원중에서 지금까지 구매기록이 1건 이상 있는 회원의 기본 정보 조회
    SELECT MEMBER.*, CART_QTY
    FROM MEMBER LEFT OUTER JOIN CART ON (MEM_ID = CART_MEMBER)
    WHERE CART_QTY IS NOT NULL;

     

    이건 현우의 풀이예요

    - JOIN하지 않고도 조건절에서 필터링을 한 거예요

     

    이건 혜연이가 한 거예요

     

    이렇게 해도 되요 중복제거는 필요하지만

     

    ---

     

    이제 insert를 만들건데요

    ----

    아우 다시 신나는 SQL 시간이예요 넘어가봅시다

    일단 prod_id와 prod_lgu를 보면, 규칙성이있어요. 주석에 달린 규칙이예요

     

    ---

    해당 분류의 상품이 없는 경우도 있는데, 이 떄는 NULL이 아닌 0이 나와야 하니까

     

    NVL처리를 해줍니다

     

    이 쿼리를 설명을 하자면

    LPAD(내용,6,'0') 내용을 6자리로 만들고, 빈 자리만큼 왼쪽에 0으로 채워줍니다(LEFT PADDING)
    NVL(내용, 0) +1 내용이 NULL이면 0으로 만들어주고, 1을 더해줍니다
    TO_NUMBER(내용) 내용의 데이터 형식을 숫자로 Parsing 해 줍니다
    SUBSTR(내용,5) 내용의 5번째 앞까지 문자를 자릅니다.
    MAX(내용) 내용의 값중 가장 큰 값을 표시합니다 
           --> 가장 큰 값 + 1 하면서 아이디가 늘어나야 하기 때문
           

     

     

    --PROD_ID , 10글자, 앞4글자는 PROD_LGU, 그 뒤는 일련번호로 증가. 
    --특정길이의 문자열로 만들면서 빈칸에는 0을 넣어준다. Padding, 그런데 왼쪽에
    --넣어줄거니까, LPAD (6칸으로 만들어 줄 거고, 빈칸에응 0 넣어줄 것)
    SELECT 'P101' || LPAD(NVL(TO_NUMBER(SUBSTR( MAX(PROD_ID), 5 )),0) +1, 6, '0')
    FROM PROD
    WHERE PROD_LGU = 'P101';

    ----

    <insert id="insertProd" parameterType="ProdVO">
    		<!-- Primary Key 생성가능 -->
    		<!-- order="BEFORE" 속성을 넣어주면 아래의 쿼리보다 먼저 실행됨 -->
    		<selectKey order="BEFORE" resultType="string" keyProperty="prodId">
    			SELECT #{prodLgu} || LPAD(NVL(TO_NUMBER(SUBSTR(MAX(PROD_ID), 5 )),0) +1, 6, '0')
    			FROM PROD
    			WHERE PROD_LGU = #{prodLgu}
    		</selectKey>
    		INSERT INTO PROD
    		(
    		PROD_ID
    		)VALUES(
    		#{prodId,jdbcType=VACHAR}
    		)
    	</insert>

    이렇게 하면, (keyProperty설정) 내부적으로는 setter가 소환되서 비어있는 id가 채워지는거지...

     

     

    [수업끝]-------------------

     

    --과제1,2) 자이제 나머지 코드를 완성해서 insert와 update를 완성해보세요

    --이건 오늘의 미션이예요

     

    -- 과제3 ) 오늘부터 시작하는 장기과제가 있어요....

    - WEB APPLICATION 만들기...

     

    과제를 위한 밑작업..

    DEVELOPER에 가 보세요....

     

    그동안은 MariaDB의 emp를 가지고 놀아보세요 했는데요

    걔는 데이터도 없고 테이블도 하나였잖아요?

     

    이제 좀 더 다양하게 놀아보아야 해요

    그러기 위해서 이제 계정을 추가할거예요...

    오라클이 설치된 위치로 가 봅니다. 

    이 경로를 타고 타고 와서
    이 경로에 보면... 있는데 이건
    아주 복잡해서 지금은 안할거예요

     

    ----

    다른걸 합시다

    우리는 여기에서
    이걸 가지고 놀거거든요
    D: 에 복사해서 넣어주고요
    열어보면 이렇게 생긴 파일이거든요

     

    --

    쟤를 이제 적용해줄거예요

    자sql developer로 와서요

    관리자 계정으로  와 주세요

     

    @ 이거는 실행하겠다는 뜻인데요

    @d:\scott.sql

    이렇게 작성해서 실행해줍니다

     

    그리고&nbsp; select 문을 통해서 조회해 봤을 떄 scott이 들어있으면 잘 된거예요

     

    암호를 java 로 바꿔줄거예요 HR테이블도 SCOTT테이블도
    그리고 이놈들이 잠겨서 사용할 수 없을 수도 있으니까 잠금을 해제 해 주고요, 계정을 추가해주세요

     

     

     

    그러면 준비가 다 되었죠 그러면 application을 만들도록..하세요...

     

    (이런 순서로 진행하시면 됩니다,,)

    1. maven 프로젝트 만들어요

    2. layered architecture 만들어요

    3. dao 만들려면... 저 테이블의 scheme 알아야 해요 알아서 적용하세요

     

    테이블 열어보면 이렇게 열, 데이터 등이 있어요

     

    쿼리도 많이 연습해보시고요

     

    그냥 쿼리 연습이 만약 하고싶으시면 

    HR계정 열어보세요

    좀더 테이블이 많고요 관계가 다 이어져 있어요

    연습하기 더 좋죠

     

    ---

    과제4)...db 10제를 하세요

    1. 남녀 성별 회원수 조회
    2. 구매기록이 없는 회원의 인적사항 조회(아이디, 이름, 이메일)
    or
    구매기록이 있는 회원의 인적사항 조회(아이디, 이름, 이메일)
    3. 등록된 상품이 한건도 없는 상품분류 조회(상품분류코드, 분류명)
    4. 지금까지 가장 많이 팔린 상품 조회(상품코드, 상품명, 상품분류명, 거래처명, 마일리지)
    5. 지금까지 가장 적게 팔린 상품 조회(상품코드, 상품명, 상품분류명, 거래처명, 마일리지)
    6. 거래처 중 거래 품목 수가 가장 많은 거래처 조회(거래처코드, 거래처명, 거래처분류명, 담당자명)
    7.   거래처 중 거래 품목 수가 가장 적은 거래처 조회(거래처코드, 거래처명, 거래처분류명, 담당자명)
    8. 남녀 성별 각각 구매율이 높은 상품 조회(성별, 상품코드, 상품명, 분류명)
    9. 각 회원별 구매 총액 조회(회원아이디, 회원명, 구매총액)
    10. 각 상품별 구매왕 조회(구매왕아이디, 회원명, 구매총액)

     

    -----

    정리

    오늘 한것들과, 내일부터 할 것(빨간색으로 표시)

     

    이렇게 layered 구조에서 계속 framework들을 더하고 있음. 

    과제도 이런 구조로 계속 짤 것.

     

Designed by Tistory.