[1028web JSTL ]커스텀 라이브러리 2022.03.19
VelocityEngine 2022.02.19
Java 프로그래밍 언어의 코드 규칙, java 표준 코딩 2021.12.16
[1028web annotation] 어노테이션 2021.08.29
[스터디할래? Java] 목차 2021.05.17
[스터디할래? Java 15]lambda 람다 2021.05.15
[스터디할래? Java 14]제네릭 2021.05.15
[스터디할래? Java 13]I/O 2021.05.15
[스터디할래? Java 12]애노테이션 2021.05.15
[스터디할래? Java 11]enum 2021.05.15
[스터디할래? Java 10]멀티쓰레드 프로그래밍 2021.05.15
[스터디할래? Java 09]예외처리 2021.05.14
[스터디할래? Java 08]인터페이스 2021.05.14
[스터디할래? Java 07]패키지 2021.05.14
[스터디할래? Java 06]상속 2021.05.14
[1028 Spring boot] 에러모음 2021.05.11
[1028web.com] Spring boot 2 Validation Example 2021.05.09
[1028 JPA]에러모음 2021.05.06
Runner 구현 2021.05.03
[1028 from 스프링 백기선 JPA] 스프링데이터 Common _ 쿼리, 비동기, 도메인, QueryDSL (추후 추가. ) 2021.05.03
[1028 from 스프링 백기선 JPA] 스프링데이터 Common _ Repository, Interface, null 2021.05.03
[1028 from 스프링 백기선 JPA] 스프링데이터 _ JPA 원리, 스프링데이터 모듈 2021.05.03
[1028 from 스프링 백기선 JPA]Hibernate _ 엔티티, Cascade, Fetch, Query FROM EntityManager 2021.04.30
스프링 목차 2021.04.29
[1028 FORM 백기선 스프링프레임워크 핵심기술] SpEL, AOP,Null-safety 2021.04.29
[1028 FORM 백기선 스프링프레임워크 핵심기술] Validation, 데이터 바인딩. 2021.04.28
[1028 FORM 백기선 스프링프레임워크 핵심기술] Environment, MessageSource, ApplicationEventPublisher, ResourceLoader 2021.04.28
[1028 FORM 백기선 스프링프레임워크 핵심기술] IoC 컨테이너와 빈 2021.04.28
[1028 from 백기선 스프링 JPA] 릴레이션 vs JPA, postgres using docker 2021.04.27
[스터디할래? Java 05] 클래스_ BinrayTree_DFS,BFS 2021.04.27
728x90

error 1. 

문제 Integer로 정의된 Map 이 연산식으로 만들어진 숫자키를 읽지 못함 cannot get Map Integer key's value
검색  
해결 taglib 로 Integer 로 형변환하는 태그 생성해서 호출함 정상 확인

커스텀 테그 라이브러리 생성

1. taglibs 프로젝트에 등록

- pom.xml  taglibs-standard-impl 추가. 

- maven Reload project

		<dependency>
			<groupId>org.apache.taglibs</groupId>
			<artifactId>taglibs-standard-impl</artifactId>
			<version>1.2.5</version>
		</dependency>

2. 동작할 메소드 생성

- static으로 생성, 내부에 static 선언의 필요할수 있으니 주의할것.

public class MimimiTagLibHandler extends SimpleTagSupport {

    public static Integer integerValueOf(int number){
        return new Integer(number);
    }
}

3. jsp에서 호출할수있게 설정

- /WEB-INF/임의 폴더/XXXX.tld 추가. 

- show-name <c:   부분  <mimimi:

- uri :  jsp taglib 선언시 주소 와 맵핑 

- function-class : 클래스 정보,  function-signature : 메소드 정보

<?xml version="1.0" encoding="UTF-8"?>
<taglib version="2.0" xmlns="http://java.sun.com/xml/ns/j2ee"
        xmlns:xml="http://www.w3.org/XML/1998/namespace"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee  http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd ">

    <description>mimimi tag library</description>
    <tlib-version>1.0</tlib-version>
    <short-name>mimimi</short-name>
    <uri>/WEB-INF/taglib/mimimi-taglib.tld</uri>

    <function>
        <name>integerValueOf</name>
        <function-class>com.web.team.handler.MimimiTagLibHandler</function-class>
        <function-signature>java.lang.Integer integerValueOf(int)</function-signature>
    </function>
</taglib>

4. jsp 호출 사용

<%@ taglib prefix="mimimi" uri="/WEB-INF/taglib/mimimi-taglib.tld" %>
${mimimi:integerValueOf(bibleOn.chapterNo-1)}

 

참고 : https://dion-ko.tistory.com/47

'JAVA' 카테고리의 다른 글

[1028web JSTL ]커스텀 라이브러리  (0) 2022.03.19
VelocityEngine  (0) 2022.02.19
Java 프로그래밍 언어의 코드 규칙, java 표준 코딩  (0) 2021.12.16
[1028web annotation] 어노테이션  (0) 2021.08.29
728x90

VTL (Velocity Template Language)

VTL Velocity에서 템플릿 개발에 사용되는 언어로 레퍼런스(Reference), 디렉티브(Directive), 그리고 주석(Comment)으로 구성된다.

레퍼런스 ${variable} 컨텍스트에서 제공되는 변수에 대한 레퍼런스
${variable.property} 속성에 대한 레퍼런스
${variable.method(args)} 메소드 대한 레퍼런스
디렉티브 #set 레퍼런스의 값을 설정
#if #elseif #else 조건문 제어
#foreach 반복문 제어
#include 파싱되지 않는 로컬 파일 출력
#parse 파싱되는 로컬 템플릿 출력
#stop 템플릿 엔진의 동작 정지
#macro 반복적으로 사용될 매크로 정의
주석 ##  줄짜리 주석
#* .... *# 여러 줄에 걸친 주석



출처: https://androphil.tistory.com/525 [소림사의 홍반장!]

'JAVA' 카테고리의 다른 글

[1028web JSTL ]커스텀 라이브러리  (0) 2022.03.19
VelocityEngine  (0) 2022.02.19
Java 프로그래밍 언어의 코드 규칙, java 표준 코딩  (0) 2021.12.16
[1028web annotation] 어노테이션  (0) 2021.08.29
728x90

출처 : https://www.oracle.com/java/technologies/javase/codeconventions-namingconventions.html

2. 파일 이름 확장자  .java : 자바소스, .class : 클래스 소스 
일반적사용 파일이름 GNUmakefile , README
3. 파일구성 파일 구성 0. 2000줄 보다 긴 파일은 피할것.  Java Source File Example 참고. 
1. 각 Java 소스 파일에는 단일 공용 클래스, 인터페이스 포함,  공개 클래스는 파일의 첫 번째 클래스 또는 인터페이스. 
Java 소스 파일 의 순서. 
- 주석시작(Beginning Comments)
- 패키지 및 가져오기 문(Package and Import statements)
- 클래스 및 인터페이스 선언(Class and Interface Declaration)
1. 주석시작
: Beginning Comments
모든 소스파일은 c-style 주석으로 시작하고, 클래스이름, 버전, 날짜, copyright 작성
/*
* Classname
* Version information
* Date
* Copyright notice
*/
주석  출처 : https://en.cppreference.com/w/c/comment

C-style      : /* C-style*/
C++-style :  // C++-style
2. package, import 주석이 없는 첫번째 라인
package java.aws;
import java.awt.peer.CanvasPeer;
3. Class, Interface 선언 1. doc 작성은 /**  */
2. class or interface  문구작성
3. class or interface  구현 주석은 /* */
4. class (static) 변수 작성   : 작성순서 : public > protected >(default) > private
5. 인스턴스변수( Instance variables) :
                                     작성순서 :  public > protected >(default) > private
6. 생성자
7. 메소드 : 범위 접근성이 아닌, 기능별 그룹화(개인클래스 매서드는 두개의 공용 인스턴스 메서드 사이에 있을수 있음)
8. 
4. 들여쓰기(Indentation)   4개의 공백을 들여쓰기 단위로 사용, 정확한 구성(space vs tabs)은 지정되지 않음, 탭은 8칸마다 설정
1. 라인 길이  터미널에서 80자 보다 긴 줄은 잘 처리 되지않음으로 피하세요.
document 사용시 70자를 넘기지 않게 작성
2. 줄바꿈 표현식이 한 줄에 맞지 않으면 다음 일반원칙을 따름. 
1. 쉼표(,) 뒤에 엔터
      ~~~(String a,
             String b)
2. 높은레벨과 낮은 레벨에서 줄바꿈이 필요하면 높은레벨에서 줄바꿈
var = method1( a ,
                    method2(c,
                                d));
3. 연산자(operator) 앞에서 줄바꿈
4. 같은 레벨의 새로운 시작은 이전줄의 같은 레벨에서 줄바꿈
      sum = a +~~~ + q
               +r+~ ;
      sum = a +~~~ + q
                        +r+~ ;     // 피할 것.         
5. 위의 규칙으로 코드가 혼란스럽거나 오른쪽 여백에 대해 눌러진 코드가 발생하면 대신 8칸 들여쓰기 하세요.  
public static synchronized longNameMehhodNameLongLong(int a,
         int bLongNamelonglonglonglong, int cLongNamelonglonglonglong,
         int d)
6. 8 칸 들여쓰기 규칙이 보통쓰이지만 내용을 인식하기 어려운경우 4칸을  더 들여쓰세요. 
if ( ( alongLongLongLong  && blongLongLongLong)
           || ( clongLongLongLong  && dlongLongLongLong)
           || ( elongLongLongLong  && flongLongLongLong)
   ) {
      contentDo();
}

if ( ( alongLongLongLong  && blongLongLongLong) || ( clongLongLongLong  && dlongLongLongLong)
           || ( elongLongLongLong  && flongLongLongLong)
   ) {
      contentDo();
}

// 아래 피할것. 
if ( ( alongLongLongLong  && blongLongLongLong)
       || ( clongLongLongLong  && dlongLongLongLong)
       || ( elongLongLongLong  && flongLongLongLong)
   ) {
      contentDo();
}

7. 3항연산자(ternary expressions) 정렬
a = (aLongLongLong) ? b : c;
a = (aLongLongLong) ? b
                             : c;
a = (aLongLongLong)
      ? b
      : c;
 
5. 주석(Comments)   /*...*/ 
: 구현주석(implementation comments)
: C++ 에서 볼수있는주석. 
: 코드 주석처리, 특정 구현에 대한 주석을 작성하기 위함
/**...*/
: 문서주석(documentation comments)
:  java 전용, javadoc 도구를 사용하여 HTML 파일로 추출가능

1. 주석은 코드의 개요를 제공하고, 코드 자체에서 쉽게 사용할 수 없는 추가 정보를 제공하는데 사용해야 합니다. 
2. 설명에는 프로그램을 읽고 이해하는 데 관련된 정보만 포함되야 합니다. 
(해당 패키지가 어떻게 빌드되었는지, 어떤디렉토리에 있는지에 대한 정보 주석포함 안됨. )
3. 애매한코드(nontrivial or nonobvious) 에대한 주석은 적절하지만, 명확한 코드에는 작성하지 않습니다. ( 중복된 내용 발생)
4. 주석을 추가해야 하는경우 코드를 다시 작성해서 명확하게 하는것이 좋습니다. 
5. 주석에 특수문자 백스페이스, 들여쓰기 줄바꿈(form-feed) 사용하지 말것 ex)\f, \b
6. 주석을 별표나 문자로 되어 있는 넓은 범위에 코드에 사용하지 말것
(해석 불분명 : Comments should not be enclosed in large boxes drawn with asterisks or other characters.)
Carriage return
Line feed
Form feed

 출처 : https://stackoverflow.com/questions/3091524/what-are-carriage-return-linefeed-and-form-feed
https://ko.wikipedia.org/wiki/%EC%BA%90%EB%A6%AC%EC%A7%80_%EB%A6%AC%ED%84%B4

carriage return (= Return= CR = 0x0D) : 커서를 현재 줄의 맨 처음으로 보냄
$) note\rbook
note
book


Line feed (= New line = LF = 0x0A): 줄을 옮김  
$) note\nbook
note
book

Form feed (= FF = 0x0C) : 들여쓰기 줄바꿈
$) note\fbook
note
      book
https://itng.tistory.com/25

스페이스바 띄워쓰기 

백스페이스 바 
1. 구현 주석 형식 블록(block)
한줄(single-line)
후행(trailing)
줄끝(end-of-line)
1.1. 블록주석 파일, 메서드, 데이터 구조 및 알고리즘에 대한 설명제공
함수, 메서드 내부 블록 주석은 설명하는 코드와 동일한 수준 들여쓰기 사용
블록 주석은 코드의 나머지 부분과 구분하기 위해 공백 행이 앞에와야함
/*
 * block comment
 */
들여쓰기(indent) indent (-)가 형식을 재구성 할수없는 블록 주석으로 인식하게 한다. 
/*-
 * block comment
 */
1.2 한줄주석 한줄 주석은 다음 라인에 오는 소스만큼 들여쓰기 작성
만약 주석을 한줄로 쓸수없다면 블록주석포멧으로 작성.
한줄 주석 앞에는 공백이 있어야 합니다. 
    /* 주석 */
    public ....
1.3 후행(Trailing) 주석 매우 짧은주석으로, 코드와 분리 되어 있을수 있도록 멀리이동
둘이상 짧은 주석이 있으면 도일한 탭으로 들여쓰기 

if (a==1){
    return true;         /* 주석1*/
} else {
    return false;        /* 주석2*/
}
1.4 줄끝(End-of-line)주석 "//" 구분자 는 전체행, 또는 일부행만 주석처리 가능
연속된 여러줄에 사용하면안됩니다. 
그러나 코드를 주석처리할때는 사용할수있습니다. 

한줄주석처럼, 후행주석처럼, 코드만 연속된줄에 사용가능. 


2. 문서 주석 https://www.oracle.com/technical-resources/articles/java/javadoc-tool.html 이위치에 더자세한 설명
java class, interfaces, constructors, method, field 에 사용

/**...*/  인터페이스, 클래스, 멤버당 하나의 주석 존재, 선언직전 사용. 

/**
 * 문서주석
 */
public class Example {

- 클래스, 인터페이스
최상위 클래스와 인터페이스는 들여쓰기가 되어 있지 않지만, 그 구성원은 들여쓰기. 
첫번째 줄은 들여쓰지 않고 후행 1칸씩 들여쓰기. (별표 세로정렬위해)

- 생성자를 포함한 구성원. 
첫번째 문서 줄에 4개의 공백, 그후 5개의 공백

문서화에 적합하지 않은 클래스, 인터페이스, 변수 또는 메서드에 대한 정보를 제공해야 하는 경우 바로 뒤에 구현블록 주석 혹은 한줄블록 주석
예를들어 클래스 구현에 대한 세부정보는 클래스 문 다음의 구현블록 주석에 들어가야
Java 는 문서 주석을 주석 뒤의 첫 번째 선언과 연관시키기 때문에 문서 주석은 메소드 또는 생성자 정의 블록 내부에서 위치해서는 안됩니다. 
6 선언(Declarations) 1. 줄당 숫자 줄당 하나의 선언을 추천합니다.  
주석을 권장 하기위해 
int aLevel; // 주석1
int bLevel; // 주석2

int aLevel, bLevel;  이것보다 줄당 하나의 선언 추천.  같은타입만 사용. 
  2. 초기화 선언된 지역 변수를 초기화할것.
초기화 하지 않는 유일한 이유는 초기 값이 먼저 발생하는 계산에 의존하는경우
  3. 위치(Placement)  
     

Conventions 규약

'JAVA' 카테고리의 다른 글

[1028web JSTL ]커스텀 라이브러리  (0) 2022.03.19
VelocityEngine  (0) 2022.02.19
Java 프로그래밍 언어의 코드 규칙, java 표준 코딩  (0) 2021.12.16
[1028web annotation] 어노테이션  (0) 2021.08.29
728x90
어노테이션 영어사전: 주석, extra information

1. built-in 어노테이션 : Java 코드에 적용되는 어노테이션 
   ex) @Overried, @Deprecated, @SuppressWarnings, @SafeVarargs, @FunctionalInterface
2. Meta 어노테이션 : 다른 어노테이션에 적용되기 위한 어노테이션(custom-annotation 생성 시)
   ex) @Retention, @Documented, @Target...
meta-annotaiton custom-annotation(커스텀 어노테이션) 생성할 때 주로 사용. 
cf) Meta-Data :  데이터에 대한 데이터
@SpringBootApplication @Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
@Target Java compiler 가 annotation이 어디에 적용될지 결정하기 위해 사용. 

ElementType.PACKAGE : 패키지 선언
ElementType.TYPE : 타입 선언
ElementType.ANNOTATION_TYPE : 어노테이션 타입 선언
ElementType.CONSTRUCTOR : 생성자 선언
ElementType.FIELD : 멤버 변수 선언
ElementType.LOCAL_VARIABLE : 지역 변수 선언
ElementType.METHOD : 메서드 선언
ElementType.PARAMETER : 전달인자 선언
ElementType.TYPE_PARAMETER : 전달인자 타입 선언
ElementType.TYPE_USE : 타입 선언
출처 : https://sanghye.tistory.com/39
@Retention Annotation 이 실제로 적용되고 유지되는 범위

RetentionPolicy.SOURCE  소스코드(.java)까지
RetentionPolicy.CLASS     클래스파일(.java) 까지
RetentionPolicy.RUNTIME 런타임 까지

https://jeong-pro.tistory.com/234
@Documented 해당 어노테이션을 javadoc에 포함시킴
@Inherited 어노테이션의 상속 허용 
@Repeatable java8부터 연속적으로 어노테이션 선언가능
   
   

'JAVA' 카테고리의 다른 글

[1028web JSTL ]커스텀 라이브러리  (0) 2022.03.19
VelocityEngine  (0) 2022.02.19
Java 프로그래밍 언어의 코드 규칙, java 표준 코딩  (0) 2021.12.16
[1028web annotation] 어노테이션  (0) 2021.08.29
728x90

이글은 백기선님 스터디 할래? 스터디를 뒤늦게 따라간 기록입니다.

매년 혼자 자바 책한권씩 정리했었는데, 이 스터디 따라가는게 훨~~~씬 좋았습니다. 

어떻게 공부할지에 대한것을 많이 배웠습니다. 

누군가에게 도움이 되길 바라며 남김니다.  

 

유튜브 구독하시면 이전 스터디 수강가능합니다. 

백기선님 유튜브 >>https://www.youtube.com/user/whiteship2000

스터디할래 유튜브 >>https://youtu.be/peEXNN-oob4

스터디할래 링크 >> https://github.com/whiteship/live-study

 

[스터디할래? Java 01] JVM 이란 무엇인가?

[스터디할래? Java 02] 자바 데이터 타입, 변수 그리고 배열

[스터디할래? Java 03] 연산자 Operator

[스터디할래? Java 04] 제어문

[스터디할래? Java 05] 클래스_ BinrayTree_DFS,BFS

[스터디할래? Java 06]상속

[스터디할래? Java 07]패키지

[스터디할래? Java 08]인터페이스

[스터디할래? Java 09]예외처리

[스터디할래? Java 10]멀티쓰레드 프로그래밍

[스터디할래? Java 11]enum

[스터디할래? Java 12]애노테이션

[스터디할래? Java 13]I/O

[스터디할래? Java 14]제네릭

[스터디할래? Java 15]lamda

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

'JAVA > Basic' 카테고리의 다른 글

[스터디할래? Java] 목차  (0) 2021.05.17
[스터디할래? Java 15]lambda 람다  (0) 2021.05.15
[스터디할래? Java 14]제네릭  (0) 2021.05.15
[스터디할래? Java 13]I/O  (0) 2021.05.15
[스터디할래? Java 12]애노테이션  (0) 2021.05.15
[스터디할래? Java 11]enum  (0) 2021.05.15
728x90

[스터디할래? Java] 목차

이글은 백기선님 스터디 할래? 스터디를 뒤늦게 따라간 기록입니다.

스터디할래 링크 >> https://github.com/whiteship/live-study

이필기를 시작으로 공부했습니다 >>https://xxxelppa.tistory.com/207https://tourspace.tistory.com/6

여기 없는내용은 스터디 할래 강의 내용 혹은 제가 java Doc보고작성하거나 예제를 만들어 추가했습니다.

그외는 같이 출처가 써있습니다. 

람다식 lambda expression : 식별자 없이 실행 가능한 함수표현식
익명클래스를 함수표현식으로 처리할수 있음. 

식별자: 코드에 존재하는 변수, 자료형, 서브루틴 등을 가리키는 토큰이다.

+ java8 부터 람다식 가능하게한것은 함수형프로그램이 가능하게 하기위해. 
함수 자체가 first-class-function : 변수할당, 매개변수 전달, 리턴 전달 가능해짐. 
컬렉션 잘쓰려고 스트림 지원, 그를위해 함수형 프로그래밍 지원, 그를위해 람다 지원. 

+ 익명내부클래스는 XXXXXX$1.class 로 컴파일 됨. 
        람다는 invoke dynamic(jdk1.7, 인디) 이라는 opcode 사용. 바이트트 코드 확인가능
                 이런이유로 버전올라갈때 개선의 여지가 있다고함. 

invoke dynamic : (jdk1.7, 인디) 동적타입언어. 바이트 코드 셋.
-기존 4가지 invokevirtual(instance메소드 디스패치), invokestatic, invokeinterface, invokespecial
-메소드이름, 메소드시그니처, 메소드 정의 클래스, 메소드 실행 바이트 코드 가 명확히선언필요...
invoke dynamic  : https://tourspace.tistory.com/12

+ 람다를 지연연산으로 활용할수 있다.  
Variable Capture 변수 캡쳐

람다 외부 정의된 변수 : 자유변수 :Free Valiable
자유변수를 참조 : 람다 캡쳐링 :Lambda Capthuring
람다에서 지역변수 참조시 : 1. final, 2. final처럼 동작  ==> 재할당 안되야. 
원인 : 지역변수 스택생성 쓰레드끼리 공유 안된다. 인스턴스변수 힙영역생성, 쓰레드 공유가능. 
람다는 변수도 자신의 스택에 저장해서 쓰는데 변하면안된다는 제약조건 필요한이유. 
https://perfectacle.github.io/2019/06/30/java-8-lambda-capturing/

+ VariableCapture 클래스. 
run 메서드  안에 익명클래스는다른영역
                  -->(익명내부클래스 쉐도잉 = 새로운 scop 를 가짐, 동일변수선언가능). 
run 메서드 안에 람다는 같은 scope 같은 이름 변수 정의 불가. 
메소드 생성자 레퍼런스 :: "
1. static 메소드참조
클래스이름::메소드이름  System.out::println
2. 인스턴스메소드참조  
3. 람다식 매개변수로 접근가능 메소드참조
BiFunction<string,string,boolean> stringContain = String::contains;
System.out.println(stringContain.apply("apple","a"));
4. 생성자 참조
클래스이름 :: new
Supplier<Random> random = Random::new;
System.out.println(random.get().nextInt(10)+1);
타입추론 Predicate<String> isEmpty = s-> s==null || s.length()<0;
함수형 인터페이스
함수형 인터페이스
@FunctionalInterface
추상메서드가 하나뿐인인터페이스
Consumer,Runnable, Predicate,  supplier, functon.....
Runnable         Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println("Run");
            }
        };

        Runnable lambdaRun = ()->{System.out.println("run");};
        new Thread(lambdaRun).start();
predicate<T> boolean test(T t);
        List<Integer> numbers = new ArrayList();
        numbers.add(3); numbers.add(1); numbers.add(0); numbers.add(2);
        Predicate<Integer> moreThen3 = (num) -> num >= 3;
        System.out.println(moreThen3.test(4));
        numbers.removeIf(moreThen3);
        String num = numbers.stream().map(Object::toString).collect(Collectors.joining(","));
        System.out.println(num);
https://zetcode.com/java/predicate/


List<VerseModel> verses =  chapter.getBibleVerse().stream().filter(verse -> verse.getBiblePublish().getPublishSn() ==publishesSn.get(0)).collect(Collectors.toList());





Consumer<T>



https://zetcode.com/java/consumer/
void accept(T t);
        List<Integer> numbers = new ArrayList();
        numbers.add(3); numbers.add(1); numbers.add(0); numbers.add(2);
Consumer<List> toStringList = (list) -> {
   System.out.println(list.stream().map(Object::toString).collect(Collectors.joining(",")));;
};
toStringList.accept(numbers);
ArrayList.forEach(Consumer<? super E> action)
        List<Integer> numbers = new ArrayList();
        numbers.add(3); numbers.add(1); numbers.add(0); numbers.add(2);
        numbers.forEach((num)->{System.out.println(String.valueOf(num));});
Consumer.andThen(Consumer<? super T> after)
        Consumer<List<String>> addRoom = (list) -> {
            for (int i = 0; i < list.size(); i++) {
                list.set(i,list.get(i).concat(" Room"));
            }
        };
        Consumer<List> toStringList = (list) -> {
            System.out.println(list.stream().map(Object::toString).collect(Collectors.joining(",")));;
        };
        List<String> strNum = new ArrayList<>();
        strNum.add("a"); strNum.add("B"); strNum.add("C"); strNum.add("d");
        addRoom.andThen(toStringList).accept(strNum);
Consumer<T>, BiConsumer<T,U>, DoubleConsumer, IntConsumer, LongConsumer, ObjDoubleConsumer, ObjIntConsumer, ObjLongConsumer
Supplier<T>




T get();
Supplier random10Supplier = ()-> new Random().nextInt(10)+1;

Stream.generate(random10Supplier).limit(5).forEach(System.out::println);
System.out.println(random10Supplier.get());
https://java2blog.com/java-8-supplier-example/#Java_8_Supplier_example
Supplier<T>, BooleanSupplier, DoubleSupplier, IntSupplier LongSupplier
Function<T,R> R apply(T t);
        Function<Integer,Integer> plus4 = (num)-> num + 4;
        System.out.println(plus4.apply(5));
Function<T,R>, BiFunction<T,U,R>, DoubleFunction<R>, IntFunction<R>, IntToDoubleFunction....

List<Integer> publishSnList = publishModelList.stream().map(TheBiblePublishModel::getPublishSn).collect(Collectors.toList())

List<String> verseList = verses.stream().map(verse -> verse.getVerse()).collect(Collectors.toList());
UnaryOperator<T> T apply(T t);
- Function<T,R> 같은타입일때. 
        UnaryOperator<Integer> UnaryPlus4 = (num)-> num + 4;
        System.out.println(UnaryPlus4.apply(5));
BinaryOperator - BiFunction<T,U,R>, UnaryOperator<T>, DoubleBinaryOperator.....
stream from https://futurecreator.github.io/2018/08/26/java-8-streams/
stream jdk8 람다 활용가능기술
1. 생성 :스트림인스턴스생성
2. 가공 : 필터링, 맵핑, 등 중간작업
3. 결과 
stream 생성 1. 배열 스트림
2. 컬렉션스트림
3. 비어있는스트림 Stream.empty()
4. 빌더스트림
Stream<String> builderStream 
= Stream.<String>builder().add("A").add("B").add("C").build();
5. Stream.generate()
Stream<String> genStream
                = Stream.generate(()->"gen").limit(3);
System.out.println(genStream.map(String::toString).collect(Collectors.joining()));//gengengen
6. Stream.iterate()
Stream<Integer> iterStream
       = Stream.iterate(1,n->n+1).limit(3);
System.out.println(iterStream.map(num-> String.valueOf(num)).collect(Collectors.joining()));//123
7.기본타입, 문자형 스트림. 파일, 병렬
IntStream, LongStream, DoubleStream, .paralleStream()
stream 가공 1. 연결
Stream.concat(stream1,stream2);
2. Filtering -> Stream<T> filter(Predicate<? super T> predicate)
Stream<String> stream = name.stream().filter(name-> name.contain("a"));
3. Mapping -> <R> Stream<R> map(Function<? super T, ? extends R> mapper);
4. flatMap -> <R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);
List<String> flatList = list.stream() .flatMap(Collection::stream) .collect(Collectors.toList()); // [a, b]
4. sorting()
sorted(Comparator.comparingInt(String::length))
5. peek : 그냥 확인해본다. 
stream 결과 1. 연산
스트림.count(), 스트림.sum(), 스트림.min();, 스트림.max()
2. reduce
        OptionalInt reduced =
                IntStream.range(1, 4) // [1, 2, 3]
                        .reduce((a, b) -> {
                            return Integer.sum(a, b);
                        });
        System.out.println(reduced.getAsInt());
3. Collecting  >> .collect(XXXXXX)
- Collectors.toList() 리스트 반환
-Collectors.joining(", ", "<", ">");
- Collectors.averageIngInt(Product::getAmount);  평균
- Collectors.summingInt() 합
- Collectors.summarizingInt(); 합, 평균
- Collectors.groupingBy()  그룹
- Collectors.partitioningBy() Predicate 함수.
- Collectors.of()  직접 Collector 만듬
3. Matching
.anyMatch(name -> name.contains("a"));
4. foreach : 최종과정의 peek
names.stream().forEach(System.out::println);


Map<Integer, String> map = list.stream().collect( Collectors.toMap(Item::getId, Item::getValue));
Map<Integer, Boolean> isUsedPublish = publishesSn.stream().collect(Collectors.toMap(Function.identity(), e -> true));

** random.nextInt(max - min + 1) + min

추천책 : 시작의 기술 ,

못하는건가... 안하는건가.....

 


+ 리플렉션. : 가장 빨리 getter를 읽는 방법은? 
https://dzone.com/articles/java-reflection-but-faster

  • Java Reflection is slow.
  • Java MethodHandles are slow too.   // MethodHandlers.lookup() jdk7   리플렉션과 별차이없음...
  • Generated code with javax.tools.JavaCompiler is fast.    //JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
  • LambdaMetafactory is pretty fast.      //MethodHandles.Lookup lookup = MethodHandles.lookup();
            CallSite site = LambdaMetafactory.metafactory(lookup,

제니퍼.

 

So, the devil is in the details. Let’s go through the implementations to confirm that I applied typical magical tricks, such as

So, the devil is in the details.  >>> (A를 B로 합시다)... 구현하면 일이 많아진다. 

 

 


String[] names = {"Z","B","C"};
Arrays.sort(names,String::compareToIgnoreCase);   //(this, o2) -> this.compareTo(o2)
Arrays.stream(names).forEach(System.out::print);

 

 

 

 

 

 

  • 람다식 사용법
  • 함수형 인터페이스
  • Variable Capture
  • 메소드, 생성자 레퍼런스

'JAVA > Basic' 카테고리의 다른 글

[스터디할래? Java] 목차  (0) 2021.05.17
[스터디할래? Java 15]lambda 람다  (0) 2021.05.15
[스터디할래? Java 14]제네릭  (0) 2021.05.15
[스터디할래? Java 13]I/O  (0) 2021.05.15
[스터디할래? Java 12]애노테이션  (0) 2021.05.15
[스터디할래? Java 11]enum  (0) 2021.05.15
728x90

[스터디할래? Java] 목차

이글은 백기선님 스터디 할래? 스터디를 뒤늦게 따라간 기록입니다.

스터디할래 링크 >> https://github.com/whiteship/live-study

이필기를 시작으로 공부했습니다 >>https://sujl95.tistory.com/73 ,  https://docs.oracle.com/javase/tutorial/java/generics/types.html

여기 없는내용은 스터디 할래 강의 내용 혹은 제가 java Doc보고작성하거나 예제를 만들어 추가했습니다.

그외는 같이 출처가 써있습니다. 

제네릭 data type을 클래스, 메소드에서 내부 데이터 타입을 제네릭으로 지정,
"컴파일과정에서 문제제거"
- jdk1.5 부터 도입 
- jdk 1.7 Diamond  <>: 타입안에 안써도됨, 타입추론
- 클래스나 메소드 내부에서 사용되는 객체의 타입을 컴파일과정에서 문제제거
- 반환값에 대한 타입변환 및 타입 검사에 들어가는 노력줄인다. 
- 타입국한 효과로 타입변환이 불필요해져 성능향상효과

A generic type is a generic class or interface that is parameterized over types. 
제네릭 타입은 타입에서 매개변수로 사용되는 클래스나 인터페이스
https://docs.oracle.com/javase/tutorial/java/generics/types.html 
제네릭 컴파일 ----- .java
        List<Integer> numbers = new ArrayList<>();
        numbers.add(3);
------.class
        List<Integer> numbers = new ArrayList();
        numbers.add(3);
컴파일할때 소거자에 대해 타입정보가 사라지는것 > 구체화타입ex) List
제네릭 사용법
제네릭 메소드 만들기
interface fruit<K,V>{                                           //클래스 
    public default K getKey() {return null;}
    public default V getValue() {return null;}
}
class Banana<K,V> implements fruit<K,V>{                // 상속시 

    public <T> boolean isBTime(List<T> list, T addvlaue) {  //메서드
        T value = list.get(0);
        V[] vArray =(V[]) new Object[2];                        // 배열 선언 
        if (value == addvlaue) return true;
        return false;
    }
}
와일드 카드 wild card 
-Unbounded WildCard
: List<?> :모든클래스
-Upper Bounded wildcard
: List<? extends Number>:특정타입자식클래스
-Lower Bounded Wildcard
: List<? super Number>: 특정타입 부모클래스


아무이름 컴파일은 문제없음 클래스, 메소드매개변수,반환값 가능

매개변수 명명 규약
E - Element (used extensively by the Java Collections Framework)
K - Key
N - Number
T - Type
V - Value
S,U,V etc. - 2nd, 3rd, 4th types
Erasure
Generics Type Erasure
List<Object> list = new ArrayList<Integer>();  >> 컴파일에러. 

메서드 수준

제네릭 특이점 - 원시타입 사용불가.
타입 파라메터 자리에 원시타입 사용안함>> 타입소거(Erasure)발생때문.. 명시안되면 Object로
>> Object클래스를 상속받으면서 하위호환성이지켜진다. >> Wrapper 클래스 사용. 

- 배열선언은 캐스팅이용
  V[] vArray =(V[]) new Object[2];            
new 연산자 동적메모리 할당영역 heap 영역에 생성한 객체 할당.
제네릭은 컴파일타임동작. Object 생성후 캐스팅하여 사용. 

- static 으로 사용불가. 
static 내부에선 제네릭사용가능
https://blog.naver.com/hsm622/222251602836
브리지 메서드 매개변수가 반환타입소거시 가끔 브리지메서드를 생성하는데 stackTrace에 가끔 나타나니 알아두기
public class A extends ArrayList<String>{
    public boolean add(String e){
        return super.add(e)
    }
}
A a = new A();
a.add("text"); 
https://rockintuna.tistory.com/102

Erasure 이레이저 삭제 말소

Conventions 규약

Unbounded  무한한

추천책 : 클라우드 네이티브 자바

 

 

리플렉션으로 볼수 있음.

 

 

  • 제네릭 사용법
  • 제네릭 주요 개념 (바운디드 타입, 와일드 카드)
  • 제네릭 메소드 만들기
  • Erasure

'JAVA > Basic' 카테고리의 다른 글

[스터디할래? Java] 목차  (0) 2021.05.17
[스터디할래? Java 15]lambda 람다  (0) 2021.05.15
[스터디할래? Java 14]제네릭  (0) 2021.05.15
[스터디할래? Java 13]I/O  (0) 2021.05.15
[스터디할래? Java 12]애노테이션  (0) 2021.05.15
[스터디할래? Java 11]enum  (0) 2021.05.15
728x90

[스터디할래? Java] 목차

이글은 백기선님 스터디 할래? 스터디를 뒤늦게 따라간 기록입니다. 

스터디할래 링크 >> https://github.com/whiteship/live-study

이필기를 시작으로 공부했습니다 >> https://www.notion.so/I-O-af9b3036338c43a8bf9fa6a521cda242

여기 없는내용은 스터디 할래 강의 내용 혹은 제가 java Doc보고작성하거나 예제를 만들어 추가했습니다.

그외는 같이 출처가 써있습니다. 

I/O Input & Ouput 입출력
java.io  // 데코레이션 패턴으로 만들어짐 : 
컴퓨터 내부 또는 외부장치와 프로그램간 데이터 주고받기. 
ex) 키보드 데이터 입력, System.out.println()
데코레이션패턴 객체의 타입, 메소드 그대로 유지하면서 새로운 책임을 추가할때 사용. 
탈부착가능한 책임. 
하기 코드 참고.
ex)
BufferedInputStream 담아 보내면 모아서 보내서 시스템 콜 횟수가 줄어서 성능이익
Stream 스트림이란 데이터를 운반하는데 사용되는 연결 통로. 
단방향 통신만 가능. 
먼저 보낸데이터 먼저, 중간에 건넘뜀없이 연속적
바이트 단위로 데이터 전송
AutoCloseable(1.7) <-Closeable(1.5) <- InputStream (1.0) <- FileInputStream (1.0)
                                               <- OutputStream (1.0) <- FileOutputStream (1.0)
InputStream/OutputStream 상속받은 클래스 종류

- FileInputStream / FileOutputStream : 파일
- ByteArrayInputStream / ByteArrayOutputStream
                                              : 메모리(Byte배열) > 메모리만써서 close필요없음
- PipedInputStream / PipedOutputStream : 프로세스간 통신
- AudioInputStream / AudioOutputStream :오디오 장치 

소스작성 흐름
1. FileInputStream : HDD에 존재하는 파일과 연결
2. InputStreamReader : 8bit Stream 16bit stream 연결, char변경(encoding)
3. BufferedReader : 스트림으로 연결된곳에서 줄단위로 읽음. readLine()
InputStream  InputStream 의 추상메서드 read()  --> reader

public abstract class InputStream implements Closeable {
    public abstract int read()  
* byte단위 전송, int값을 가져옴- 4byte중 1byte 이용 범위가 0~255 와 -1 이기때문.

    public int read(byte b[]) 
    public int read(byte b[], int off, int len) 
    public long skip(long n)               // 주어진길이만큼 건너뜀
    public int available()                    //스트림으로부터읽을수 있는 데이터 크기 반환
    public void close()                       // 닫고 사용하던자원반환
    public synchronized void mark(int readlimit) //현재 위치 표시. reset에의해 다시돌아감
    public synchronized void reset()     //스트림위치를 마지막 mark호출된위치 되돌림
    public boolean markSupported()    // mark reset 기능 제공하는지 확인

OutputStream  OutSteream 의 추상메서드 write()  --> writer

public abstract class OutputStream implements Closeable, Flushable {
    
    public abstract void write(int b)  주어진값출력소스에 쓴다. 
    public void write(byte b[])
    public void write(byte b[], int off, int len)
    public void flush()  : 스트림의 버퍼에 있는 모든 내용을 출력소스에 쓴다. 
    public void close()  : 입력소스 닫음으로써 사용하던 자원반납

}
보조 스트림 보조 스트림 : 기능향상, 새로운기능 추가.
각각 inputStream, OutputStream 상속
- FilterInputStream / FilterInputStream 
- BufferedInputStream / BufferedOutputStream
- DataInputStream/DataOutputStream
- SequenceInputStream /없음
- LineNumberInputStream/없음
- PushbackInputStream/없음
- 없음/PrintStream
표준입출력 콘솔을 통한 데이터 입력, 출력
System.in   : inputStream
System.out : PrintStream
System.err : printStream
FileReader /FileWriter FileReader(1.1) -> InputStreamReader(1.1)->Reader(1.1)--> Readable(1.5), Closerble(1.5)
Reader : 문자기반 스트림. byte배열대신 char 배열사용. 자동인코딩
4byte 중 2byte 사용해서 문자단위전송. 

FileReader fileReader = new FileReader("파일이름경로");
fileReader.read() ;
fileReader.close();
Byte스트림 vs Character스트림 Byte 스트림 : 8bit :한번에 전달하는양 작지만 속도빠름
InputStream - FileInputStream, ObjectInputStream, DataInpuStream
Char스트림: 16bit : 한번에 전달하는양 많지만 속도 느림. 
Reader : FileReader , InputStreamReader, BufferedReader
PipeReader /pipeWriter 입출력스트림을하나의 스트림으로 연결
직렬화 Serializable , 파일 읽을때쓸때, 웹에서 데이터 보내고 받을때 줄로보냄. 그때 사용. 
transient - 직렬화 제외
serialVersionUID = 버전관리,  
NIO New Input / Output 새로운 입출력(jdk1.4)
java.nio.channels : 파일채널, TCP, UDT 채널
java.nio.channels.spi java.nio.channels 위한 서비스 제공자. 
java.nio.charset 문자셋 인코더 디코더 API
java.nio.charset.spi
java.nio.file 파일 파일시스템 접근위한 서비스
java.nio.file.attribute 속성접근
java.nio.file.spi
java.nio.buffer
...
입출력방식은  IO는 스트림 NIO 는 채널방식  : 스트림은 매번 생성, 채널은 만들필요없음
버퍼 방식은   IO 넌버퍼,   NIO 는 버퍼 : IO는 넌버퍼라서 bufferedInputStream 연결사용
비동기방식   IO 지원안함 , NIO 지원   : 
프로킹/넌블로킹 IO 블로킹방식만 지원 : 동기, NIO 블로킹/넌블로킹 모두 지원
                                          블로킹(대기상태): IO는 인터럽트안되나 NIO는 가능    
                                          넌블로킹(쓰레드가 입출력시 블로킹안됨)
* NIO 전 FileReader 사용했음. FileWriter 사용 추천. 
Buffer 읽고 쓰기가 가능한 메모리 배열(일반)
데이터를 전송하는 상호간 장치에서 OS system core (저속)와 java api호출(고속) 장치간의 속도차이로 인해 저속 장치가 작업을 추리하는 동안 기다리는 현상 줄어짐
 buffer는 사이즈 지정이 가능, 효율관런 고려 가능

package java.nio;
public abstract class Buffer (1.4))
버퍼에 담았다 한번에 모아서 보냄. 입출력 횟수 줄어 성능이점
ByteBuffer, CharBuffer, DoubleBuffer, FloatBuffer, IntBuffer, LongBuffer, ShortBuffer
할당:
바이트버퍼.allocatedDirect(크기);
- 다이렉트    Direct      : 운영체제 관리 메모리공간 :생성시간 느림, 한번생성재사용, IMDG 참고
바이트버퍼.allocated(크기);
- 넌다이렉트 NonDirect : JVM 관리 힙 메모리 공간. :생성시간은빠름, 큰크기사용힘듬
https://docs.oracle.com/javase/7/docs/api/java/nio/Buffer.html
Channel 파일, 소켓, 데이터그램등과 같은 I/O소스로부터 데이터 블록을 버퍼로 쓰거나 읽음. 
- Socket과 연결, 입출력 역할 수행
- 입력과 출력을 동시 수행
- Selector와 연결, 하나Selector에 다수 채널 존재
- Blocking 스레드 깨우거나 다시 Blocking할수 있다. 
기존 IO 에서 쓰레드에 Reader, Writer만 존재해 Reader로 블로킹, Writer로 블로킹풀어줌
NIO 에서 Non-blocking방식, 쓰레드 -버퍼사이 터널을 만들어주는데 이것이 채널하는역할
package java.nio.channels;
public interface Channel extends Closeable {
https://adrian0220.tistory.com/150
selector java NIO에서 하나의 쓰레드에 여러개 연결이 있어
Selector를 이용해 어떤채널과 연결 선택, 
선택된 채널이 스레드와 버퍼 연결 진행하는게 NIO 매커니즘.  
NIO 파일 읽고 쓰기 package study;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class NIOReadeWrite {
    public static void main(String[] args) throws IOException {

        LocalDateTime localDateTime = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String contexts = localDateTime.format(formatter) +"  "+ "안녕하세요 \r\n";
        String path = "C:\\Users\\신미성\\Desktop\\test.txt";
        fileWrite(contexts, path);
        fileRead(path);
    }

    public static void fileWrite(String contents, String pathString) {
        Path path = Paths.get(pathString);
        try(FileChannel writeFileChannel
                    = FileChannel.open(path, StandardOpenOption.CREATE, StandardOpenOption.WRITE)){
            ByteBuffer byteBuffer =  Charset.defaultCharset().encode(contents);
            writeFileChannel.write(byteBuffer);
        }catch (IOException e){
            e.printStackTrace();
        }
    }

    private static void fileRead(String pathString) throws FileNotFoundException {
        Path path = Paths.get(pathString);
        if (!Files.exists(path))
            throw new FileNotFoundException("경로 없음");
        try(FileChannel readFileChannel = FileChannel.open(path, StandardOpenOption.READ)){
            ByteBuffer byteBuffer = ByteBuffer.allocate((int)Files.size(path));
            readFileChannel.read(byteBuffer);
            byteBuffer.flip();
            System.out.println(Charset.defaultCharset().decode(byteBuffer).toString());
        }catch (IOException e){
            e.printStackTrace();
        }
    }
}


참고는 했으나.. 파일생성은 없었음.  : https://multifrontgarden.tistory.com/194
StandardOpenOption APPEND
CREATE                 없으면생성
CREATE_NEW         파일생성 있으면 에러남
DELETE_ON_CLOSE
DSYNC
READ
SPARSE
SYNC
TRUNCATE_EXISTING
WRITE

https://docs.oracle.com/javase/7/docs/api/java/nio/file/StandardOpenOption.html
IMDG IMDG(In Memory Data Grid)는 메인 메모리에 데이터를 저장
자바가 쓸수있는것보다 더큰메모리 저장가능

component 부품

decorate 꾸미다. 

책추천 : 유닉스의탄생

개발자취업  https://codesquad.kr/page/masters/curriculum.html

 

데코레이션패턴

package study;

public class CoffeDeco {
    public static void main(String[] args) {
        Latte latte = new Latte();
        System.out.println(latte);
    }
}

//component
abstract class Beans{
    protected String name="원두";
    public abstract double cost();
    public String getName() {return name; }
    public String toString(){return getName() +" : " +cost(); }
}
//deco
abstract class AddMilk extends Beans{
    public abstract String addMilk();
}
class Espresso extends Beans{
    Espresso(){name = "에스프레소"; }
    @Override
    public double cost() { return 1000;}
}
class Latte extends AddMilk{
    Latte(){name = "라떼"; }
    @Override
    public double cost() {return 3000;}
    @Override
    public String addMilk() {return "HALF"; }
    @Override
    public String toString() {
        return super.toString()+"(Milk:"+addMilk()+")";
    }
}

//참고사이트 : https://johngrib.github.io/wiki/decorator-pattern/
  • 스트림 (Stream) / 버퍼 (Buffer) / 채널 (Channel) 기반의 I/O
  • InputStream과 OutputStream
  • Byte와 Character 스트림
  • 표준 스트림 (System.in, System.out, System.err)
  • 파일 읽고 쓰기
728x90

[스터디할래? Java] 목차

이글은 백기선님 스터디 할래? 스터디를 뒤늦게 따라간 기록입니다.

스터디할래 링크 >> https://github.com/whiteship/live-study

이필기를 시작으로 공부했습니다 >> https://b-programmer.tistory.com/264 ,

                                                https://gowoonsori.site/java/annotation/

여기 없는내용은 스터디 할래 강의 내용 혹은 제가 java Doc보고작성하거나 예제를 만들어 추가했습니다.

그외는 같이 출처가 써있습니다. 

어노테이션 정의방법 @Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, MODULE, PARAMETER, TYPE})
public @interface Deprecated {

java.lang.Annotation 구현 from Bytecode
장점 : 유효성검사등 명시 , AOP 을 쉽게 구성할 수 있게해준다. 
용도 : 문서화, 컴파일러 체크, 코드 분석 자동생성, 런타임 프로세싱
완전히 정적이어야 한다. final. 
빌트인 어노테이션 Java에 내장되어 있는 어노테이션, 컴파일러를 위한 어노테이션
@Override
@Deprecated
@SuppressWarning
개발자가 의도를 가지고 만들었는데 컴파일이 알지못하고 경고를 띄울수있어 제거하는목적
@SafeVarargs
jdk7 제네릭 같은 가변인자 매개변수 사용시 경고 무시
@FunctionalInterface
메타 어노테이션 어노테이션 정의 하기 위해 사용
@Retention, @Target, @Documented, @Inherited, @Repeatable
@Retention 어노테이션 LIfe Time 적용범위
public enum RetentionPolicy {
    SOURCE,  // 소스파일에만 존재, 클래스파일존재 안함
    CLASS,    // 클래스파일에만 존재, 런타임유지 필요없음 
                // default : class
    RUNTIME // 클래스파일에도 존재하고 런타임에 VM에 의해 유지, ==> 리플렉션 정보읽기가능
}
// 정말 Runtime 설정이 필요한 정보인가? 
리플렉션
XXXController.class.getAnnotation();
XXXController.class.getDeclardAnnotations();//클래스에 정의되어 있는것만

@Target 어노테이션 적용대상
public enum ElementType {
    TYPE,   //Class, Interface, enum , recode(JDK14)
    FIELD,
    METHOD,
    PARAMETER,  // 매개변수
    CONSTRUCTOR,
    LOCAL_VARIABLE,
    ANNOTATION_TYPE,
    PACKAGE,
//1.8 이후 추가. 
    TYPE_PARAMETER,  //타입메개변수
//jdk 9이후
    TYPE_USE,
    MODULE,
//jdk 14
    RECORD_COMPONENT
}
@Documented 어노테이션 정보 javaDoc 작성된 문서에 포함. 생성된문서가 어노테이션인지 여부가 차이가남.
@Inherited 부모에 이설정이 있는 어노테이션이 있으면 
자식도 같이 씀.  (하기 예시참조)
@Repeatable 어노테이션을 반복적으로 선언할 수 있게 하는 어노테이션
애노테이션 프로세서 어노테이션을 프로세싱 하는기술.
컴파일타임에 어노테이션들을 프로세싱하는 javac에 속한 빌드 툴로 어노테이션
소스코드를 분석하고 처리하기 위해 사용되는 훅. 
- 보일러플레이트코드 제거하는데 도움이 된다. 
: AbstractProcessort 구현하여 만들고 getter/setter 컴파일타임에 만들어서 보일러 플레이트 코드 제거.
marker annotation 메서드 선언 없는 인터페이스
ex) Serializable, Cloneable
public interface Serializable {
}
   

어노테이션 에노테이션 에너테이션 어너테이션

 

책추천: 

아웃라이어... 1만시간....

부의 추월차선.....사업.  5일을 노예처럼일하고. 노예처럼일하기위해 2일을 쉰다. 

 

XDoclet 엑스닥렛 java5.... 에노테이션 전신

 

ServiceLoader : JAR 파일에 포함된 구성 파일을 읽어서 인터페이스 구현을 찾고, 구현을 선택한 오브젝트의 목록으로 사용. 

serviceLoader.load(XXXX.class)

 

@Inherited

package study;

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

@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface InheritedAnnotation {
}

@Retention(RetentionPolicy.RUNTIME)
@interface notInherit{
}
@InheritedAnnotation
class A {}
@notInherit
class B {}
class AA extends A {}
class BB extends B {}

class test{
    public static void main(String[] args) {
        Class AAClass = AA.class;
        Class BBClass = BB.class;

        Annotation[] AAAnnotations =AAClass.getAnnotations();

        for (int i = 0; i < AAAnnotations.length; i++) {
            System.out.println(AAAnnotations[i]);
        }
        Annotation[] BBAnnotations =BBClass.getAnnotations();

        for (int i = 0; i < BBAnnotations.length; i++) {
            System.out.println(BBAnnotations[i]);
        }
    }
}

 

728x90

[스터디할래? Java] 목차

이글은 백기선님 스터디 할래? 스터디를 뒤늦게 따라간 기록입니다.

스터디할래 링크 >> https://github.com/whiteship/live-study

이필기를 시작으로 공부했습니다 >> https://xxxelppa.tistory.com/204?category=858435 , 

여기 없는내용은 스터디 할래 강의 내용 혹은 제가 java Doc보고작성하거나 예제를 만들어 추가했습니다.

그외는 같이 출처가 써있습니다. 

 

enum정의 public enum TODAY {
    MORNING,
    AFTERNOON
}

public enum TODAY_TIME {
    MORNING(6, 11),
    AFTERNOON(12, 6);
    private int startTime;
    private int endTime;

    TODAY_TIME(int startTime, int endTime) {
        this.startTime = startTime;
        this.endTime = endTime;
    }

    public int getStartTime() {
        return this.startTime;
    }

    public int getEndTime() {
        return this.endTime;
    }
}

내부 static
values() vs  valueOf() values : 선언 상수를 배열로 반환, 컴파일되며 생김
valueOf : enum 존재 상수를 가져올때. 상속 받음,  jdk8기준 없으면 illegalArgumentException
ordinal()  TODAY_TIME.AFTERNOON.ordinal()  //1
ordinal  서수 , enum 클래스에 나열된 상수가 몇번째 나열되어있는지. 
zero base 로 넘버링 한 위치를 반환. 
EnumSet, EnumMap 에서 사용.. 내부용
java.lang.Enum enum 은 java.lang.Enum 클래스 상속받음. - 아래 바이트 코드 참고. 
생성자 : Sole constructor : 컴파일러 사용, 사용자 직접 호출사용불가. 
  /**
     * Sole constructor.  Programmers cannot invoke this constructor.
     * It is for use by code emitted by the compiler in response to
     * enum type declarations.
     *
     * @param name - The name of this enum constant, which is the identifier
     *               used to declare it.
     * @param ordinal - The ordinal of this enumeration constant (its position
     *         in the enum declaration, where the initial constant is assigned
     *         an ordinal of zero).
     */
    protected Enum(String name, int ordinal) {
        this.name = name;
        this.ordinal = ordinal;
    }
EnumSet java.util
Set자료구조특징. 중복허용 안함. 
EnumSet<TODAY_TIME> todayTimeAllSet = EnumSet.allOf(TODAY_TIME.class);
EnumSet todayTimeSet = EnumSet.of(TODAY_TIME.AFTERNOON);
EnumSet todayTimeAt =todayTimeAllSet.complementOf(todayTimeSet);  //특정상수제외
System.out.println(todayTimeAllSet.range(TODAY_TIME.MORNING,TODAY_TIME.AFTERNOON));
// 출력 : [MORNING, AFTERNOON][MORNING, AFTERNOON]

EnumSet은 왜 생성자를 사용자가 호출할수있게만들었을까?
1. ReqularEnumSet 개수적을때  JumboEnumSet 많을때
개발한 사람이 구현 객체 발환해준다면.. 사용입장에서 접합한지 몰라도된다 
2. 사용자는 빈번하게 EnumSet초기화 진행가능
3. 확장성, 유지보수
EnumMap EnumMap<TODAY_TIME> enumMap = new EnumMap<>(TODAY_TIME.class)

enum 에넘, 이늄, 열거형

 

추천책 : 토비의 스프링.

하이버네이트 : java persistence ,> 번역서  하이버네이트 

                      JPA 프로그래밍

----------

type safey

- 타입에 안정적

- query DSR 각광.  http://www.querydsl.com/

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

jpa 맵핑시

enum Fruit{

    kiwi, apple, banana

}

@Enumerated(EnumType.STRING)

Fruit fruit;

 

EnumType.STRING

EnumType.ORDINAL  

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

private final static String hello = "/hello";

@GetMapping(hello)  << final 만 참조. "변하지않는값'

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

순서 정의할때 1,2,3 보다는 10,20,30으로 정의 

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

Enum 싱글톤으로 쓸수 있다. 

spring에서  @Component 하면 싱글톤을 사용할수 있다. 

---------

리플렉션 : 객체를 통해 클래스의 정보 분석해내는 기법

Calss c = Data.class;

 

 

 

바이트코드

// class version 52.0 (52)
// access flags 0x4031
// signature Ljava/lang/Enum<Lstudy/TODAY_TIME;>;
// declaration: study/TODAY_TIME extends java.lang.Enum<study.TODAY_TIME>
public final enum study/TODAY_TIME extends java/lang/Enum {

  // compiled from: TODAY_TIME.java

  // access flags 0x4019
  public final static enum Lstudy/TODAY_TIME; MORNING

  // access flags 0x4019
  public final static enum Lstudy/TODAY_TIME; AFTERNOON

  // access flags 0x2
  private I startTime

  // access flags 0x2
  private I endTime

  // access flags 0x101A
  private final static synthetic [Lstudy/TODAY_TIME; $VALUES

  // access flags 0x9
  public static values()[Lstudy/TODAY_TIME;
   L0
    LINENUMBER 5 L0
    GETSTATIC study/TODAY_TIME.$VALUES : [Lstudy/TODAY_TIME;
    INVOKEVIRTUAL [Lstudy/TODAY_TIME;.clone ()Ljava/lang/Object;
    CHECKCAST [Lstudy/TODAY_TIME;
    ARETURN
    MAXSTACK = 1
    MAXLOCALS = 0

  // access flags 0x9
  public static valueOf(Ljava/lang/String;)Lstudy/TODAY_TIME;
    // parameter mandated  name
   L0
    LINENUMBER 5 L0
    LDC Lstudy/TODAY_TIME;.class
    ALOAD 0
    INVOKESTATIC java/lang/Enum.valueOf (Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
    CHECKCAST study/TODAY_TIME
    ARETURN
   L1
    LOCALVARIABLE name Ljava/lang/String; L0 L1 0
    MAXSTACK = 2
    MAXLOCALS = 1

  // access flags 0x2
  // signature (II)V
  // declaration: void <init>(int, int)
  private <init>(Ljava/lang/String;III)V
    // parameter synthetic  $enum$name
    // parameter synthetic  $enum$ordinal
    // parameter  startTime
    // parameter  endTime
   L0
    LINENUMBER 11 L0
    ALOAD 0
    ALOAD 1
    ILOAD 2
    INVOKESPECIAL java/lang/Enum.<init> (Ljava/lang/String;I)V
   L1
    LINENUMBER 12 L1
    ALOAD 0
    ILOAD 3
    PUTFIELD study/TODAY_TIME.startTime : I
   L2
    LINENUMBER 13 L2
    ALOAD 0
    ILOAD 4
    PUTFIELD study/TODAY_TIME.endTime : I
   L3
    LINENUMBER 14 L3
    RETURN
   L4
    LOCALVARIABLE this Lstudy/TODAY_TIME; L0 L4 0
    LOCALVARIABLE startTime I L0 L4 3
    LOCALVARIABLE endTime I L0 L4 4
    MAXSTACK = 3
    MAXLOCALS = 5

  // access flags 0x1
  public getStartTime()I
   L0
    LINENUMBER 17 L0
    ALOAD 0
    GETFIELD study/TODAY_TIME.startTime : I
    IRETURN
   L1
    LOCALVARIABLE this Lstudy/TODAY_TIME; L0 L1 0
    MAXSTACK = 1
    MAXLOCALS = 1

  // access flags 0x1
  public getEndTime()I
   L0
    LINENUMBER 21 L0
    ALOAD 0
    GETFIELD study/TODAY_TIME.endTime : I
    IRETURN
   L1
    LOCALVARIABLE this Lstudy/TODAY_TIME; L0 L1 0
    MAXSTACK = 1
    MAXLOCALS = 1

  // access flags 0x8
  static <clinit>()V
   L0
    LINENUMBER 6 L0
    NEW study/TODAY_TIME
    DUP
    LDC "MORNING"
    ICONST_0
    BIPUSH 6
    BIPUSH 11
    INVOKESPECIAL study/TODAY_TIME.<init> (Ljava/lang/String;III)V
    PUTSTATIC study/TODAY_TIME.MORNING : Lstudy/TODAY_TIME;
   L1
    LINENUMBER 7 L1
    NEW study/TODAY_TIME
    DUP
    LDC "AFTERNOON"
    ICONST_1
    BIPUSH 12
    BIPUSH 6
    INVOKESPECIAL study/TODAY_TIME.<init> (Ljava/lang/String;III)V
    PUTSTATIC study/TODAY_TIME.AFTERNOON : Lstudy/TODAY_TIME;
   L2
    LINENUMBER 5 L2
    ICONST_2
    ANEWARRAY study/TODAY_TIME
    DUP
    ICONST_0
    GETSTATIC study/TODAY_TIME.MORNING : Lstudy/TODAY_TIME;
    AASTORE
    DUP
    ICONST_1
    GETSTATIC study/TODAY_TIME.AFTERNOON : Lstudy/TODAY_TIME;
    AASTORE
    PUTSTATIC study/TODAY_TIME.$VALUES : [Lstudy/TODAY_TIME;
    RETURN
    MAXSTACK = 6
    MAXLOCALS = 0
}

 

 

 

 

 

 

  • enum 정의하는 방법
  • enum이 제공하는 메소드 (values()와 valueOf())
  • java.lang.Enum
  • EnumSet
728x90

[스터디할래? Java] 목차

이글은 백기선님 스터디 할래? 스터디를 뒤늦게 따라간 기록입니다.

스터디할래 링크 >> https://github.com/whiteship/live-study

이필기를 시작으로 공부했습니다 >> https://sujl95.tistory.com/63 

                                               , https://wisdom-and-record.tistory.com/48

여기 없는내용은 스터디 할래 강의 내용 혹은 제가 java Doc보고작성하거나 예제를 만들어 추가했습니다.

그외는 같이 출처가 써있습니다. 

 

프로세스 와 쓰레드 프로세스 : 자원(resources, 데이터+메모리) + 쓰레드 
쓰레드 : 프로세스의 자원을 이용해 셀제 작업을 수행하는것. 
 Runnable vs Thread Runnable : 함수형인터페이스
package java.lang;
public interface Runnable {       
    public abstract void run();
}
---------------
Thread : 클래스, 쓰레드 그룹등 사용가능 
package java.lang;
public class Thread implements Runnable {

--------------
run() 말고 다른것도 재정의가 필요하면 thread상속, run()만 수정하면 Runnble 사용. 
thread는 순서대로 실행되지 않는다. 
suspend(), resume(), stop()//쓰레드종료 안전성때문에 Deprecated
쓰레드는 코어수와 비례
Thread 종류 - 일반쓰레드 : 
- 데몬쓰레드 : 일반쓰레드 보조역할, GC.자동저장, 갱신등 사용. 
                   일반쓰레드 종료시 같이 종료. 보통무한루프로 구현.
                   쓰레드.setDaemon(True) 하면 데몬쓰레드 지정

- 메인쓰레드 : 프로그램 시작시 가장 먼저 실행 쓰레드, 
public static void main(Stringp[] args){}  메인 쓰레드의 시작점 선언
따로 쓰레드 실행하지 않고 main() 메소드만 실행하면 싱글 쓰레드 애플리케이션

JVM -> Other Daemon Threads(ex_ Gc)
       -> MainThread -> Child ThreadA
                            -> Child ThreadB -> child ThreadC
                            ->         ...
Thread 메서드 static void sleep(long millis) : 지정시간 쓰레드 일시정지 -> TIMED_WAITING
void join()   : (지정시간)실행, 호출한 쓰레드 일시정지 호출 실행 완료 후에 재개
void join(long millis)
void interrupt() : sleep(), join() 일시정지 -InterruptedException->  실행대기로 만듬
static void yield() : 실행중에 자신에게 주어진 실행시간 다른쓰레드 양보, 자신은실행대기
public synchronized void start() 호출
쓰레드의 상태     public enum State {
        NEW,                  //객체만 생성 start() 미호출
        RUNNABLE,          // start() 쓰래드 실행
        BLOCKED,            //쓰레드 실행중지, 락이 풀리는것 대기
        WAITING,            //쓰레드 대기중
        TIMED_WAITING,  //특정 시간만큼  대기중 
        TERMINATED;      //쓰레드가 종료
    }

New  -(start())----> Runnable              -> Terminated
                           --------------------
                          -> Blocked
                          -> Waiting           
                          -> Timed Wating 
쓰레드의 우선순위 쓰레드.setPriority(int newPriority)
    public final static int MIN_PRIORITY = 1;       //최소
    public final static int NORM_PRIORITY = 5;   //기본값
    public final static int MAX_PRIORITY = 10;    //최대
runnable vs callable  Runnable :어떤 객체도 리턴하지 않음 , Exception발생시키지 않음
Callable: 특정타입 객체 리턴 Exception 발생가능
public interface Callable<V> {
    V call() throws Exception;
}
https://codechacha.com/ko/java-callable-vs-runnable/
Object의
thread관련 메소드
wait() , wait(long timeout), wait(long timeout, int nanos)
: 동기화블록내  쓰레드를 해당객체 waiting pool에 넣는다. 
notify(), notifyAll()
: 동기화블록내 waitng pool 대기중인 쓰래드를 깨운다. 
synchronized 동기화 
: 여러개의 쓰레드가 한 개의 리소스를 사용하려고 할 때 사용 하려는 쓰레드를 제외한 나머지 접근못하게 함. (Thread-safe)

구현
- Synchronized 키워드 : 동기화블록, 메소드 선언시, 메소드내 특정 문장 감싸기
                                범위가 좁게 사용하는것을 추천. 그래서 동기화블록사용이 적합..
- Atomic 클래스: java.util.concurrent
: 여러쓰레드 접근해도 원자적 접근 데이터 구조 ,한쓰레드씩 접근사용.
- Volatile 키워드 : java 변수를 메인메모리 저장 명시, multi thread 환경 cpu cache값 불일치 문제 때문에 사용. ,한쓰레드씩 접근사용.

Lock  jdk1.5 락. : 상호 배재를 사용할수 있는 클래스 제공
package java.util.concurrent.locks;
public interface Lock {
    void lock();                  // 잠근다.
    void lockInterruptibly() throws InterruptedException;
    boolean tryLock();
    boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
    void unlock();               //해지한다.
    Condition newCondition();
}
lock구현체
- ReentrantLock              : 재진입가능, 가장일반적임
- ReentrantReadWriteLock : 읽기공유가능 쓰기 lock
- StampedLock                 : ReentrantReadWriteLock 에 기능추가. 
DeadLock   교착상태 
둘 이상의 쓰레드가 lock 을 획득하기 위해 대기 하는데 
대기하는 쌍방이 우위를 가리수 없어 어느쪽도 진행되지 않는상태(block)

Thread 1 rocks A, waits for B
Thread 2 locks B, waits for A

동시성 vs 병렬성 concurrency programming model,
: 동시성 프로그래밍 모델 ex_자바쓰레드

Parallelism programing model
: 병렬성 프로그래밍 모델
- critical path : 동시 실행 하는것중 가장 긴거.. 이것을 줄여야 수행시간이 줄다.
----
-----------
---- 
              -----------------
              -----
              -------
                                  ---------
                                  -------------
                                  --------
race condition: 어떻게 접근하느냐에 따라 결과가 달라지는 경우. 

추천책 : 자바 병렬프로그래밍...이출판사 번역신경쓰니참고.

 

thread.. 서버 수준 구현 할때만 필요. ex) tomcat

톰캣 최종분석...톰캣을 만들어봄.... ㅋㅋㅋOTL

요즘 컨테이너는 NIO Connector 사용...

 

동시 프로그래밍 모델: concurrency programing model 

 - 예 자바 쓰레드, Actor Model -아카..., STM(Software Trancsaction memory)- closer

  당시 actor가 가장빠름. contention 이 없어서.. 자원충돌날것이 없음. 

동시성 vs 병렬성

free lunch is over 

: CPU 클럭속도 한계가 와서 더많은 코어를 잘쓸수있는 방향으로. >>멀티쓰레딩 패러다임이 바뀌고 있다. 

무어의 법칙이... 주춤해짐...년 혹은 18개월마다 반도체의 집적도는 2배가 된다

 

Volatile 볼레틸 휘발성 

 

Thread, runnable 구현

package study;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ThreadExample  {
    public static void main(String[] args) {
        Thread byThread = new ThreadByThread();
        byThread.start();

        Runnable runnable  = new ThreadByRunnable();
        Thread byRunnable = new Thread(runnable);
        //byRunnable.run();

        byRunnable.start();
        Lock lock= new ReentrantLock();
    }

    public static void print(String threadInfo , int num){

        for (int i =0; i<100;i++)
            System.out.println(threadInfo + " | " + num);
    }
}

class ThreadByThread extends Thread{
    @Override
    public void run() {
        ThreadExample.print(Thread.currentThread().getName(), 1);
    }
}

class ThreadByRunnable implements Runnable{
    @Override
    public void run() {
        ThreadExample.print(Thread.currentThread().getName(),0);
    }
}

강사님 설명소스. 

package study;

public class ThreadExample  {
    public static void main(String[] args) {
        Thread byThread = new ThreadByThread();
        byThread.start();

        new Thread(()->ThreadExample.print(Thread.currentThread().getName(), 0)).start();
    }

    public static void print(String threadInfo , int num){

        for (int i =0; i<100;i++)
            System.out.println(threadInfo + " | " + num);
    }
}

class ThreadByThread extends Thread{
    @Override
    public void run() {
        ThreadExample.print(Thread.currentThread().getName(), 1);
    }
}

  • Thread 클래스와 Runnable 인터페이스
  • 쓰레드의 상태
  • 쓰레드의 우선순위
  • Main 쓰레드
  • 동기화
  • 데드락
728x90

[스터디할래? Java] 목차

 

이글은 백기선님 스터디 할래? 스터디를 뒤늦게 따라간 기록입니다.

스터디할래 링크 >> https://github.com/whiteship/live-study

이필기를 시작으로 공부했습니다 >>  https://www.notion.so/3565a9689f714638af34125cbb8abbe8

여기 없는내용은 스터디 할래 강의 내용 혹은 제가 java Doc보고작성하거나 예제를 만들어 추가했습니다.

그외는 같이 출처가 써있습니다. 

 

 

자바제공하는 예외 계층구조 Object <- Throwable <- Error :치명적 시스템오류 해결불가. 
                            <- Exception <- RuntimeException : unchecked Exception
                                              <- RE 아닌 Exception : checked Exception
Exception vs Error 오류 :Error : 시스템의 비정상적인 상황이 생겼을때. 시스템레벨, 심각한수준 오류.  예측불가
                개발자가 상속받지도, 사용할필요 없음. 
예외 :Exception : 개발자가 구현한로직에서 발생, 미리 예측 처리
RuntimeException vs RE가 아닌 Exception RuntimeException : Unchecked Exception
: 예외처리 하지 않아도 됨.
ex) IOException, SQLException

RE 아닌 Exception : checked Exception
: 반드시 예외 처리. 
NullPointException, IllegalArgumentException

https://cheese10yun.github.io/checked-exception/
throw vs throws throws 현재 메서드에서 호출한 "상위 메서드로 Exception 발생"
throw : 현재 메서드에  프로그래머가 일부러 에러를 발생시킬때  throw new XXXException();
예외 처리방법 1. 예외 복구 : 예외 발생시 다른작업 흐름유도
   : try -catch ~final
2. 예외처리 회피(전파) : 처리하지 않고 호출한 쪽으로 던짐
   : throw ~.. 
3. 예외 전환 : 호출한쪽으로 명확한 의미 전달하기위해 다른예외 전환던짐
    : try -catch( 특정예외 e ){throw 커스텀예외} ~final
from 토비의 스프링 3.1 Vol.1 4장 예외
(최종까지 예외 발생시 예외처리후 해당 쓰레드 종료. )
커스텀한 예외 만드는법.  커스텀예외 참고4가지
1. 항상 이익이 있어야 한다. jdk 있으면 ..있으면있는거 써라
2. 네이밍 규칙 따르기
3. 자바doc을 작성하세요. 
4. 커스텀 예외 던지기전 예외의 이유를 작성하자. 
    원래 발생한 에러가 있으면 같이 전달.  생성자에 Throwable cause 변수 추가. 
(참고. https://m.blog.naver.com/sthwin/221144722072, https://dzone.com/articles/implementing-custom-exceptions-in-java?fromrel=true)
 예외처리 비용.  예외 발생시 발생메서드의 Stack Trace를 모두 메모리에 담고있어야함>> 비용
예외처리로 비즈니스로직 처리 피하는 이유 
로직으로 할수 있는것은 예외던지는것보다 값을 리턴하는게 비용적으로 이득. 
try - catch - finally catch 여러 줄일때 상속관계 인지 주의 할것. 상위 상속관계가 뒤에 
finally 안에 return 을 쓰는 것은 anti 패턴.  finally에 리턴이 있음 try 리턴작동안함. 
e.printStackTrace 로그로 출력하면 안되는 정보들 주의 -개인정보
Multicatch블록 JDK 1.7, 역시 부모자식관계 주의 
try{         }catch(예외1 | 예외2 | 예외3 e) {         }
메서드체이닝 여러 메서드 호출을 연결해 하나의 실행문 표현. 
Init init = new Init();
init.set1(1); init.set2(2); init.set3(3);
메서드 체이닝 :  init.set1(1).set2(2).set3(3);
- setN메서드의 리턴값으로 this를 반환 해서 만듬. 
try-with-resource -알아서 close처리. finally 생략 가능해짐
--컴파일코드 보면 다중 try catch 문이 생기고 catch 블록에서 Throwble로 잡아 close를 해줌. 마지막에도 close()호출. (아래 컴파일 전후 확인)
메이븐 >라이프사이클>컴파일> 타켓 폴더 생성 해당 class파일 확인
@Cleanup -lombok close를 호출해줌.  알고만있고 try-with -resource.로~
   
   
   
   
   
트랜젝션 스프링 기본 트랜젝션 전략에서... 설정을 확인할필요. 
기본적으로 Checekd Exception은 Rollback 하지 않고
unchecked Exception 은 Rollback됨.
스택프레임 스택영역에서 함수 호출 끝난뒤에 돌아갈 정보들을 쌓아놓은곳을 스택프래임이라고한다. 
많이쓰는 기본예외 런타임아닌익셉션 계열 : checked 예외
ClassNotFoundException 
FileNotFoundException 
IOException 
InterruptedException : 특정쓰레드 작업 멈춰달라..
NoSuchMethodException 

RuntimeException계열 : unchecked예외
ArithmeticException : 산술(Arithmetic)연산
ArrayIndexOutOfBoundsException : 배열 인덱스 넘어갈때 
NullPointerException
NumberFormatException
StringIndexOutOfBoundsException
illegalargumentexception 값이 잘못들어옴. 

GoF의 다자인패턴. 

surrond with .. :ctrl alt T

리펙터링 책추천. http://www.yes24.com/Product/Goods/89649360

 

try-with-resource

package study;

import java.io.FileInputStream;
import java.io.InputStream;

public class TryCatchResource {



    public static void main(String[] args) {
        try(InputStream inputStream = new FileInputStream("없는파일.xml")){
            System.out.println(inputStream.toString());
        }catch (Exception e){

        }finally {

        }

    }
}





















package study;

import java.io.FileInputStream;
import java.io.InputStream;

public class TryCatchResource {
    public TryCatchResource() {
    }

    public static void main(String[] args) {
        try {
            try {
                InputStream inputStream = new FileInputStream("없는파일.xml");
                Throwable var2 = null;

                try {
                    System.out.println(inputStream.toString());
                } catch (Throwable var20) {
                    var2 = var20;
                    throw var20;
                } finally {
                    if (inputStream != null) {
                        if (var2 != null) {
                            try {
                                inputStream.close();
                            } catch (Throwable var19) {
                                var2.addSuppressed(var19);
                            }
                        } else {
                            inputStream.close();
                        }
                    }

                }
            } catch (Exception var22) {
            }

        } finally {
            ;
        }
    }
}

 

 

Q1 아래 소스 문제는?

답 : close에 try catch블록이 없다.in 닫을 때 예외 발생하면 out 못닫음 

출처 : 백기선의 스터디할래 강의

Q2 뭣이출력

답: 3

package study;

public class TryCatchFinal {

    public static void main(String[] args) {

       int num = onTryCatchFinally();
        System.out.println(num);
    }

    private static int onTryCatchFinally() {

        try {

            return 1;
        }catch (Exception e){
            return 2;
        }finally {
            return 3;
        }
    }
}

 

package study;

public class TryCatchFinal {

    public static void main(String[] args) {

       int num = onTryCatchFinally(100);
        System.out.println(num);
    }

    private static int onTryCatchFinally(int num) {

        try {
            if (num ==100){
                new RuntimeException();
            }
            return 1;
        }catch (Exception e){
            return 2;
        }finally {
            return 3;
        }
    }
}
728x90

[스터디할래? Java] 목차

이글은 백기선님 스터디 할래? 스터디를 뒤늦게 따라간 기록입니다.

스터디할래 링크 >> https://github.com/whiteship/live-study

이필기를 시작으로 공부했습니다 >> https://www.notion.so/4b0cf3f6ff7549adb2951e27519fc0e6

여기 없는내용은 스터디 할래 강의 내용 혹은 제가 java Doc보고작성하거나 예제를 만들어 추가했습니다.

그외는 같이 출처가 써있습니다. 

 

인터페이스 규약. : 개발기간 단축, 결합도 낮주기, 표준화 

구성
-상수
-추상메소드     : 재정의 하여 사용
-디폴트 메소드  jdk8  : 재정의 가능
-스테틱 메소드  jdk8  : 변경불가

구현방법
- 상속
- 익명클래스 

다중상속
- 동일 이름 메서드 있을때. 재정의 필요. 
@Overide
public void sameMethod(){
  AInterface.super.sameMethod();
  BInterface.super.sameMethod();
}
-동일 이름 static 메서드
재정의가 안됨. 
-동일 이름 메서드 부모 static, 자식 default
 호출방법이 다름. 
- 동일이름 메서드 무보 default 자식 static
  불가. 
추상클래스
vs 인터페이스
public class LinkedList<E>
    extends AbstractSequentialList<E>
    implements List<E>, Deque<E>, Cloneable, java.io.Serializable

링크드 리스트는 "추상 순차 목록"이다. "List, Deque, Cloneable, Serializable" 을 할수 있다.
해당 클래스는 "추상~~~클래스"이다. "인터페이스" 을 할수 있다. 
클래스타입레퍼런스
vs 인스턴스 레퍼런스
클래스타입레퍼런스 : CalssA  classA = new CallsA();
인스턴스타입레퍼런스 : List<String> stringList = new ArrayLIst<>();
강한결합 vs 느슨한결합 강한결합: 코드 변경필요 :빠르지만 변경불리
기존 : A -> B
추가 : A -> C ->B or A->B->C
느슨한 결합 :코드변경 필요없음: 느리지만 유연하고 변경 유리
기존 : A--->I , I->B
추가: C --->I
default Method java8
등장이유 : 하위 호환성, 오픈소스코드에서 메소드가 추가되었을때 오류가 발생할수있다. 
from 자바의 신
이전에는 Handler 기능이 필요하면 추상클래스 adoptor를상속받아 일부만 구현할수 있게했음

public interface HandlerInterceptor {
    default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return true;
    }
static method java8
File의
 public static File[] listRoots() {
        return fs.listRoots();
    }
private method java9

1. private 메소드는 구현부를 가져야한다. 
2. 오직인터페이스 내부에서만사용가능
3. private static 메소드는 다른 static, static아닌 메소드에서 사용가능 ??? 아직모르겠다. 
4. static이 아닌 private메소드는 private static  메소드에서 상용불가
private static method java9
File의 
  private static String slashify(String path, boolean isDirectory) {
        String p = path;
        if (File.separatorChar != '/')
            p = p.replace(File.separatorChar, '/');
        if (!p.startsWith("/"))
            p = "/" + p;
        if (!p.endsWith("/") && isDirectory)
            p = p + "/";
        return p;
    }
자바 8 이후 추상클래스 자바8 , 9 기준 인터페이스 에서 못하는부분이 남아있음. 

public abstract class AbstractJoinMember {
   private String message  =""
   public void setMessage(String message){
   }
}

인터페이스 구현불가 : private 상수.  자바8기준 private 안됨. 
Constant Interface 안티패턴임. 사용하지 마세요~
1. 상수포함하여 모두 가져오고 계속가지고있음
2. 컴파일때 사용 런타임때 용도없음
3. 이진호환성을 필요로할때  계속유지
4. IDE가 없으면 상수 implement한 클래스에서 상수 사용할 때 네임스페이스 사용하지 않음 
    네임스페이스도 인터페이스 상수들로 오염
5. 인터페이스 구현해 클래스를 만드는 것은 클라이언트에게 알리는 행위... 혼동
6. 의도치 않은 현상 발생
https://jessyt.tistory.com/78
안티패턴 소프트웨어 공학 분야 용어이며, 실제 많이 사용되는 패턴이지만 비효율적이거나 비생산적인 패턴을 의미한다. 

 

 

extract method : 리펙토링메뉴. ????

https://spark.adobe.com/sp/design/page/new?_branch_match_id=623005067329261293 

로고, 아이콘만들때. 

비폭력 대화 

 

  • 인터페이스 정의하는 방법
  • 인터페이스 구현하는 방법
  • 인터페이스 레퍼런스를 통해 구현체를 사용하는 방법
  • 인터페이스 상속
  • 인터페이스의 기본 메소드 (Default Method), 자바 8
  • 인터페이스의 static 메소드, 자바 8
  • 인터페이스의 private 메소드, 자바 9
728x90

[스터디할래? Java] 목차

이글은 백기선님 스터디 할래? 스터디를 뒤늦게 따라간 기록입니다.

스터디할래 링크 >> https://github.com/whiteship/live-study

이필기를 시작으로 공부했습니다 >>  https://kils-log-of-develop.tistory.com/430

                                                https://sangwoobae.github.io/posts/java-livestudy-7week/

여기 없는내용은 스터디 할래 강의 내용 혹은 제가 java Doc보고작성하거나 예제를 만들어 추가했습니다.

그외는 같이 출처가 써있습니다. 

package 키워드 패키지 이름은 java로 시작하면안된다. 
소스 첫줄, 
폴더이름과 패키지 이름이 같아야
FQCN : Fully Qualified Class Name : 패키지이름과 정의된 클래스 모 표현되야 정확한 표현
ex) java.lang.String
FQCN  FQCN : Fully Qualified Class Name : 패키지이름과 정의된 클래스 모 표현되야 정확한 표현
패키지이름 규칙 java : 자바기본 패키지
javax : 자바 확장패키지
org : 비영리단체(오픈소스) 패키지
com : 영리단체(회사) 패키지

패키지 이름은 모두 소문자. 
자바 예약어 사용불가

빌트인 패키지 : 자바는 개발자들이 사용하는 패키지, 클래스 제공
ex) import java.lang.System, import java.lang.String
import 키워드 import 패키지*  사용가능. 
import static 

* import 하지 않아도 되는 패키지
java.lang, 같은패키지
접근제어자 public            누구나 접근
protected       같은패키지, 상속받은경우
private-package  = default  : 같은패키지내
private            해당클래스내 
클래스 패스 JVM이 프로그램 실행할때 클래스파일을 찾는데 기준되는 파일경로. 
- java runtime -classpath 
- javac -classpath
- 환경변수 CLASSPATH  안하는쪾으로..개발할때 라이브러리 꼬일수있음. 
CLASSPATH=
클래스 패스 옵션은 언제 쓸수 있나? 둘다 or javac or java   >> 둘다 쓸수 있다. 
cf)
maven pom.xml scop- runtime, provied.. 의존성설정 관련되어있다고함. 
클래스 로더.  java 에 3가지 기본 클래스 로더 존재
Bootstrap class loader
: 최상위 클래스 로더, jre/lib/rt.jar 에 담긴 JDK 클래스 파일 로딩
: 원시 클래스 로더 : Primordial ClassLoader
Extension class loader
: jre/lib/ext , java.ext.dirs 로 지정된 클래스파일 로딩. 
Application class loader
: classpath 나 jar 파일 안에 있는 Manifest파일의 class-path 속성값으로 지정된 폴더의 클래스 로딩
: 자가 애플리케이션 구동을 위해 직접 작성한 대부분클래스는 애플리케이션 클래스 로더에 의해로딩

동작 3원칙
1. 위임 : 클래스 로딩 작업을 상위 클래스 로더 위임
2. 가시범위 원칙 : 하위클래스 로더 상위클래스로더 볼수 있지만 상위는 하위클래스로더 로딩 볼수없음
3. 유일성 원칙 : 하위 클래스로더는 상위 클래스 로더가 로딩한 클래스를 다시로딩하지 못함

https://umanking.github.io/2019/06/25/java-class-loader/#:~:text=%E2%80%BB%20rt.jar%20%ED%8C%8C%EC%9D%BC%EC%9D%B4%EB%9E%80,%EC%8B%9C%EC%97%90%20%EB%A9%94%EB%AA%A8%EB%A6%AC%EC%97%90%20%EC%98%AC%EB%A6%B0%EB%8B%A4.
rt.jar RunTime
코어 자바클래스의 콜렉션, 
JVM 에서 rt.jar 파일에 담긴 클래스 파일을 런타임때 메모리에 올림. 
String, System 클래스가 rt.jar 안에 있음. 
Built-in 패키지 패키지 = 사용자정의패키지 + 빌트인패키지
java.lang : 프리미티브타입, String
java.io : 입출력
java.util : 자료구조  Linked, Dictionary Time, Date
java.applet : Applets 생성
java.awt :  GUI 컴포넌트를 구현하기 위한 클래스들을 포함하는 패키지
java.net : 네트워킹 지원 
https://ahnyezi.github.io/java/javastudy-7-package/
   
   

테스트 주도개발 저자 켄트 벡|역자 김창준, 강규영|인사이트

maven or gradle 반드시 공부할것. 

java9 부터 모듈화가 많이됨.

클래스로더 계층구조.

부트스트랩: 최상단 

1. 부모한테 있는가?

2. 부모한테 없으면 자기가 읽음. 

보통 최상단 rt.jar에 java.lang을 읽어둠. 

 

heap 사이즈는 기본적으로 다이나믹. min max... 똑같이 썼었다.....요즘도...

java실행중 max 조정하는방법? 메모리누수.....그걸고칩시다.>> 실행할때 정해짐. 

튜닝 : 애플리케이션이 최대한으로 쓸수있는 heap을 찾는 과정. 

 

https://www.geeksforgeeks.org/java/?ref=ghm

 

Constant Interface  >> 쓰지마세용...

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

public interface Constats{

  int NUMBER = 100;

  String NAME = "NAME";

}

public class myBook implements Constants{

  private static final String NAME ="";

]

}

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

>> 1. anti patten. : 인터페이스가 존재하는 목적이 아님. 규약 정하는게 목적. 

>> 2. 상수를 갖고 인스턴스를 만들게됨. 

인터페이스는 기본적으로 public static 이 써있음. .

public class Constants{

  public static final int NUMBER=100;

   private Constants(){}  // 생성못하게 막음. 

}

!! ENUM >> 선택가능한값 고정할때!!!

JPA.. 쿼리 DSR 

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

import를 구체적 or 포괄적 ... 설정...  java > import > Class.... 999 이렇게 넣으면 패키지.* 사용하지 않음(명시적)

 

  • package 키워드
  • import 키워드
  • 클래스패스
  • CLASSPATH 환경변수
  • -classpath 옵션
  • 접근지시자
728x90

[스터디할래? Java] 목차

이글은 백기선님 스터디 할래? 스터디를 뒤늦게 따라간 기록입니다.

스터디할래 링크 >> https://github.com/whiteship/live-study

이필기를 시작으로 공부했습니다 >>  https://leemoono.tistory.com/20 

여기 없는내용은 스터디 할래 강의 내용 혹은 제가 java Doc보고작성하거나 예제를 만들어 추가했습니다.

그외는 같이 출처가 써있습니다. 

자바상속 특징 다중상속 금지 : extends A, B   X
최상위 클래스 Object
디스패치  프로그램이 어떤 메소드를 호출할 것인가를 결정하여 그것을 실행하는 과정. 
- 동적 디스패치
- 정적 디스패치
Static Dispatch
정적 디스패치
어떤 메소드 실행될지 컴파일시점에서 알수 있음. 
static class Do{
void run(){}
void run(int number){}
}
Do.run();  <<<  정적디스패치는 ... 메소드 오버로딩의 경우. 
Dynamic Method Dispatch
동적 디스패치
컨파일타임에 알수 없는 메서드 의존성을 런타임에 늦게 바인딩
abstract class Do{
void run(){}
}
class MoningDo extends Do{
  @Overried
   void run(){ System.out.println("1"); }
}
class EveningDo extends Do{
  @Overried
   void run(){ System.out.println("2"); }
}
EveningDo ed = new EveningDo();
ed.run()  <<<<< 컨파일때는 알수 없고, 런타임때 알수 있다. 
바이트코드 : imvokvirtual : 동적디스패치
cf) 바이트코드 : imvorkspecial : 생성자 호출. 
더블 디스패치 동적 디스패치 두번 발생 
- 방문자 패턴: visitor partten 더블 디스패치 사용한 대표적 패턴.  
interface Post{
  void postOn(SNS sns);
}
class Text implements Post{
  public void postOn(Sns sns){ sns.post(this);}
}
class Picture implements Post{
  public void postOn(Sns sns){ sns.post(this);}
}
--------------------------- POST 구현하는클래스2개 postOn 생성. 
interface SNS{
  void post(Text text);
  void post(Picture picture);
}
class Facebook implements SNS{
   public void post(Text text){}
   public void post(Picture Picture){}
}
class Twitter implements SNS{
  public void post(Text text){}
   public void post(Picture Picture){}
}
--------------------------상기 상속받은 클래스를 매개변수로 쓰는 SNS 상속클래스 2개

public static void main(String[] args) {
     List<Post> posts = Arrays.asList(new Text(), new Picture()); 
     List<SNS> sns = Arrays.asList(new Facebook(), new Twitter());
     posts.forEach(p -> sns.forEach(s -> p.postOn(s)));
     //1. 어떤 구현체의 PostOn. 2. 어떤 SNS의 post  : 두번발생. 
}
출처 : https://blog.naver.com/swoh1227/222181505425
방문자 패턴 visitor pattern 
- SAX Parser  (cf _DOM Parser)



final class
variable
method
Object 클래스 clone: 해당객체 복제본생성
finalize()  해당객체 더는 아무도 참조지 않아 GC 호출함
notify()  해당객체 대기하고 있는 스레드 다시실행 할때 호출
wait()  notify, notifyall 메소드 호출전까지 현재 스레드 일시적 대기.  
varargs 가변인자, 변수의 마지막선언
내부적으로 배열로 받음. 
String... message  ==  String[] message
-------------------
void sum (String A, String...str){}
void sum (String...str){}
컴파일에러. 
------------------
var = variable
args = 아그 독립변수. 변수 독립변수. 
UML 상속 : 실선
구현 : 점선

- 클래스이름
- 필드내용
- 메소드 내용

객체지향의 사실과 오해, 오브젝트- 조영호저

dispatch : 보내다. 

 

 

웹 uml 툴 : https://app.diagrams.net/

public class Object {

    private static native void registerNatives();
    static {
        registerNatives();
    }
    public final native Class<?> getClass();
    public native int hashCode();
    public boolean equals(Object obj) {
        return (this == obj);
    }
    protected native Object clone() throws CloneNotSupportedException;

    public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }
    public final native void notify();
    public final native void notifyAll();
    public final native void wait(long timeout) throws InterruptedException;
    public final void wait(long timeout, int nanos) throws InterruptedException {
        if (timeout < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (nanos < 0 || nanos > 999999) {
            throw new IllegalArgumentException(
                                "nanosecond timeout value out of range");
        }

        if (nanos > 0) {
            timeout++;
        }

        wait(timeout);
    }
    public final void wait() throws InterruptedException {
        wait(0);
    }
    protected void finalize() throws Throwable { }
}

학습할 것 (필수)

  • 자바 상속의 특징
  • super 키워드
  • 메소드 오버라이딩
  • 다이나믹 메소드 디스패치 (Dynamic Method Dispatch)
  • 추상 클래스
  • final 키워드
  • Object 클래스

 

728x90

Error 1

현상 @Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();}

등록시 경로지정을 안해줬다는 에러발생.
찾은것 stackoverflow.com/questions/64822250/illegalstateexception-after-upgrading-web-app-to-spring-boot-2-4
결론 원인은 스프링에서도 component-scan 을 재지정해줌
스프링 부트 그대로 사용하기위해 xml 빈을 안만드려고 다른방법 찾아다니다. 하기 방법발견. 
@Bean
WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> enableDefaultServlet() {
return (factory) -> factory.setRegisterDefaultServlet(true);
}
728x90

GIT : github.com/miseongshin/diary/tree/forValidationInBlog


INDEX

 

1. @Valitated

  • CustomerController.java

2. Custom Validate Annotation

  • CustomerSignUpData.java
  • SameValue.java
  • SameValueValidator.java

3. Validation Annotation, BindingResult

  • CustomerController.java
  • CustomerSignUpData.java
  • DiaryValidErrorException.java
  • DiaryExceptionHandlers.java
  • ValidErrorData.java
  • ValidErrorResultData.java

4. Sequences(or order)

  • CustomerController.java
  • CustomerSignUpData.java
  • Sequences.java

 


1.  pom.xml 

org.hibernate.validator is  for the Validated field

com.google.cod.gson is for JUnit5

        <!-- valid annotation for  @Valid  -->
        <dependency>
            <groupId>org.hibernate.validator</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>6.0.13.Final</version>
        </dependency>
        <!-- for json parameter for java bean  -->
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

2. CustomerController.java

@Valitated(Sequence.class) is for Sequences(or order)

@Validated(Sequences.class) @RequestBody CustomerSignUpData customerSignUpData, BindingResult bindingResult) throws DiaryValidErrorException

and

if (bindingResult.hasErrors()) {
throw new DiaryValidErrorException(bindingResult, messageSource);
}

are for @Valitated, BindingResult

    @PostMapping("/signUp/ajax")
    @ResponseStatus(HttpStatus.CREATED)
    public ResponseEntity<Map> signUpAjax(HttpServletRequest request, @Validated(Sequences.class) @RequestBody CustomerSignUpData customerSignUpData, BindingResult bindingResult) throws DiaryValidErrorException {

        if (bindingResult.hasErrors()) {
            throw new DiaryValidErrorException(bindingResult, messageSource);
        }

        Map result = new HashMap<>();

        return ResponseEntity.ok(result);
    }

3. CustomerSignUpData.java

@SameValue(field = "password", fieldMatch = "confirmPassword") is for Custom Validation

groups= Sequences.OrderXX.class is Sequences(or order),

package com.today10sec.diary.customize.dto;

import com.today10sec.diary.customize.validator.SameValue;
import com.today10sec.diary.customize.validator.Sequences;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.hibernate.validator.constraints.Length;

import javax.validation.constraints.Email;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Pattern;

@Setter
@Getter
@AllArgsConstructor
@ToString(exclude = {"password", "confirmPassword"})
@SameValue(field = "password", fieldMatch = "confirmPassword", groups= Sequences.Order6.class)
public class CustomerSignUpData {


    @NotEmpty(groups = Sequences.Order1.class)
    @Length(max=320, groups= Sequences.Order2.class)
    @Email(groups= Sequences.Order2.class)
    private String email;

    @NotEmpty(groups= Sequences.Order3.class)
    @Length(min= 6, max= 12, groups= Sequences.Order4.class)
    @Pattern(regexp="[a-zA-Z1-9]{6,12}",groups= Sequences.Order4.class)
    private String password;


    @NotEmpty(groups= Sequences.Order5.class)
    @Length(min= 6, max= 12, groups= Sequences.Order7.class)
    private String confirmPassword;

}

4. SameValue.java

this source for Custom Validation

package com.today10sec.diary.customize.validator;

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Constraint(validatedBy = SameValueValidator.class)
public @interface SameValue {

    String field();

    String fieldMatch();

    String message() default "{come.today10sec.diary.error.valid.samePassword}";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};

}

5. SameValueValidator.java

this source for Custom Validation

package com.today10sec.diary.customize.validator;

import org.springframework.beans.BeanWrapperImpl;
import org.springframework.stereotype.Component;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

@Component
public class SameValueValidator implements ConstraintValidator<SameValue,Object> {

    private String field;
    private String fieldMatch;

    @Override
    public void initialize(SameValue constraintAnnotation) {
        this.field = constraintAnnotation.field();
        this.fieldMatch = constraintAnnotation.fieldMatch();

    }

    @Override
    public boolean isValid(Object object, ConstraintValidatorContext constraintValidatorContext) {

        String fieldValue = String.valueOf(new BeanWrapperImpl(object).getPropertyValue(field));
        String fieldMatchValue = String.valueOf(new BeanWrapperImpl(object).getPropertyValue(fieldMatch));

        if (fieldValue == null) {
            throw new RuntimeException("fieldValue can not be null");
        }else if(fieldMatchValue ==null ){
            throw new RuntimeException("fieldMatchValue can not be null");
        }

        if (fieldValue.equals(fieldMatchValue)){
            return true;
        } else{

            constraintValidatorContext.disableDefaultConstraintViolation();
            constraintValidatorContext.buildConstraintViolationWithTemplate("message")
                    .addPropertyNode(fieldMatch)
                    .addConstraintViolation();
            return false;
        }
    }
}

6. Sequences.java

this source for Sequences(or order)

package com.today10sec.diary.customize.validator;

import javax.validation.GroupSequence;
import javax.validation.groups.Default;

@GroupSequence(value = {Sequences.Order1.class, Sequences.Order2.class, Sequences.Order3.class, Sequences.Order4.class, Sequences.Order5.class, Sequences.Order6.class, Sequences.Order7.class, Sequences.Order8.class, Sequences.Order9.class, Sequences.Order10.class, Default.class})
public interface Sequences {

    public @interface Order1 {
    }

    public @interface Order2 {
    }

    public @interface Order3 {
    }

    public @interface Order4 {
    }

    public @interface Order5 {
    }

    public @interface Order6 {
    }

    public @interface Order7 {
    }

    public @interface Order8 {
    }

    public @interface Order9 {
    }

    public @interface Order10 {
    }
}

7. DiaryValidErrorException.java

this source for Custom Validation BindingResult

package com.today10sec.diary.customize.exception;

import lombok.Getter;
import org.springframework.context.MessageSource;
import org.springframework.http.HttpStatus;
import org.springframework.util.Assert;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ResponseStatus;

/**
 * Validation Exception for Common Diary 
 */
@ResponseStatus(value= HttpStatus.BAD_REQUEST)
@Getter
public class DiaryValidErrorException extends Exception {

    private final BindingResult bindingResult;
    private final MessageSource messageSource;

    public DiaryValidErrorException(BindingResult bindingResult, MessageSource messageSource) {
        Assert.notNull(bindingResult, "BindingResult must not be null");
        Assert.notNull(bindingResult, "BindingResult must not be null");
        this.bindingResult = bindingResult;
        this.messageSource = messageSource;
    }
}

8. ValidErrorExceptionHandler.java

this source for Custom Validation, BindingResult

package com.today10sec.diary.config;

import com.today10sec.diary.customize.dto.ValidErrorData;
import com.today10sec.diary.customize.dto.ValidErrorResultData;
import com.today10sec.diary.customize.exception.DiaryValidErrorException;
import org.springframework.context.MessageSource;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import java.util.List;
import java.util.stream.Collectors;

@ControllerAdvice
public class DiaryExceptionHandlers {

    @ResponseBody
    @ExceptionHandler(DiaryValidErrorException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ValidErrorResultData ValidErrorExceptionHandler (DiaryValidErrorException diaryValidErrorException){

        MessageSource messageSource = diaryValidErrorException.getMessageSource();
        BindingResult bindingResult = diaryValidErrorException.getBindingResult();

        List<ValidErrorData> errorDataList = bindingResult.getFieldErrors()
                .stream().map(error-> new ValidErrorData(error, messageSource)
                ).collect(Collectors.toList());

        return new ValidErrorResultData(errorDataList);
    }
}

9. ValidErrorData.java

this source for Custom Validation, BindingResult

package com.today10sec.diary.customize.dto;

import lombok.Getter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.validation.FieldError;

import java.util.Locale;

@Getter
public class ValidErrorData {

    Locale locale;

    private String fieldName;
    private String message;

    public ValidErrorData(FieldError fieldError, MessageSource messageSource){
        this.fieldName = fieldError.getField();
        this.message = messageSource.getMessage(fieldError.getCodes()[0],fieldError.getArguments(),fieldError.getDefaultMessage()+"["+fieldError.getCodes()[0]+"]",locale);
    }

    @Autowired
    public void setLocale(Locale locale) {
        this.locale = locale;
    }
}

10. ValidErrorResultData.java

this source for Custom Validation, BindingResult

package com.today10sec.diary.customize.dto;


import lombok.AllArgsConstructor;
import lombok.Getter;

import java.util.List;

@AllArgsConstructor
@Getter
public class ValidErrorResultData {
    private final Boolean validData = true;
    private List<ValidErrorData> errors;
}

 

11. CustomerControllerTest.java

this source for Custom Validation

package com.today10sec.diary.mvc.controller;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.google.gson.Gson;
import com.today10sec.diary.customize.dto.CustomerSignUpData;
import com.today10sec.diary.customize.dto.ValidErrorResultData;
import com.today10sec.diary.customize.validator.SameValue;
import com.today10sec.diary.customize.validator.SameValueValidator;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayNameGeneration;
import org.junit.jupiter.api.DisplayNameGenerator;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
@ExtendWith(SpringExtension.class)
@WebMvcTest({CustomerController.class, SameValueValidator.class, SameValue.class, CustomerSignUpData.class})
class CustomerControllerTest {

    @Autowired
    MockMvc mockMvc;

    @Test
    void SIGN_UP_AJAX_VALID_CONFIRM_PW() throws Exception {

        String expectedResult = "{\"validData\":true,\"errors\":[{\"locale\":null,\"fieldName\":\"confirmPassword\",\"message\":\"비밀번호와 비밀번호확인값이 일치하지 않습니다. \"}]}";
        CustomerSignUpData customerSignUpData = new CustomerSignUpData("a@a.com","111111","222222" );
        ObjectMapper mapper = new ObjectMapper();
        mapper.configure(SerializationFeature.WRAP_ROOT_VALUE, false);
        ObjectWriter ow = mapper.writer().withDefaultPrettyPrinter();
        String requestJson=ow.writeValueAsString(customerSignUpData);

        MvcResult mvcResult= mockMvc.perform(
                post("/customer/signUp/ajax")
                        .contentType(MediaType.APPLICATION_JSON)
                        .accept(MediaType.APPLICATION_JSON)
                        .content(requestJson))
                .andDo(print())
                .andExpect(status().isBadRequest())
                .andReturn();

        String result = mvcResult.getResponse().getContentAsString();
        Gson gson = new Gson();
        ValidErrorResultData resultData = gson.fromJson(result, ValidErrorResultData.class);
        Assertions.assertEquals("confirmPassword",resultData.getErrors().get(0).getFieldName(),"confirmPassword not contian");

    }

}

 

 

>> 도움이 많이 되었는데 예전버전이라 이것저것하면서 적용

***Spring REST Validation Example mkyong.com/spring-boot/spring-rest-validation-example

**Spring Boot Validation 순서 정하기 & 테스트 코드 dncjf64.tistory.com/302

www.baeldung.com/spring-mvc-custom-validator

mkyong.com/java/how-do-convert-java-object-to-from-json-format-gson-api/

728x90

error 1.

문제 Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
검색 에러 발생 시 Eclipse Run Configurations에서 Arguments에 --debug 추가  출처  kamsi76.tistory.com/entry/%EC%8B%9C%EC%9E%91
해결 application.properties 에 설정추가. 
logging.level.org.springframework= debug
logging.level.org.springframework.web= debug

error 2. 

문제 defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment]
해결 DB 서버 재기동 & 상태점검 >> 도커재기동  restart docker

 

error3

문제 org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Error while committing the transaction

중략
Caused by: javax.validation.ConstraintViolationException: Validation failed for classes [com.today10sec.diary.customize.model.Customer] during persist time for groups [javax.validation.groups.Default, ] List of constraint violations:[ ConstraintViolationImpl{interpolatedMessage='반드시 최소값 6과(와) 최대값 12 사이의 길이이어야 합니다.', propertyPath=password, rootBeanClass=class com.today10sec.diary.customize.model.Customer, messageTemplate='{org.hibernate.validator.constraints.Length.message}'} ] at org.hibernate.cfg.beanvalidation.BeanValidationEventListener.validate(BeanValidationEventListener.java:140) 
해결 스프링시큐리티 적용하면서 password 길이수가 늘었는데 생각못해서. 수정
validate range  change

error4

문제 jpa count NonUniqueResultException: query did not return a unique result: 31

중략

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'XXXController': Unsatisfied dependency expressed through field 'XXXControllerService'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'defaultXXXControllerService': Injection of autowired dependencies failed; nested exception is org.springframework.dao.IncorrectResultSizeDataAccessException: query did not return a unique result: 31; nested exception is javax.persistence.NonUniqueResultException: query did not return a unique result: 31

해결 count 를 사용하려고 했는데  이렇게 인간적인 jpa 일쭐이야.
count 밖에 쓸일이 없는 쿼리라 count로 정의 하려고 했는데.. 고민될정도로 count사용이 지저분했다.  
1. 리턴값은 List<long> 
그리고 조건을 group by 한 거였는데   list 의 길이가 내가 원한 값(그룹바이한 조건 값 31)이고  리스트 안에 long 은 반복되는 횟수(3)였다.   

error5

문제 Invocation of init method failed; nested exception is org.hibernate.AnnotationException: A Foreign key refering co   
중략  
has the wrong number of column. should be 2

해결 멀티키를 가진 model 을 join 할때 해당 멀티키를 각각  @joinColumn 선언필요
... 우선선언은했는데.. sn 한 컬럼만조인하면되는데.. 쓰레기 컬럼이 생겨버림...

error6

문제 Unable to find column with logical name XXXX:  in org.hibernate.mapping.Table(XXXX) and its related supertables and secondary tables
해결 @column @joinColumn 선언 검토 필요
테이블 구조를 변경하면서 오타발생

error7  >> 추가 검토 필요. 

문제 2022-06-18 17:40:42.159 ERROR 17664 --- [p-nio-80-exec-5] o.h.engine.jdbc.spi.SqlExceptionHelper   : HikariPool-1 - Connection is not available, request timed out after 30012ms.
해결 https://techblog.woowahan.com/2664/
쓰레드 1개, 히카리 Maximum pool size 1개 -> 하나의 task 에 동시 요구되는 connection 2개

풀싸이즈 = 트랜젝션 x  (커넥션-1) +1
풀사이즈 = 트랜젝션 (커넥션-1) + 트랜젝션/2

  java.lang.Exception: Apparent connection leak detected
  spring.datasource.hikari.leak-detection-threshold=240000

클일일세... https://docs.openkm.com/kcenter/view/okmkb/warning-in-update-or-creation-stage-javalangexception-apparent-connection-leak-detected.html

https://do-study.tistory.com/97

 

728x90

 

package com.today10sec.diary.etc;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.transaction.Transactional;

@Component
@Transactional
public class JpaRunner implements ApplicationRunner {

    @PersistenceContext
    EntityManager entityManager;

    @Autowired
    Environment environment;

    @Override
    public void run(ApplicationArguments args) throws Exception {

    }
}
728x90
쿼리 만들기 스프링 데이터 저장소의 메소드 이름으로 쿼리 만드는 방법
메소드 이름을 분석해서 쿼리 만들기 (CREATE)
미리 정의해 둔 쿼리 찾아 사용하기 (USE_DECLARED_QUERY)
미리 정의한 쿼리 찾아보고 없으면 만들기 (CREATE_IF_NOT_FOUND)  >> 기본값

@SpringBootApplication
//@EnableJpaRepositories(queryLookupStrategy = QueryLookupStrategy.Key.CREATE)
@EnableJpaRepositories(queryLookupStrategy = QueryLookupStrategy.Key.CREATE_IF_NOT_FOUND)
//@EnableJpaRepositories(queryLookupStrategy = QueryLookupStrategy.Key.USE_DECLARED_QUERY)
public class DiaryApplication {

리턴타입 
{접두어}{도입부}By{프로퍼티 표현식}(조건식)[(And|Or){프로퍼티 표현식}(조건식)]{정렬 조건} (매개변수)

 
리턴타입 E, Optional<E>, List<E>, Page<E>, Slice<E> Stream<E>
{접두어} Find, Get, Query, Count
{도입부} Distinct, First(N), Top(N)
By  
{프로퍼티 표현식} Person Address ZipCode => findPersonByAddress_ZipCode()
{조건식} IgnoreCase, Between, LessThan, GreaterThan, Like, Contains
[(And|Or)]  
{프로퍼티 표현식}  
{조건식}  
{정렬조건} OrderBy프로퍼티Asc|Desc
(매개변수) Pageable, solt
 
쿼리 찾는 방법 메소드 이름으로 쿼리를 표현하기 힘든 경우에 사용.
저장소 기술에 따라 다름.
JPA: @Query @NamedQuery
@Query  @Query(SELECT c FROM Comment AS C" nativeQuery=true)
@Async 비동기 쿼리
@Async Future<User> findByFirstname(String firstname);  
@Async CompletableFuture<User> findOneByFirstname(String firstname);
@Async ListenableFuture<User> findOneByLastname(String lastname); 
- 해당 메소드를 스프링 TaskExecutor에 전달해서 별도의 쓰레드에서 실행함.
- Reactive랑은 다른 것임

권장하지 않는 이유
테스트 코드 작성이 어려움.
코드 복잡도 증가.
성능상 이득이 없음. 
DB 부하는 결국 같고.
메인 쓰레드 대신 백드라운드 쓰레드가 일하는 정도의 차이.
단, 백그라운드로 실행하고 결과를 받을 필요가 없는 작업이라면 @Async를 사용해서 응답 속도를 향상 시킬 수는 있다.

커스텀 리포지토리 쿼리 메소드(쿼리 생성과 쿼리 찾아쓰기)로 해결이 되지 않는 경우 직접 코딩으로 구현 가능.
스프링 데이터 리포지토리 인터페이스에 기능 추가.
스프링 데이터 리포지토리 기본 기능 덮어쓰기 가능.
구현 방법
커스텀 리포지토리 인터페이스 정의 
인터페이스 구현 클래스 만들기 (기본 접미어는 Impl)
엔티티 리포지토리에 커스텀 리포지토리 인터페이스 추가

기능 추가하기

기본 기능 덮어쓰기

접미어 설정하기
기본 리포지토리 커스터마이징 모든 리포지토리에 공통적으로 추가하고 싶은 기능이 있거나 덮어쓰고 싶은 기본 기능이 있다면 

JpaRepository를 상속 받는 인터페이스 정의
@NoRepositoryBean
기본 구현체를 상속 받는 커스텀 구현체 만들기
@EnableJpaRepositories에 설정
repositoryBaseClass

@NoRepositoryBean public interface MyRepository<T, ID extends Serializable> extends JpaRepository<T, ID> { boolean contains(T entity); }
도메인 이벤트 도메인 관련 이벤트를 발생시키기

스프링 프레임워크의 이벤트 관련 기능
https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#context-functionality-events
ApplicationContext extends ApplicationEventPublisher
이벤트: extends ApplicationEvent
리스너
  - implements ApplicationListener  E extends ApplicationEvent
  - @EventListener

스프링 데이터의 도메인 이벤트 Publisher
-@DomainEvents
-@AfterDomainEventPublication
-extends AbstractAggregateRoot<E>
-현재는 save() 할 때만 발생 합니다.

QueryDSL  

Distinct 분명한 : 중복없이 불러옴.

alt F7 사용된 위치 탐색

ctrl + alt + B  자세하게 추적. 

Pageable -> paging 으로 받아야 누락없음. 

             -> sorting 관련 파라메터도 넣을수 있음. 

resolveQuery 처리 : 쿼리 > 프로시져 > 네임드 쿼리 

like sql 키워드  변수 사용불가. 혹은 별명처리.. 

더보기
public final class JpaQueryLookupStrategy {

중략
        protected RepositoryQuery resolveQuery(JpaQueryMethod method, EntityManager em, NamedQueries namedQueries) {
            RepositoryQuery query = JpaQueryFactory.INSTANCE.fromQueryAnnotation(method, em, this.evaluationContextProvider);
            if (null != query) {
                return query;
            } else {
                RepositoryQuery query = JpaQueryFactory.INSTANCE.fromProcedureAnnotation(method, em);
                if (null != query) {
                    return query;
                } else {
                    String name = method.getNamedQueryName();
                    if (namedQueries.hasQuery(name)) {
                        return JpaQueryFactory.INSTANCE.fromMethodWithQueryString(method, em, namedQueries.getQuery(name), this.evaluationContextProvider);
                    } else {
                        RepositoryQuery query = NamedQuery.lookupFrom(method, em);
                        if (null != query) {
                            return query;
                        } else {
                            throw new IllegalStateException(String.format("Did neither find a NamedQuery nor an annotated query for method %s!", method));
                        }
                    }
                }
            }
        }
    }

쿼리관련 참고

더보기

기본 예제

 

List<Person> findByEmailAddressAndLastname(EmailAddress emailAddress, String lastname);

// distinct

List<Person> findDistinctPeopleByLastnameOrFirstname(String lastname, String firstname);

List<Person> findPeopleDistinctByLastnameOrFirstname(String lastname, String firstname);

// ignoring case

List<Person> findByLastnameIgnoreCase(String lastname);

// ignoring case

List<Person> findByLastnameAndFirstnameAllIgnoreCase(String lastname, String firstname);

 

정렬

 

List<Person> findByLastnameOrderByFirstnameAsc(String lastname);

List<Person> findByLastnameOrderByFirstnameDesc(String lastname);

 

페이징

 

Page<User> findByLastname(String lastname, Pageable pageable);

Slice<User> findByLastname(String lastname, Pageable pageable);

List<User> findByLastname(String lastname, Sort sort);

List<User> findByLastname(String lastname, Pageable pageable);

 

스트리밍

 

Stream<User> readAllByFirstnameNotNull();

  • try-with-resource 사용할 것. (Stream을 다 쓴다음에 close() 해야 함)

 

728x90
스프링 데이터 Common Repository
CrudRepository
PagingAndSortingRepository
스프링 데이터 JPA JpaRepository -> PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T>
CrudRepository PagingAndSortingRepository -> CrudRepository

<S extends T> S save(S var1);
<S extends T> Iterable<S> saveAll(Iterable<S> var1);
Optional<T> findById(ID var1);
boolean existsById(ID var1);
Iterable<T> findAll();
Iterable<T> findAllById(Iterable<ID> var1);
long count();
void deleteById(ID var1);
void delete(T var1);
void deleteAll(Iterable<? extends T> var1);
void deleteAll();
@Rollback(false) 롤백안함
트렌젝션  + 테스트 -->  하이버네이트가 롤백할 커리여서 테스트에서 insert 안나라감.
PagingAndSortingRepository public interface Page<T> extends Slice<T> {
    static <T> Page<T> empty() { 
        return empty(Pageable.unpaged());
    }
    static <T> Page<T> empty(Pageable pageable) {
        return new PageImpl(Collections.emptyList(), pageable, 0L);
    }
    int getTotalPages();
    long getTotalElements();
    <U> Page<U> map(Function<? super T, ? extends U> var1);
}
테스트용 h2 DB설정  1. h2 test 추가. 
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <scope>test</scope>
</dependency>

2. @DataJpaTest 추가. 
@ExtendWith(SpringExtension.class) 
@DataJpaTest
class DiaryRepositoryTest {
Repository 인터페이스 정의 특정레포지터리 제작
@RepositoryDefinition(domainClass = Study.class, idClass = Integer.class)
public interface PersonalRepository {
    Study save(Study study);
    List<Study> findAll();
}
@NoRepositoryBean @NoRepositoryBean  > 레퍼지토리아님. 상속받아 사용. 
public interface MyRepository<T, ID extends Serializable> extends Repository<T, ID> {    
    <E extends T> E save(E entity);
    
    List<T> findAll();

}
Null 처리  리턴값 1개일떄 
java 8 Optional
<E extends T> Optional<E> findByID(ID id);
spring 5
@NonNullApi, @NonNull, @Nullable.
@Nullable
<E extends T> E save(E entity);     
런타임 체크 지원 함.
JSR 305 애노테이션을 메타 애노테이션으로 가지고 있음. (IDE 및 빌드 툴 지원)
인텔리제이 : Build, Execution, Deployment > Compiler
> Add runtime assertion for notnull-annotated methods and parameters
> Configure annotations 클릭 > 위에박스 + nullable 스프링추가, 아랫박스 NoneNull 추가
 

 >> 반영

 

@NonNullApi
package com.today10sec.diary.repository;;
Optional 단일값 받을 때 추천. .. 최근추세  == null  안씀... 
Optional<Diary> byId= diaryRepository.findById(100);
assertThat(byId).isEmpty();
List의 경우 스프링데이터에서 빈 컬렉션이 나옴
isEmpty(); 체크만. 
 쿼리 만들기 개요.   

Paging and sorting repository , crudRepository

더보기
package com.today10sec.diary.repository;

import com.today10sec.diary.model.Diary;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.junit.jupiter.SpringExtension;

import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;

@ExtendWith(SpringExtension.class)
@DataJpaTest
class DiaryRepositoryTest {

    @Autowired
    DiaryRepository diaryRepository;

    @Test
    @Rollback(false)
    public void crud_Repository(){
        //Given
        Diary diary = new Diary();
        diary.setName("aaaaa");
        assertThat(diary.getId()).isNull();
        //when
        Diary newDiary = diaryRepository.save(diary);
        //then
        assertThat(newDiary.getId()).isNotNull();
        //when
        List<Diary> diaries = diaryRepository.findAll();  //이것만 JPA REpository
        //then
        assertThat(diaries.size()).isEqualTo(1);
        assertThat(diaries).contains(newDiary);

    }

    @Test
    @Rollback(false)
    public void PagingAndSorting_Repository(){
        //Given
        Diary diary = new Diary();
        diary.setName("aaaaa");
        Diary newDiary = diaryRepository.save(diary);
        //when
        Page<Diary> page =diaryRepository.findAll(PageRequest.of(0, 10));
        //then
        assertThat(page.getTotalElements()).isEqualTo(1);
        assertThat(page.getNumber()).isEqualTo(0);
        assertThat(page.getSize()).isEqualTo(10);
        assertThat(page.getNumberOfElements()).isEqualTo(1);

        //when
        page = diaryRepository.findByNameContains("aaaaa", PageRequest.of(0,10));
        //then
        assertThat(page.getTotalElements()).isEqualTo(1);
        assertThat(page.getNumber()).isEqualTo(0);
        assertThat(page.getSize()).isEqualTo(10);
        assertThat(page.getNumberOfElements()).isEqualTo(1);
    }



}
728x90

 

JpaRepository

JpaRepository<Entity, Id> 인터페이스
매직인터페이스 
@Repository가 없어도 빈으로 등록해 줌

public interface DiaryRepository extends JpaRepository<Diary, Integer> { }
@EnableJpaRepositories (스프링부트에서 지원, 생략)  컨피규레이션 위에 올림. 
스프링부트 시작은 @Import(JpaRepositoriesRegistrar.class)   
핵심은 ImportBeanDefinitionRegistrar 인터페이스 : 스프링프레임워크 
: 빈을 프로그래밍을 통해 등록가능. 
public class DiaryRegistrar implements ImportBeanDefinitionRegistrar {
    @Override public void registerBeanDefinitions(AnnotationMetadata  importingClassMetadata, BeanDefinitionRegistry registry) {
        GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
        beanDefinition.setBeanClass(Diary.class);         
        beanDefinition.getPropertyValues().add("name","오잉");
        registry.registerBeanDefinition("day", beanDefinition); }
}
jdbc  
패러다임 불일치 릴레이션 - java
단위, 관계표현, 식별자 , 상속관계표현 => ORM 해결 매핑 메타데이터 기반. 
생산성, 유지보수성, 성능.  
jpa 주의 반드시 발생하는 SQL 확인
? 출력
logging.level.org.hibernate.SQL=debug logging.level.org.hibernate.type.descriptor.sql=trace

binding parameter [2] as [VARCHAR] - [null]
binding parameter [3] as [TIMESTAMP] - [null]
binding parameter [4] as [VARCHAR] - [오늘이다.]
binding parameter [5] as [BOOLEAN] - [true]
binding parameter [6] as [INTEGER] - [3]
스프링 데이터 SQL & NoSQL 저장소, 지원프로젝트의 묶음

spring.io/projects/spring-data

스프링 데이터 모듈 : 

스프링데이터 Common : 여러 저장소 지원 프로젝트의 공통기능 제공
스프링데이터 REST: 저장소의 데이터를 하이퍼미디어 기반 Http 리소스로 REST API 제공
---------------------------
스프링데이터 JPA      : 스프링 데이터 Common 이 제공하는 기능에 jpa 관련 기능 추가. 
스프링데이터 JDBC
스프링데이터 KeyValue
---------------------------
스프링데이터 MongoDB
스프링데이터 Redis.......

 

non-invasive 논인베이시브 비침투적. 스프링 코드를 최대한 노출 시키지 않겠다. 

 

* DB 조회 변경 과정

더보기
@Repository @Transactional
public class AccountRepository {
    @PersistenceContext EntityManager entityManager;
    public Account add(Account account){
     entityManager.persist(account);
     return account;
 }
  -> @Repository @Transactional
public class AccountRepository extends GenericRepository<Account, Long> {
-> JPA package com.today10sec.diary.repository;
import com.today10sec.diary.model.Diary;
import org.springframework.data.jpa.repository.JpaRepository;

public interface DiaryRepository extends JpaRepository<Diary, Integer> {
}

package com.today10sec.diary.etc;

import com.today10sec.diary.model.Diary;
import com.today10sec.diary.repository.DiaryRepository;
import org.hibernate.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.transaction.Transactional;
import java.util.HashSet;
import java.util.Set;

@Component
@Transactional
public class JpaRunner implements ApplicationRunner {

    @PersistenceContext
    EntityManager entityManager;

    @Autowired
    DiaryRepository diaryRepository;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        Diary diary = new Diary();
        diary.setUse(true);
        diary.setName("오늘이다.");

        Session session = entityManager.unwrap(Session.class);
        session.save(diary);

        diaryRepository.findAll().forEach(diary1 -> System.out.println(diary1.getName()) );

    }
}
728x90

ERROR1.  

error creating bean with name 'entitymanagerfactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/hibernatejpaconfiguration.class]: invocation of init method failed; nested exception is org.hibernate.service.spi.serviceexception: unable to create requested service [org.hibernate.engine.jdbc.env.spi.jdbcenvironment]

두번째 서버 올렸을 때 postgresql 서버가 내려가있다는 메시지 와서 도커 재시작 해결. 

 


JPA 에서 EntityManager   

@Entity “엔티티”는 객체 세상 릴레이션. 
보통 클래스와 같은 이름을 사용하기 때문에 값을 변경하지 않음.
엔티티의 이름은 JQL에서 쓰임.
@Entity(name="myAccount")
@Table
public class Account
...기존 postgres 에서 user 가 키워드여서 user 테이블 사용불가 syntax에러 or. Entity 변경 사용  
@Table “릴레이션" 세상에서 엔티티
@Entity의 이름이 default .
테이블의 이름은 SQL에서 쓰임.
@Id 엔티티의 주키를 맵핑할 때 사용.
자바의 모든 primitive 타입과 그 랩퍼 타입을 사용할 수 있음_ 임의값과 구별과능 
-Date랑 BigDecimal, BigInteger도 사용 가능.
복합키를 만드는 맵핑하는 방법도 있지만 그건 논외로..
@GeneratedValue 주키의 생성 방법을 맵핑하는 애노테이션
생성 전략과 생성기를 설정할 수 있다.
- 기본 전략은 AUTO: DB 에따라 기본값 다름 postgres 시퀀스(생성전략다름, 명시가능 strategy)
-
TABLE, SEQUENCE, IDENTITY 중 하나.
@Column unique
nullable    : default true
length
columnDefinition
@Temporal 날짜데이터
현재 JPA 2.1까지는 Date와 Calendar만 지원.
@Transient 데이터 컬럼으로 맵핑하고 싶지 않은 멤버 변수에 사용.
application.properties spring.jpa.show-sql=true

spring.jpa.properties.hibernate.format_sql=true   // 보기좋게 포멧

Value 타입 종류 기본 : String, Date, Boolean..
Composite Value 타입
Collection Value 타입- 기본타입 콜렉션, 컴포짓 타입 콜렉션
<
Composite Value 타입 맵핑 @Embeddable
@Embedded
@AttributeOverrides
@AttributeOverride
Entity 타입
Value 타입
@Entity
public class Account{    >> 엔티티타입
    @Embedded
    private Address address ;      >>> 벨류타입.........Account 엔티티 통해서 접근. 
    @Embedded
    @Attribute
    private Address homeAddress ;
}
@Embeddable @Embeddable   > 새로운 타입값 지정. 
public class Address{
    private String street;
    private String etc;
}

    @Embedded
    @AttributeOverrides({   >> 새로운 타입값에 일부 변경
            @AttributeOverride(name = "etc", column = @Column(name = "etc2"))
    })
    private Address address;

1대다 단방향_@ManyToOne public class Study {
    @ManyToOne
    private Account one;   >> Study 가 주인._ 관계 값을 정의 위치. 
1대다 단방향
_@OneToMany
many 로 끝나야 컬렉션. >> account_studies 에 관계값 정의 
public class Account {
    @OneToMany
    private Set<Study> studies;

1대다 양방향 public class Account {
    @OneToMany(mappedBy = "owner")
    private Set<Study> studies = new HashSet<>();
public class Study {
    @ManyToOne                             >>> 이쪽에 관계값 정의 
    private Account owner;

소스작성
account.getStudies().add(study);
study.setOwner(account);
Session session = entityManager.unwrap(Session.class);
session.save(study);
session.save(account);
엔티티 상태 변화 -new Object()->  Transient: JPA가 모르는 상태

(from Transient )-session.save()-> Persistent: JPA가 관리중 상태
(fromDetached)-session.update()
                        session.marge();
                        session.saveOrUpdate()-> Persistent
Persistent: (1차 캐시, Dirty Checking, Write Behind, ...) : 변경사항 계속 모니터링
session.get()
session.load()
Query.Iterate()

(from Persistent) ->session.evict();  
                           session.clear();

                            session.close(); ->Detached: JPA가 더이상 관리하지 않는 상태.



-session.delete();->Removed: JPA가 관리하긴 하지만 삭제하기로 한 상태.
Cascade - @ManyToOne 엔티티 상태값 전이: 부모자식관계.에 쓰는 것을 추천.   
class Post{
@OneToMany(mappedBy = "post", cascade = CascadeType.PERSIST)
 private Comment comment;
}
post만 저장해도 comment 도 같이 저장.
cascade = {CascadeType.PERSIST, CascadeType.REMOVE}) 
cascade = CascadeType.All
Dirty Checking 상태변경 검사
(영속-managed-상태, Transaction 엔티티변경T@Transactional, Entity Transaction.  경우)
1) 엔티티 메니저에서 수정에 해당하는 부분에 더티 체킹 지원
2) 엔티티 데이터 변경부분 체크 DB 반영 
* 데이터 변경 시점: transaction commit, Entitymanager flush, jpql 사용시점
import org.hibernate.Session
Session session = entityManager.unwrap(Session.class);//jpa감싸는 hibernate api 그대로이용
session.save(study); session.save(account); 

Account k = session.load(Account.class, account.getId());   // null 일때 예외 
// session.get(Post.calss, 4l);  null 일 때null 가져옴

k.setUsername("ddd");
k.setUsername("eee");
System.out.println(k.getUsername());
Write Behind
DB 엔티티 변경사항을 최대한 필요한 시점에 반영하는것.
@DynamicUpdate 변경된 필드만 저장
Fetch *성능영향 연관 관계의 엔티티를 어떻게 가져올 것이냐... 지금 (Eager)? 나중에(Lazy)?
@OneToMany의 기본값은 Lazy
post 조회시 comment 를 가져오지 않음
@ManyToOne의 기본값은 Eager
comment 조회시 post 를 가져옴. 
Query JPQL, Criteria, Native Query 가 있다. 
JPQL (= HQL)  Java Persistence Query Language / Hivernate Query Language
데이터베이스 테이블이 아닌 엔티티 객체 모델 기반으로 쿼리 작성
JPA 하이버네이트가 해당쿼리 SQL로 변환 실행 , 타입세이프 하지 안음
TypedQuery<Post> query                                     // 지정해준 타입으로 나옴
= entityManager.
createQuery("SELECT p FROM Post As p", Post.class);  
List<Post> posts = query.getResultList();
https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html#hql
Criteria 타입 세이프 관리
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery criteria = builder.createQuery(Post.class);
Root root = criteria.from(Post.class);
criteria.select(root);
List posts = entityManager.createQuery(criteria).getResultList();
Native Query SQL 쿼리 실행
List<Post> posts = entityManager .createNativeQuery("SELECT * FROM Post", Post.class) .getResultList();

Composite    합성의 ... 컴포짓한 벨류타입. 

Transient   일시적인, 순간적인, 단기체류의  트랜지언트 

evict         쫓아내다. 이빅트

Detached   분리됨

캐쉬가 되었다. - PersistentContext 에 넣음. 

영향이 있는 테이블만 삭제하고 다시만듬

Model . getter setter 안만들어도 됨. 

Eager 열심인

Lazy  게으른

Criteria  criterion기준 복수  크리테리아. 

728x90

스프링 코어

IoC 컨테이너와 빈

Environment, MessageSource, ApplicationEventPublisher, ResourceLoader

Validation, 데이터 바인딩.

SpEL, AOP,Null-safety

 

 

 

 

 

 

 

 

728x90

스프링목차

SpEL 스브링EL
객체 그래프를 조회, 조작하는 기능
Unified EL과 비슷하지만, 메소드 호출 지원, 문자열템플릿 기능도 제공. 
OGNL MVEL, JBOss EL 등 자바에서 사용할 수 있는 여러 EL 이 있지만 , SpEL은 모든 스프링 프로젝트 전반에 걸처 사용할 EL로 만듬.  스프링 3.0 부터. 
ExpressionParser parser = new SpelExpressionParser() 
StandardEvaluationContext context = new StandardEvaluationContext(bean) >> 함수. 가능. 
Expression expression = parser.parseExpression(“SpEL 표현식”)
String value = expression.getvalue(context, String.class)

#{“표현식"}  "#{1+1}" 
${“프로퍼티"}
docs.spring.io/spring-framework/docs/current/reference/html/core.html#expressions-language-ref

@Value 애노테이션
@ConditionalOnExpression 애노테이션
스프링 시큐리티
 - 메소드 시큐리티, @PreAuthorize, @PostAuthorize, @PreFilter, @PostFilter
  - XML 인터셉터 URL 설정
스프링 데이터  : @Query 애노테이션
Thymeleaf  : blog.outsider.ne.kr/997
docs.spring.io/spring-framework/docs/current/reference/html/core.html#expressions-language-ref
AOP Aspect-oriendted Programming  :  OOP 보완, 흩어진 Aspect를 모듈화 
스프링은 AspectJ 연동, 혹은 따로구현. 
OOP 에 나타난... 흩어진 관심(비슷한코드)사 : Crosscutting Concerns : 유지보수 어려움. 
ClassA {    1,     2,     3 }
ClassB {    1,     3,     3 }
ClassC {    1,     2}
>> AOP 적용
ClassA   , ClassB,  ClassC                                   
AspectX : A, B, C          1소스 부분
AspectY: A, C              2소스 부분
AspectZ: A, B              3소스부분
   PointCut           +    advice            = Aspect
  어디에 적용              해야할 일            하나의 모듈
Target 적용대상  ClassA   , ClassB,  ClassC
Join point 합류 지점 ex) 생성자 호출전, 호출때, 필드 호출전, 
그중에 더 자세한내용은 PointCut
AOP 적용방법 - 컴파일(java > .class)- 
- 로드타임 위빙(컴파일 후)-                                                        >> AspectJ  경우에 따라
- 런타임(빈을 만들때 A타입 프록시 빈을 만듬... 프록시 실행후 A실행)   >> 스프링 AOP 주로
빈만들때 약간의 성능 부하, 다양한 기능적용(AspectJ)
AOP 구현체  en.wikipedia.org/wiki/Aspect-oriented_programming
Java AOP 구현체 AspectJ  : 기능 다양
스프링 AOP  : 국한적. 
프록시 패턴 Client    임의 인터페이스
                      ↑
            프록시   →   임의 클래스
프록시 객체가 실제 사용할 클래스를 감싸서 프로그램실행 : 접근제어, 부가기능 추가. 
문제점
 매번 프록시 클래스를 작성해야 하는가?
 여러 클래스 여러 메소드에 적용하려면?
 객체들 관계도 복잡하고...
스프링AOP 프록시 기반 AOP 구현체
스프링 빈에만 AOP를 적용할 수 있다.
모든 AOP 기능을 제공하는 것이 목적이 아니라, 스프링 IoC와 연동하여 엔터프라이즈
애플리케이션에서 가장 흔한 문제에 대한 해결책을 제공하는 것이 목적.

스프링 IoC 컨테이너가 제공하는 기반 시설과 Dynamic 프록시를 사용하여 여러
복잡한 문제 해결.
동적 프록시: 동적으로 프록시 객체 생성하는 방법
- 자바가 제공하는 방법은 인터페이스 기반 프록시 생성.
- CGlib은 클래스 기반 프록시도 지원.
스프링 IoC: 기존 빈을 대체하는 동적 프록시 빈을 만들어 등록 시켜준다.
- 클라이언트 코드 변경 없음.
- AbstractAutoProxyCreator implements BeanPostProcessor
@Aspect 의존성 추가. spring-boot-starter-aop
@Component
@Aspect
public class PerfAspect{
     //@Around("execution( * com.example.demo.*.EventService.*(..))") //포인트컷 표현식.
     @Around("@annotation(PerfLogging)")
     public Object logPerf(ProceedingJoinPoint pip)throws Throwable{
         Object reVal = pip.proceed();
         return reVal;
     }
}
@Pointcut @Pointcut(표현식)
- execution
- @annotation
- bean
포인트컷 조합
-&&, ||, !
어드바이스 정의 @Before
@AfterReturning
@AfterThrowing
@Around
Null-safety 스프링 프레임워크 5에 추가된 Null 관련 애노테이션
@NonNull                                     >>매개변수 널허용안됨.
@Nullable
@NonNullApi (패키지 레벨 설정)
@NonNullFields (패키지 레벨 설정)
목적 : (툴의 지원을 받아) 컴파일 시점에 최대한 NullPointerException을 방지하는 것
 컴파일러 옵션.  configuration  스프링어노테이션 추가해야 쓸수 있음. 스프링데이터쪽에서 쓴다고함
패키지 레벨... NonNull.. 허용하는대만  Nullable 사용. 

 

@Retention(RetentionPolicy.CLASS)// 언제까지 유지할것인가.

docs.spring.io/spring-framework/docs/current/reference/html/core.html#aop-pointcuts

 

 

프록시 패턴구현_ 동적, 어노테이션

더보기
package com.example.demo.event;

import java.lang.annotation.*;
/**
 * 이 어노테이션은 성릉을 로깅해줍니다.. 
 */
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.CLASS)// 언제까지 유지할것인가. 명시.. 기본값
public @interface PerfLogging {
}
package com.example.demo.event;

import org.springframework.stereotype.Service;

@Service
public class SimpleEventService implements EventService {
    @Override
    @PerfLogging
    public void createEvent() {
        System.out.println("Created an event");
    }

    @Override
    @PerfLogging
    public void publishEvent() {
        System.out.println("published an event");
    }

    @Override
    public void deleteEvent(){
        System.out.println("Delete an event");
    }
}
package com.example.demo.event;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class PerfAspect{

    //@Around("execution( * com.example.demo.*.EventService.*(..))")  //포인트컷 표현식.
    @Around("@annotation(PerfLogging)")
    public Object logPerf(ProceedingJoinPoint pip)throws Throwable{
        long begin = System.currentTimeMillis();
        Object reVal = pip.proceed();
        System.out.println(System.currentTimeMillis()-begin);
        return reVal;
    }
}

 

 

프록시 패턴구현 _ 기본이해 

더보기
package com.example.demo.event;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;

@Primary
@Service
public class ProxySimpleEventService implements EventService{

    @Autowired
    SimpleEventService simpleEventService;

    @Override
    public void createEvent(){
        long begin = System.currentTimeMillis();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        simpleEventService.createEvent();
        System.out.println(System.currentTimeMillis()-begin);
    }

    @Override
    public void publishEvent(){
        long begin = System.currentTimeMillis();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        simpleEventService.publishEvent();
        System.out.println(System.currentTimeMillis()-begin);
    }

    @Override
    public void deleteEvent(){
        simpleEventService.deleteEvent();
    }
}
package com.example.demo.event;

public interface EventService{
    void createEvent();
    void publishEvent();
    void deleteEvent();
}
package com.example.demo.event;

import org.springframework.stereotype.Service;

@Service
public class SimpleEventService implements EventService{
    @Override
    public void createEvent(){
        System.out.println("Created an event");
    }

    @Override
    public void publishEvent(){
        System.out.println("published an event");
    }

    @Override
    public void deleteEvent(){
        System.out.println("Delete an event");
    }
}

 

 

package com.example.demo.event;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

@Component
public class AppRunner implements ApplicationRunner {

    EventService eventService;

    @Override
    public void run(ApplicationArguments args) throws Exception {

        eventService.createEvent();
        eventService.publishEvent();
        eventService.deleteEvent();

    }

    @Autowired
    public void setEventService(EventService eventService) {
        this.eventService = eventService;
    }
}

.

추가 스프링부트 웹 안쓸때

SpringApplication app = new SpringApplication(DemoApplication.class);
        app.setWebApplicationType(WebApplicationType.NONE);
        app.run(args);
728x90

import static 단축키 

1.  settings > Editor > General > Auto Import

Add unambiguous imports on the fly 

Optimize imports on the fly (for current project)

두개 체크 후 저장

2. 

그리고 status() 뒤  alt + enter 로사용. **() 뒤에서 알트엔터

출처 :hjjungdev.tistory.com/102


스프링목차

스프링 validator org.springframework.validation.Validator;

객체 검증 인터페이스. 
- supports : 검증할수 있는 클래스인지 확인. 
public boolean supports(Class<?> clazz){
    return Event.class.equals(clazz);
}
- validate
public void validate(Object target Errors errors){
    ValidationUtils.rejectIfEmptyOrWhitespace(error, "분별 키","공통 키값", "없을때 메시지 ");
    Event event = (Event)target;
    if(event.getTitle()==null){
         errors.reject("필드", "메시지");...
     }
}

--소스
eventValidator.validate(event, errors);
event.hasErros()
error.getAllErrors().forEach(e->{ Arrays.stream(e.getCodes()).forEach(System.out::println)})
- 스프링부트 2.0.5 이상 스프링 LocalValidatorFactoryBean 자동등록.   - 
@Validator validator;
빈에 추가. 
@NotNull @Min(0) @Size(min=0) @NotEmpty(message = "{email.notempty}")
>> 기본메시지가 출력.  
Bean Validation javax.xml.validation.Validator;
JAVA EE 기능.
beanvalidation.org/
데이터 바인딩 프로퍼티 값을 타겟 객체에 설정하는 기능
사용자 관점 : 사용자 입력값을 애플리케이션 도메인 모델에 동적으로 변환해 넣어주는 기능
해석하자면, 입력값은 대부분 문자열, 그값을 객체가 가지고 있는 타입으로 변환해서 넣어주는 기능. 
PropertyEditor 스프링 3.0 이전까지 DataBinder가 변환 작업 사용하는 인터페이스. 
쓰레드 세이프하지 않음. -상태정보 저장하고 있음, 빈으로 등록해서.. 쓰면... 안됨. 
Object String 간의 변환만 할수 있어 사용범위가 제한적임
public class EventPropertyEditor extends PropertyEditorSupport {
>> 후에 Converter 사용. 
Converter S 타입을 T 타입으로 변환할 수 있는 매우 일반적인 변환기.
상태 정보 없음 == Stateless == 쓰레드세이프
ConverterRegistry에 등록해서 사용
@Component
public class StringToEventConverter implements Converter<String, Event> {
    @Override
    public Event convert(String source) {
        Event event = new Event();
        event.setId(Integer.parseInt(source));
        return event; }
}

public class WebConfig implements WebMvcConfigurer {  >>빈 등록시 부트는 등록안해도됨
    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addConverter(new StringToEventConverter());
    }
}
기본적인것은 자동변환..해줌. 
 Formatter PropertyEditor 대체제
Object와 String 간의 변환을 담당한다.
문자열을 Locale에 따라 다국화하는 기능도 제공한다. (optional)
FormatterRegistry에 등록해서 사용
@Component
public class EventFormatter implements Formatter<Event> {
    @Autowired
    MessageSource messagesource;                                  >> bean 등록 가능. 

    @Override
    public Event parse(String text, Locale locale) throws ParseException {
        Event event = new Event();
        int id = Integer.parseInt(text);
        event.setId(id); return event;
    }
    @Override
    public String print(Event object, Locale locale) {
        return object.getId().toString();
    }
}

public class WebConfig implements WebMvcConfigurer {>>빈 등록시 부트는 등록안해도됨
    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addFormatter(new EventFomatter());
    }
}
ConversionService 실제 변환 작업은 이 인터페이스를 통해서 쓰레드-세이프하게 사용할 수 있음.
스프링 MVC, 빈 (value) 설정, SpEL에서 사용한다.
 Default
Formatting
ConversionService
; FormatterRegistry,ConversionService상속. 
- FormatterRegistry(포멧터등록) <-  컨퍼터 ConverterRegistry(컨버터등록) 상속. 

- 여러 기본 컴버터와 포매터 등록 해 줌.
JPA 엔티티에 컨버터가 들어있음. 들어있는
컨버터 전부 보는방법. ConversionService  출력 
스프링 부트 - 웹 애플리케이션인 경우에 DefaultFormattingConversionSerivce를 상속하여 만든
WebConversionService를 빈으로 등록해 준다.
- Formatter와 Converter 빈을 찾아 자동으로 등록해 준다.

 

PropertyEditor

더보기
package com.example.demo;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.MockMvc;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@ExtendWith(SpringExtension.class)
@WebMvcTest
class DemoControllerTest {
    @Autowired
    MockMvc mockMvc;

    @Test
    void getTest() throws Exception {
        mockMvc.perform(get("/event/1"))
                .andExpect(status().isOk())
                .andExpect(content().string("1"));

    }
}

 

package com.example.demo;

import com.example.demo.event.Event;
import com.example.demo.event.EventEditor;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class DemoController {

    @InitBinder
    public void init(WebDataBinder webDataBinder){
        webDataBinder.registerCustomEditor(Event.class, new EventEditor());
    }

    @GetMapping("/event/{event}")
    public String getEvent(@PathVariable Event event){
        System.out.println(event);
        return event.getId().toString();
    }


}
package com.example.demo.event;

public class Event {
    private Integer id;

    public Event(Integer id) {
        this.id = id;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }
}
package com.example.demo.event;

import java.beans.PropertyEditorSupport;

public class EventEditor extends PropertyEditorSupport {
    @Override
    public String getAsText() {
        Event evnet = (Event)getValue();
        return evnet.getId().toString();
    }

    @Override
    public void setAsText(String text) throws IllegalArgumentException {
        setValue(new Event(Integer.parseInt(text)));

    }
}
728x90

스프링목차

Environment

프로파일과 프로퍼티를 다루는 인터페이스

 

Environment ApplicationContext extends EnvironmentCapable
profile 활성화여부 확인 및 설정
프로퍼티 소스 설정 및 프로퍼티 값 가져오기
profile Environment 에서 프로파일 확인 및설정. 
-클래스-
@Configuration @Profile(“test”)
@Component @Profile(“test”)
-메소드- 
@Bean @Profile(“test”)

사용 설정추가. 
-Dspring.profiles.avtive=”test,A,B,...”
테스트 ; ActiveProfiles

설정방법
! (not)
& (and)
 | (or)
Property StandardServletEnvironment의 우선순위
- ServletConfig 매개변수
- ServletContext 매개변수
- JNDI (java:comp/env/)
- JVM 시스템 프로퍼티 (-Dapp.key=”value”)   enviroment.getProperty("app.key");
- JVM 시스템 환경 변수 (운영 체제 환경 변수)
@PropertySource Environment를 통해 프로퍼티 추가하는 방법
@PropertySource("classpath:/app.properties") >> 스프링 부트 어플리케이션 지정한 클래스에 추가
>> enviroment에 추가됨. 
스프링 부트 프로퍼티 기본 프로퍼티 소스 지원 (application.properties)
프로파일까지 고려한 계층형 프로퍼티 우선 순위 제공 (yml)
MessageSource 국제화(i18n) 기능 제공하는 인터페이스
ApplicationContext extends MessageSource
message.properties messages_ko_kr.properties   >> 스프링 프로퍼티스. 
@Bean
public MessageSource messageSource() {
var messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasename("classpath:/messages");
messageSource.setDefaultEncoding("UTF-8");
messageSource.setCacheSeconds(3);
return messageSource;
}
운영중 빌드해주면.. 바로 반영. 
ApplicationEventPublisher 이벤트 프로그래밍에 필요한 인터페이스 제공. 옵저버 패턴 구현체.
ApplicationContext extends ApplicationEventPublisher
publishEvent(ApplicationEvent event)
이벤트 처리하는 방법
● ApplicationListener<이벤트> 구현한 클래스 만들어서 빈으로 등록하기.
● 스프링 4.2 부터는 @EventListener를 사용해서 빈의 메소드에 사용할 수 있다.
● 기본적으로는 synchronized.
● 순서를 정하고 싶다면 @Order와 함께 사용.
● 비동기적으로 실행하고 싶다면 @Async와 함께 사용.
스프링이 제공하는 기본 이벤트
● ContextRefreshedEvent: ApplicationContext를 초기화 했더나 리프래시 했을 때 발생.
● ContextStartedEvent: ApplicationContext를 start()하여 라이프사이클 빈들이 시작
신호를 받은 시점에 발생.
● ContextStoppedEvent: ApplicationContext를 stop()하여 라이프사이클 빈들이 정지
신호를 받은 시점에 발생.
● ContextClosedEvent: ApplicationContext를 close()하여 싱글톤 빈 소멸되는 시점에
발생.
● RequestHandledEvent: HTTP 요청을 처리했을 때 발생.
ResourceLoader 리소스를 읽어오는 기능을 제공하는 인터페이스
ApplicationContext extends ResourceLoader
리소스 읽어오기 Resource resource = resourceLoader.getResource("classpath:test.txt");
● 파일 시스템에서 읽어오기 
● 클래스패스에서 읽어오기
● URL로 읽어오기
● 상대/절대 경로로 읽어오기
 Resource 추상화  java.net.URL 추상화., 스프링 내부 많이 사용 인터페이스
org.springFramework.core.io.Resouce
- 클래스 패스 기준 읽어오는 기능 부재
- ServletContet를 기준으로 상대경로로 읽어오는 기능 부재
- 새로운 핸들러 등록 URL 접미사 만들면 구현복잡. 
>> 불러오는 방법 통일. 
○ getInputStream()
○ exitst()                       !!! 항상체크해서 사용. 
○ isOpen()
○ getDescription(): 전체 경로 포함한 파일 이름 또는 실제 URL
구현체
● UrlResource: java.net.URL 참고.  
● ClassPathResource: 지원하는 접두어 classpath:
● FileSystemResource
● ServletContextResource: 웹 애플리케이션 루트에서 상대 경로로 리소스 찾는다.
리소스 읽어오기
● Resource의 타입은 locaion 문자열과 ApplicationContext의 타입에 따라 결정 된다.
○ ClassPathXmlApplicationContext -> ClassPathResource
○ FileSystemXmlApplicationContext -> FileSystemResource
○ WebApplicationContext -> ServletContextResource
● ApplicationContext의 타입에 상관없이 리소스 타입을 강제하려면 java.net.URL 접두어(+ classpath:)중 하나를 사용할 수 있다.
○ classpath:me/whiteship/config.xml -> ClassPathResource
○ file:///some/resource/path/config.xml -> FileSystemResource
*접두어 추천. 다양한개발자들을 위해.. 명시. 

 

728x90

스프링목차

스프링 IoC Inversion of Control : 제어의 역전: 어떤 객체가 사용하는 의존객체를 직접 만들어 사용하는게 아니라 주입받아 사용. 
- BeanFactory  :스프링 IOC 가장 최상위 인터페이스. 
- 애플리케이션 컴포넌트 중앙저장소
- 빈설정 소스로 부터 빈 정의 읽어드리고 빈구성 제공.
ApplicationContext 
- BeanFactory, 메시지 소스 처리기능, 이벤트 발생기능, 리소스 로딩기능. 
스프링 IoC 컨테이너 빈 인스턴스 생성
의존관계 설정
빈 제공
DI DI(Depedency Injection)의존성 주입.
내부에서 만든 변수를 외부에서 넣어준다.  
객체 생성과 사용자의 관심 분리, 가독성과 재사용을 높혀준다. 
- 광범위한 역제어 테크닉의 한 형태. 
- 클래스는 더이상 객체생성에 대한 책임이 없으며 추상팩토리 디자인 패턴에서 처럼 팩토리객체로 생성을 위임할 필요가 없다. 
스프링 빈 스프링 IoC 컨테이너가 관리하는 객체
의존성 관리
라이프사이클 인터페이스 지원. - @PostConstruct  : 빈이 만들어진후 .호출. 
스코프 : 기본 스프링은 싱글톤으로 만들어 사용
ApplicationContext BeanFactory 상속 받는 인터페이스. 
ClassPathXmlApplicationContext , context:component-scan _ XML 로 스프링 빈생성해서 가져옴. 
--이후 > @Configuration , @Bean , AnnotationConfigApplicationContext();  JAVA로 스프링빈생성
--현재 > @ComponentScan(basePackages="컴포넌트 스캔 시작 클래스")
SpringBootApplication 에 ComponentScan, Configuration이 이미 셋팅. 
스프링 빈 라이프사이클 생성, 의존설정, 사용 소멸. 
- 생산, 설정- 
1. BeanNameAware's 
setBeanName
2. BeanClassLoaderAware's setBeanClassLoader
3. BeanFactoryAware's setBeanFactory
4. ResourceLoaderAware's setResourceLoader (only applicable when running in an application context)
5. ApplicationEventPublisherAware's setApplicationEventPublisher (only applicable when running in an application context)
6. MessageSourceAware's setMessageSource (only applicable when running in an application context)
7. ApplicationContextAware's setApplicationContext (only applicable when running in an application context)
8. ServletContextAware's setServletContext (only applicable when running in a web application context)
9. postProcessBeforeInitialization methods of BeanPostProcessors <<@Autowire
- 초기화-
10. InitializingBean's 
afterPropertiesSet  >> 앞뒤 설정 가능. 
11. a custom init-method definition
- 사용- 
12. postProcessAfterInitialization methods of BeanPostProcessors
- 소멸-
1. DisposableBean's destroy
2. a custom destroy-method definition

* BeamFactory 가 BeanPostProcessor 타입 빈을 찾음 그중 AutowiredAnnotationBeanPostProcessor 를 찾아서.. 일반적인 빈에 적용을 함. 
출처 : BeanFactory docs
@Autowire 필요한 의존 객체의 타입에 해당하는 빈찾아 주입. 
required 기본값 true. 못찾으면 구동실패. 
생성자, 세터, 필드 사용. 

같은타입 빈 여러개 
- @Primary      < 추천. 
- 해당타입 모두 주입 _List<타입> or 필드이름 동일한것을 찾아서 주입 
  BeanPostProcessor 빈초기화 전후>  AutowiredAnnotationBeanPostProcessor(Autowire 처리
- @Qualifer  (빈이름으로 주입 맨앞자 소문자. 변경)
@ComponentScan 스캔 위치 설정 , 필터, 어떤 애노테이션 스캔할지 하지 않을지. 
- basePackages, basePackageClasses
선언 패키지 기준 Class<?>[]basePackageClasses 에 담아 실행.   
- useDefaultFilters, includeFilters, excludeFilters
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
구동시간 bean 늘어남 늘어지는단점. .. 예민하면 펑션 등 고려
실제 스캐닝은 ConfigurationClassPostProcessor라는 BeanFactoryPostProcessor에서 다른빈 모두 등록 전에 처리 됨.
- lazyInit  true 시.. 보통은 바로 초기화,  해당클래스 사용시 초기화. 
@Component @Repository
@Service
@Controller
@Configuration
스프링 빈의 스코프 @Component @Scope("prototype") 
프로토타입 내부 싱글톤 문제없음. 항상동일
싱글톤 내부 프로토 빈 사용시 프로토가 같음... 싱글톤과.. 같은현상. , 기본값 프록시 사용안함
>>@Component @Scope("prototype", proxyMode=ScopeProxyMode.TARGET_CLASS) 
CG라이브러리 사용한 다이나믹 프록시 적용됨. 매번 바꿀수있는 프록시로 감싸도록함. 
ObjectProvider<클래스> 클래스변수이름;

singleton : 스프링 default bean scope
prototype : 애플리케이션 요청시 ( getBean() 메서드가 호출될 때마다) 스프링이 새 인스턴스를 생성합니다
request : HTTP 요청별로 인스턴스화 되며 요청이 끝나면 소멸됩니다
session : HTTP 세션별로 인스턴스화 되며 세션이 끝나면 소멸됩니다.
global session : 포틀릿 기반의 웹 애플리케이션 용도로 전역 세션 스코프가 빈과 같은 스프링 MVC를 사용한 포탈 애플리케이션 내의 모든 포틀릿 사이에 공유를 할 수 있습니다.
thread : 새 스레드에서 요청하면 새로운 bean 인스턴스를 생성합니다. 같은 스레드의 요청에는 항상 같은 인스턴스가 반환됩니다.
custom : org.pringframework.beans.factory.config.Scope를 구현하고 커스텀 스코프를 스프링의 설정에 등록하여 사용합니다.

출처 : [Spring] Bean Scope와 Bean Life Cycle ooeunz.tistory.com/107
POJO Plain Old Java Object :  오래된 방식 자바 오브젝트 : 객체지향 원리 충실  
스프링 PSA POJO 철학 반영, Portable Service Abstraction  환경 변화 관계없이 일관된 환경제공 추상화구조
proxy 인터넷상에서, 한번 요청된 데이터를 저장해 두고 반복 요청 시에 저장된 데이터를 빠르게 제공해 주는 서버.

 

 

 

Inversion of Control

더보기

private BookRepository bookRepository = new BookRepository();   <- 의존객체를 직접만들어 사용

@Autowired                                                                         <-의존객체를 주입받아 사용. 

private BookRepository bookRepository;

public BookService(BookRepository bookRepository){                    

   this.bookRepository = bookRepository;

}

스프링빈 vs 자바빈

더보기
public class Book{                  >> 자바빈
	private int id;
	public int getId(){
		return id ;
	}
    public void setId(int id){
    	this.id;
    }
}                     

@Repository
public class BookRepository{}        >> 스프링 빈   이경우 어노테이션으로 autoscan 으로 빈으로 민들어짐. 

@Configuration , @Bean, AnnotationConfigApplicationContext  사용해서 스프링빈 만들때. 

더보기
@Configuration
 public class  ApplicationConfig{
      @Bean
      public BookRepositoy bookRepository(){
          return new BookRepository();
      }
}
-----
ApplicationContext ac = new AnnotationConfigApplicationContext(ApplicationConfig.class);  <<이렇게 사용가능

 

728x90
JDBC 관계형 데이터 베이스와 자바의 연결고리  Java database connectivity
- DataSource/DriverManager
- Connection
- PreparedStatement
SQL DDL, DML
ORM Object–relational mapping  : 객체 관계 맵핑 
- 도메인 모델 사용. 
    > 객체지향 프로그램 장점 활용, 디자인패턴, 코드재사용, 비즈니스 로직 구현 테스트 편함. 

애플리케이션의 클래스와 SQL 데이터 베이스의 테이블 사이의 맵핑 정보를 기술한 메타데이터를 사용하며, 자바 애플리케이션의 객체를 SQL 데이터베이스의 테이블에 자동으로 영속화 해주는 기술. 
- Java Persistence with Hibernate, Second Edition
장점 : 생산성, 유지보수성, 성능, 밴더 독립성
단점 : 학습비용
릴레이션/애트리뷰트
튜플/카디날리티
도메인
테이블 / 속성(ex_사원번호, 이름, 전화번호, 부서, 최소 차수는 1)
레코드 / 튜플갯수, 0일수있다. 
릴레이션에 포함된 각각 속성들이 가질수 있는 값들의 집합.  (ex_성별의 의 도메인 남, 여)

ORM 패러다임 불일치.

문제 객체 릴레이션
밀도 다양한 크기 객체 만듬, 커스텀 타입 만들기 쉬움 테이블 기본 데이터 타입
UDT(Uniform Data Type) CPU 실행 않고 PG 저장 비추
서브타입 상속구조 만들기 쉽다, 다형성 상속관계없음, 표준기술 아님, 다형적관계표현안됨
식별성 문제 레퍼러스 동일성(==)
인스턴스 동일성(equals())
주키(Primary key)
관계 객체 레퍼런스로 관계표현, 근복적으로 방향존재
다대다 가능
public class Study {
    User  user;
}
public class User{
    List<Study> studyList;
}
외래키(Foreign key)
방향 의미 없음, Join, 다대다 불가, 
데이터
네비게이션
레퍼런스를 이용해서 다른 객체로 이동 가능
콜렉션을 순회 활 수 도 있음
getOwner().getStudyList.stream().forEAch(s->s.getOwner());
비효율적. 
데이터 요청 적게 할수록 성능좋다. Join사용
많이 한번에 가져오는 것도 성능 많이씀. 
그렇다고 lazy loading을 하자니 그것도 문제다. (n+1 select)

 

JPA 사용이유

1. 도메인 주도 개발... 비지니스 로직 구현 집중 가능. 소프트웨어 복잡도 최소화 

도메인 : 사용자가 사용하는것.   영어사전: 1. 영역, 2. 소유지. 

+ 단건조회의 경우 jpa가 느릴수 있으나 객체와 데이터 베이스 사이 캐시사용으로 트랜젝션안 불필요한 쿼리를 날리지 않음. 

도메인 주도개발  참고 : 도메인 주도 설계(Domain-Driven Design) in Real Project — 도메인 

 

PostgreSQL 설치 및 서버 실행 (docker)

더보기

잘못만들어 삭제시

C:\Users\miseong>docker container ps
CONTAINER ID   IMAGE      COMMAND                  CREATED          STATUS          PORTS                    NAMES
6fe0fabf1380   postgres   "docker-entrypoint.s…"   22 minutes ago   Up 22 minutes   0.0.0.0:5432->5432/tcp   postgres_boot

C:\Users\miseong>docker container stop 6fe0fabf1380
6fe0fabf1380

C:\Users\miseong>docker container rm 6fe0fabf1380
6fe0fabf1380

C:\Users\miseong>docker images ps
REPOSITORY   TAG       IMAGE ID   CREATED   SIZE

C:\Users\miseong>docker images ps -a
REPOSITORY   TAG       IMAGE ID   CREATED   SIZE

 

 

--------
C:\Users\miseong>docker imgaes
docker: 'imgaes' is not a docker command.
See 'docker --help'

C:\Users\miseong>docker images ps
REPOSITORY   TAG       IMAGE ID   CREATED   SIZE

docker run -p 5432:5432 -e POSTGRES_PASSWORD=pass -e POSTGRES_USER=keesun -e POSTGRES_DB=springdata --name postgres_boot -d postgres

docker run -p 5432:5432 -e POSTGRES_PASSWORD=1234 -e POSTGRES_USER=day -e POSTGRES_DB=diarydata --name postgres_diary -d postgres


C:\Users\miseong>docker images
REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
postgres     latest    26c8bcd8b719   2 weeks ago   314MB

C:\Users\miseong>docker ps -a
CONTAINER ID   IMAGE      COMMAND                  CREATED              STATUS              PORTS                    NAMES
6fe0fabf1380   postgres   "docker-entrypoint.s…"   About a minute ago   Up About a minute   0.0.0.0:5432->5432/tcp   postgres_boot


C:\Users\miseong>docker start postgres_diary
postgres_diary

 

C:\Users\miseong>docker exec -i -t postgres_diary bash
root@b1de21ce08f0:/# su - postgres
postgres@b1de21ce08f0:~$ psql --username day --dbname diarydata
psql (13.2 (Debian 13.2-1.pgdg100+1))
Type "help" for help.

diarydata=# CREATE TABLE ACCOUNT(id int, username varchar(255), password varchar(255));
CREATE TABLE
diarydata=# INSERT INTO ACCOUNT VALUES(1,'day', 'pass');
INSERT 0 1
diarydata=# SELECT * FROM ACCOuNT;
 id | username | password
----+----------+----------
  1 | day      | pass
(1 row)

데이터베이스 조회

diarydata=# list
diarydata-# ;
ERROR:  syntax error at or near "list"
LINE 1: list
        ^
diarydata=# \list
                             List of databases
   Name    | Owner | Encoding |  Collate   |   Ctype    | Access privileges
-----------+-------+----------+------------+------------+-------------------
 diarydata | day   | UTF8     | en_US.utf8 | en_US.utf8 |
 postgres  | day   | UTF8     | en_US.utf8 | en_US.utf8 |
 template0 | day   | UTF8     | en_US.utf8 | en_US.utf8 | =c/day           +
           |       |          |            |            | day=CTc/day
 template1 | day   | UTF8     | en_US.utf8 | en_US.utf8 | =c/day           +
           |       |          |            |            | day=CTc/day
(4 rows)

diarydata=#

 

테이블 조회

diarydata=# \dt
        List of relations
 Schema |  Name   | Type  | Owner
--------+---------+-------+-------
 public | account | table | day
(1 row)

잘못만들어 삭제시

C:\Users\miseong>docker container ps
CONTAINER ID   IMAGE      COMMAND                  CREATED          STATUS          PORTS                    NAMES
6fe0fabf1380   postgres   "docker-entrypoint.s…"   22 minutes ago   Up 22 minutes   0.0.0.0:5432->5432/tcp   postgres_boot

C:\Users\miseong>docker container stop 6fe0fabf1380
6fe0fabf1380

C:\Users\miseong>docker container rm 6fe0fabf1380
6fe0fabf1380

C:\Users\miseong>docker images ps
REPOSITORY   TAG       IMAGE ID   CREATED   SIZE

C:\Users\miseong>docker images ps -a
REPOSITORY   TAG       IMAGE ID   CREATED   SIZE

 

 

--------
C:\Users\miseong>docker imgaes
docker: 'imgaes' is not a docker command.
See 'docker --help'

C:\Users\miseong>docker images ps
REPOSITORY   TAG       IMAGE ID   CREATED   SIZE

docker run -p 5432:5432 -e POSTGRES_PASSWORD=pass -e POSTGRES_USER=keesun -e POSTGRES_DB=springdata --name postgres_boot -d postgres

docker run -p 5432:5432 -e POSTGRES_PASSWORD=1234 -e POSTGRES_USER=day -e POSTGRES_DB=diarydata --name postgres_diary -d postgres


C:\Users\miseong>docker images
REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
postgres     latest    26c8bcd8b719   2 weeks ago   314MB

C:\Users\miseong>docker ps -a
CONTAINER ID   IMAGE      COMMAND                  CREATED              STATUS              PORTS                    NAMES
6fe0fabf1380   postgres   "docker-entrypoint.s…"   About a minute ago   Up About a minute   0.0.0.0:5432->5432/tcp   postgres_boot


C:\Users\miseong>docker start postgres_diary
postgres_diary

 

C:\Users\miseong>docker exec -i -t postgres_diary bash
root@b1de21ce08f0:/# su - postgres
postgres@b1de21ce08f0:~$ psql --username day --dbname diarydata
psql (13.2 (Debian 13.2-1.pgdg100+1))
Type "help" for help.

 

diarydata=# CREATE TABLE ACCOUNT(id int, username varchar(255), password varchar(255));
CREATE TABLE
diarydata=# INSERT INTO ACCOUNT VALUES(1,'day', 'pass');
INSERT 0 1
diarydata=# SELECT * FROM ACCOuNT;
 id | username | password
----+----------+----------
  1 | day      | pass
(1 row)

 

데이터베이스 조회

diarydata=# list
diarydata-# ;
ERROR:  syntax error at or near "list"
LINE 1: list
        ^
diarydata=# \list
                             List of databases
   Name    | Owner | Encoding |  Collate   |   Ctype    | Access privileges
-----------+-------+----------+------------+------------+-------------------
 diarydata | day   | UTF8     | en_US.utf8 | en_US.utf8 |
 postgres  | day   | UTF8     | en_US.utf8 | en_US.utf8 |
 template0 | day   | UTF8     | en_US.utf8 | en_US.utf8 | =c/day           +
           |       |          |            |            | day=CTc/day
 template1 | day   | UTF8     | en_US.utf8 | en_US.utf8 | =c/day           +
           |       |          |            |            | day=CTc/day
(4 rows)

diarydata=#

 

테이블 조회

diarydata=# \dt
        List of relations
 Schema |  Name   | Type  | Owner
--------+---------+-------+-------
 public | account | table | day
(1 row)

 

 

 

 

 

jdbc 예제

더보기
package com.today10sec.diary.basic;

import java.sql.*;

public class DBConnectTest {

    public static void main(String[] args) throws SQLException {
        String url = "jdbc:mariadb://localhost:3306/today10secDB";
        String userName = "today";
        String pw = "1234";

        //try with resource java 7  //자동 자원정리 메소드
        try(Connection connection = DriverManager.getConnection(url, userName,pw)){
            //System.out.println("Connection Created"+ connection);
            //String sql = " CREATE TABLE ACCOUNT(id int, username varchar(255), password varchar(255))";
            //String sql = " INSERT INTO ACCOUNT VALUES(1,'day', 'pass')";
            String sql =" SELECT * FROM ACCOuNT";
            ResultSet rs ;
            try(PreparedStatement statement = connection.prepareStatement(sql)){
                rs = statement.executeQuery();
                //int result = statement.executeUpdate();
                //System.out.println(result);
                while (rs.next()){
                    System.out.println(rs.getInt("id")+rs.getString("username")+rs.getString("password"));
                }
            }

        }
        //JDBC : 커넥션 만드는 비용이 비쌈 - 오래걸림.
        //스프링 부트 : hicari : 커넥션 객체 미리 만들고 사용. 
    }
}

JPA 프로그래밍: 프로젝트 세팅

 

데이터베이스 실행

  • PostgreSQL 도커 컨테이너 재사용
  • docker start postgres_boot
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <scope>runtime</scope>
        </dependency>

스프링 부트

  • 스프링 부트 v2.*
  • 스프링 프레임워크 v5.*

 

스프링 부트 스타터 JPA

  • JPA 프로그래밍에 필요한 의존성 추가
    • JPA v2.*
    • Hibernate v5.*
  • 자동 설정: HibernateJpaAutoConfiguration
    • 컨테이너가 관리하는 EntityManager (프록시) 빈 설정
    • PlatformTransactionManager 빈 설정
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

 

엔티티메니저.. JPA 스팩. 

엔티티매니저 내부적 하이버네이트 사용. 

강의 해선. 스프링데이터 JPA 를 사용

 

 

JDBC 설정

  • jdbc:postgresql://localhost:5432/springdata
  • keesun
  • pass

 

application.properties

  • spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
  • spring.jpa.hibernate.ddl-auto=create

#spring.jpa.hibernate.ddl-auto : create or update ( 매번 스키마 생성.  )for dev, validate(매핑안되면 에러) for prod,추천 

update..  스키마 변경시...  스키마가 추가가됨.  주의 

 

spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation  :

추가한 드라이버가 메시지를 구현안했을때 경고  >> true  없음. 

 

 

 

spring.jpa.hibernate.ddl-auto=create..  운영에서 소스 잘못 올라가면 살인날듯

 

 

entityManager 

 

 

기본예제

더보기
#basic db
spring.datasource.url=jdbc:postgresql://localhost:5432/diarydata
spring.datasource.password=1234
spring.datasource.username=day

#hibernate
spring.jpa.hibernate.ddl-auto=create
#spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
package com.today10sec.diary.etc;

import org.hibernate.Session;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.transaction.Transactional;

@Component
@Transactional
public class JpaRunner implements ApplicationRunner {

    @PersistenceContext
    EntityManager entityManager;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        Account account = new Account();
        account.setUsername("day");
        account.setPassword("12345");
        Session session = entityManager.unwrap(Session.class);
        session.save(account);
        entityManager.persist(account);
        System.out.println("접근");
    }
}
package com.today10sec.diary.etc;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
public class Account {

    @Id @GeneratedValue
    private Long id;

    @Column
    private String username;

    private String password;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

 

 

728x90

[스터디할래? Java] 목차

이글은 백기선님 스터디 할래? 스터디를 뒤늦게 따라간 기록입니다.

스터디할래 링크 >> https://github.com/whiteship/live-study

이필기를 시작으로 공부했습니다 >> https://www.notion.so/Live-Study-5-75f857b63e524d33914a8b3ec6e1e894

여기 없는내용은 스터디 할래 강의 내용 혹은 제가 java Doc보고작성하거나 예제를 만들어 추가했습니다.

그외는 같이 출처가 써있습니다. 

LinkedList vs ArrayList Vactor: Java1.0 시작 생성시 capacity 10로 정해져 10개씩 늘어남.
           thread에 대한 접근 동기화 보장 성능이슈
Java1.2 : List 인터페이스 대체
Collections.synchronizedList(List<T> list);   // Thread-safe 가필요할 때사용. 
ArrayList :내부적으로 데이터를 배열에서 관리, 추가 삭제를 위해 임시배열을 생성 데이터 복사
             *** 대량의 자료를 추가/삭제 하는 경우 그만큼 데이터의 복사가 많이 일어나 성능저하
             *** 반면 각 데이터는 인덱스를 가지고 있기 때문에 한번에 참조가 가능 검색에는 유리
LinkedList: 데이터를 저장하는 각 노드가 이전 노드와 다음 노드의 상태만 알고 있다. 
             ***추가 삭제 유리하지만 검색시 처음부터 노드를 순회해야함 성능상 불리 
접근제어자 public       동일클래스, 동일패키지, 자손클래스, 그외의 영역
protected  동일클래스 , 동일패키지, 자손클래스
(default)    동일클래스, 동일 패키지  >>자바파일안 클래스 동등두개 선언시 파일명 다른것. 
private      동일클래스
초기화블럭 vs 생성자 public class Init {
    private int number;
    private static int staticNum;
    {System.out.println("초기"); }
    static {System.out.println("정적초기");}
    public Init(){ System.out.println("생성");}
    public static void main(String[] args) {
        Init init = new Init();
    }
}   // 정적초기 > 초기 > 생성
this() 생성자에서 다른생성자 호출. 
public Init(){}
public Init(String start){ this(); }
-  this() 는 숨어있지않음, super()만 숨어있음
- this() 호출은 첫줄에서
기본생성자 선언하지 않아도 기본생성자 자동생성
변수가 들어간 생성자가 생기면 기본생성자를 자동 생성하지 않음
final public final class String :: 상속 막을 때 
상속이 적절하지 않을때  :: 특수한 String이 생겨버림. 
abstract public abstract class Init ::인스턴스 생성막을 떄 
Nested Class 중첩클래스 : 클래스 내부 다른클래스  
1. static nested class
2. inner class 
static nested class public class Outer {
  public static class Nested {
  }
}
InnerClass inner class >> Outter 호출후 사용. 
public class OuterClass{
    static class StaticNestedCalss{}
    class InnerClass{   
        class InnerInnerClass{}
    }
}
>>컴파일시 클래스파일 각각 3개 생성
OuterClass$InnerClass$InnerInnerClass.class
OuterClass$InnerClass.class
OuterClass.class
Local class 코드블럭 안에 정의된 클래스.  특정메소드 내에서만 필요한 객체가 필요할때 
public class Main{
 public static boolean methodExample(String... values){
   Class Value{
   }   
 }
}
Anonymous class 익명클래스= 이름없는 클래스
클래스의 정의와 인스턴스화를 한번에 작성.  인스턴스 구현, 추상클래스상속한 처리 부분적이용. 
만약 런타임시 클래스의 정보를 알고싶다면? Reflection API >
구체적 클래스 타입을 알지 못해도 클래스정보(생성자,필드,메서드) 접근할수 있게 해주는 자바 API, 상황에 따라 인스턴스 유동적 생성
https://woowacourse.github.io/javable/post/2020-07-16-reflection-api/#:~:text=Reflection%20API%EB%9E%80%3F,%EC%9E%88%EA%B2%8C%20%ED%95%B4%EC%A3%BC%EB%8A%94%20%EC%9E%90%EB%B0%94%20API%EB%8B%A4.
Java Reflection API 상기링크 참조
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method
Class carClass = Car.class;
Method move = carClass.getMethod("move");
move.invoke(obj, null);
import java.lang.reflect.Field; Field[] fields = Class.forName("java.com.whiteship.demo.Init").getDeclaredFields();
리플렉션을 사용하기 때문에 실제 Exception이 일어날 수 없어 Exception 처리를 용이하기 위함입니다.
>>리플렉션 사용예 .https://woowabros.github.io/experience/2020/10/08/excel-download.html
Heap 메모리 Heap 자료구조를 쓰기 때문. _ 완전이진트리. 항상 위의값이 아랫값보다 큼. 
min Heap , max Heap

java8 변화 추상클래스가 없어지고 인터페이스+디폴트메소드로 옮겨가고 있음. 
인터페이스 : 규약. 토비스프링3. ..참고. 

capacity 수용력

Nested 내포반복. 

Reflection 반영, 비추다. 

invoke 들먹이다 언급하다. 

http://tutorials.jenkov.com/java/nested-classes.html#:~:text=In%20Java%20a%20static%20nested,instance%20of%20the%20enclosing%20class.]

 

Java의 LinkedList와 ArrayList에 대한 비교 https://www.holaxprogramming.com/2014/02/12/java-list-interface/

 

객체지향의 사실과 오해.. 책 찾아볼것. 

 

 

package com.whiteship.demo;

import com.sun.xml.internal.ws.api.ha.StickyFeature;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

/*int 값을 가지고 있는 이진 트리를 나타내는 Node 라는 클래스를 정의하세요.
int value, Node left, right를 가지고 있어야 합니다.
BinrayTree라는 클래스를 정의하고 주어진 노드를 기준으로 출력하는 bfs(Node node)와 dfs(Node node) 메소드를 구현하세요.
DFS는 왼쪽, 루트, 오른쪽 순으로 순회하세요.*/
class Node_Binary{

    private int value;
    private Node_Binary left;
    private Node_Binary right;

    public Node_Binary(int value, Node_Binary left, Node_Binary right){
        this.value=value;
        this.left = left;
        this.right=right;
    }
    public Node_Binary(int value){
        this.value=value;
    }

     public int getValue() {
         return value;
     }

     public void setValue(int value) {
         this.value = value;
     }

     public Node_Binary getLeft() {
         return left;
     }

     public void setLeft(Node_Binary left) {
         this.left = left;
     }

     public Node_Binary getRight() {
         return right;
     }

     public void setRight(Node_Binary right) {
         this.right = right;
     }
 }
public class BinaryTree {
    private Node_Binary root;
    public BinaryTree(Node_Binary root){
        this.root=root;
    }
    public Node_Binary getRoot() {
        return root;
    }

    public void getDFS (Node_Binary node, List<String> resultDfs){
        if (node == null) return;
        resultDfs.add(String.valueOf(node.getValue()));
        getDFS(node.getLeft(), resultDfs);
        getDFS(node.getRight(), resultDfs);
    }

    public List<String> getBFS (Node_Binary node, List<String> resultBfs){
        Queue<Node_Binary> queue  = new LinkedList<>();
        queue.offer(root);
        while (!queue.isEmpty()){
            node = queue.poll();
            resultBfs.add(String.valueOf(node.getValue()));
            if (node.getLeft() !=null){
                queue.offer(node.getLeft());
            }
            if (node.getRight() != null){
                queue.offer(node.getRight());
            }
        }

        return resultBfs;
    }
}
package com.whiteship.demo;

import org.junit.jupiter.api.Test;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collector;
import java.util.stream.Collectors;

import static org.junit.jupiter.api.Assertions.*;

class BinaryTreeTest {

    private List<String> resultDfsList = Collections.EMPTY_LIST;
   // 1 - 2 -4,5
   //   - 3-6,7
    private BinaryTree getUpBinaryTreeValue(){
        Node_Binary node4 = new Node_Binary(4);
        Node_Binary node5 = new Node_Binary(5);
        Node_Binary node6 = new Node_Binary(6);
        Node_Binary node7 = new Node_Binary(7);
        Node_Binary node2 = new Node_Binary(2,node4,node5);
        Node_Binary node3 = new Node_Binary(3,node6,node7);
        Node_Binary root = new Node_Binary(1,node2,node3);

        return new BinaryTree(root);
    }
    @Test
    void TEST_DFS (){
        BinaryTree binaryTree = getUpBinaryTreeValue();
        binaryTree.getDFS(binaryTree.getRoot(), resultDfsList);
        String resultDFS = String.join("",resultDfsList);
        assertEquals("1245367", resultDFS);
    }

    @Test
    void TEST_BFS(){
        BinaryTree binaryTree = getUpBinaryTreeValue();
        List<String> resultBfsList = binaryTree.getBFS(binaryTree.getRoot(), new ArrayList<>());
        String resultBfs = String.join("",resultBfsList);
        assertEquals("1234567",resultBfs);
    }
}

목표

자바의 Class에 대해 학습하세요.

학습할 것 (필수)

  • 클래스 정의하는 방법
  • 객체 만드는 방법 (new 키워드 이해하기)
  • 메소드 정의하는 방법
  • 생성자 정의하는 방법
  • this 키워드 이해하기

마감일시

2020년 12월 19일 토요일 오후 1시까지.

과제 (Optional)

  • int 값을 가지고 있는 이진 트리를 나타내는 Node 라는 클래스를 정의하세요.
  • int value, Node left, right를 가지고 있어야 합니다.
  • BinrayTree라는 클래스를 정의하고 주어진 노드를 기준으로 출력하는 bfs(Node node)와 dfs(Node node) 메소드를 구현하세요.
  • DFS는 왼쪽, 루트, 오른쪽 순으로 순회하세요.

 

+ Recent posts