문제 : 초기페이지 hello.html으로 안가짐
HomeController에서 getmapping ="/" 이고 return값 hello 인데 왜 안될까
이유 -> Application.java 파일이 shop폴더 안에 있었음. 가장 바깥위치로 나와야함
@SpringbootApplication 아래부터 쭉 검색하는원리 @ComponentScan원리 생각하면 됨
문제 : 초기페이지 hello.html으로 안가짐
HomeController에서 getmapping ="/" 이고 return값 hello 인데 왜 안될까
이유 -> Application.java 파일이 shop폴더 안에 있었음. 가장 바깥위치로 나와야함
@SpringbootApplication 아래부터 쭉 검색하는원리 @ComponentScan원리 생각하면 됨
@GeneratedValue(stragey= 전략 )
전략에는 크게 4종류가 존재한다.
Identity - 기본키생성을 hibernate가 아니라 데이터베이스가 하도록 위임한다.
데이터를 저장한 후 commit 시점에 최적의 상황을 고려하여 쿼리를 실행시키는 것이 아니라, persist() 시점에 insert 문이 바로 실행되고 DB 에서 기본키 값을 생성한다. 그리고 이 키 값을 가져와서 JPA 1차 캐시에 (key, entity) 키, 값을 저장한다.
따라서 IDENTITY 옵션 사용시 write-behind (쓰기지연) 기능을 무시한다. write-behind 는 한 트랜잭션 안에서 이루어지는 성능 최적화이므로 이 부분은 이루어지지 않아도 양보가 가능하다. 단, bulk insert 가 안되는 문제가 있을 수 있다. (다른 해결책이 있음)
Sequence
Hibernate가만들어주는 Sequence를 사용한다.
데이터베이스(Oracle 등)가 제공해주는 시퀀스를 사용할 수 있다. @SequenceGenerator 등록이 필요하다.
@Entity
@SequenceGenerator(
name = "BADGE_SEQ_GENERATOR",
sequnceName = "BADGE_SEQ",
initialValue = 1,
allocationSize = 50)
public class Badge {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "BADGE_SEQ_GENERATOR")
private Long id;
private String name;
}
데이터 저장시 (persist()) 데이터베이스에서 시퀀스를 조회해서 JPA 1차 캐시에 (key, entity) 키, 값을 저장한다.
데이터베이스에 시퀀스를 조회하러 DB I/O 요청 cost가 생긴다. 하지만, initialValue 와 allocationSize 를 조정함으로써 메모리에 미리 순번을 저장해 놓을 수 있다. 따라서 대량의 insert 쿼리가 주로 발생하는 엔티티라면 이 값을 설정해주면 좋을 것이다.
initialValue 는 기본값이 1, allocationSize 는 기본값이 50이다. 즉 1부터 한번에 50개의 순번을 가져온다. 한 번에 더 많이 가져오려면 allocationSize = 100 등으로 이 값을 늘리면 될 것이다.
table
키 생성용 테이블을 별도로 사용하여 (마치 시퀀스처럼), 키를 생성한다.
모든 데이터베이스에서 적용가능하지만, 성능이 좋지 않으므로 실제 운영에서 잘 사용되지 않는다.
Auto
@Entity
public class Badge {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
}
이 전략옵션은 말그대로 '자동'으로 적절한 전략을 알아서 매핑시킨다. @GeneratedValue 라고만 쓰면 기본으로 AUTO 옵션을 사용한다.
Hibernate 는 적절한 옵션을 알아내기 위해 아래 논리대로 탐색한다.
Mysql을 사용하고 아무옵션도 주지않는다면 AUTO로 적용되어 SEQUENCE로 기본키를 자동으로 생성한다.
REST API 생성시 고려사항1[회원등록] (0) | 2022.06.01 |
---|---|
엔티티 매핑 (0) | 2022.05.21 |
프로세스란? - 우리가 실행하는 프로그램이라 생각하면된다.
- 프로세스는 각각 독립된 메모리 영역(Code, Data, Stack, Heap의 구조)을 할당받는다.
- 기본적으로 프로세스당 최소 1개의 스레드(메인 스레드)를 가지고 있다.
- 각 프로세스는 별도의 주소 공간에서 실행되며, 한 프로세스는 다른 프로세스의 변수나 자료구조에 접근할 수 없다.
- 한 프로세스가 다른 프로세스의 자원에 접근하려면 프로세스 간의 통신(IPC, inter-process communication)을 사용해야 한다.(Ex. 파이프, 파일, 소켓 등을 이용한 통신 방법 이용)
스레드란? - 프로세스 내 작업의 흐름을 말한다.
- 스레드는 프로세스 내의 스택 영역을 제외한 다른 메모리 영역(Code,Heap,Data)을 프로세스 내의 다른 스레드들과 공유한다.
멀티프로세스 - 하나의 응용프로그램을 여러개의 프로세스로 구성해서 각 프로세스가 하나의 작업을 처리하도록 한다.
장점 - 여러자식 프로세스중 하나가 문제가 발생해서 죽더라도 다른 영향이 확산되지 않는다.
단점 - ContextSwitching 에서의 오버헤드 문제가 있다
멀티스레드 - 하나의 응용프로그램을 여러개의 스레드로 구성하고 그 스레드마다 하나의 작업을 처리하도록 하낟.
장점 - 스레드는 프로세스 내의 Stack 영역을 제외한 모든 메모리를 고유하기때문에 통신의 부담이 적다
단점 - 멀티스레드의 경우 자원공유의 문제가 발생(동기화 문제), 하나의 스레드에 문제가 발생하면 전체 프로세스에 영향을 받는다.
참고: https://gmlwjd9405.github.io/2018/09/14/process-vs-thread.html
업캐스팅
상위 클래스로 변수를 선언하고 하위클래스의 생성자로 인스턴스를 생성한다
Customer customer = new VipCustomer();
이때 인스턴스는 VipoCustomer가 만들어졌지만 타입은 Customer이므로접근할 수 있는것은 Customer의 변수와 메서드이다.(VipCustomer()생성자에 의해 VipCustomer 클래스의 모든 멤버변수가 메모리에는 생성됨)->다운캐스팅을하면?
VipCustomer vCustomer = new VipCustomer();
addCustomer(vCustomer);
int addCustomer(Customer customer){
}
하위클래스는 상위 클래스의타입을내포하고있으므로상위 클래스로 묵시적 형변환이 ㄱ가능함
상속관계에서 모든 하위클래스는 상위 클래스로 형변환(업캐스팅)이 된다.
업캐스팅을 사용하는 이유 OR 장점 예시
다형성, 하나의 인스턴스(슈퍼클래스)로 서브클래스를 전부 관리할 수 있다.
Class Juice{
public void make(){
System.out.print("쥬스만들어");
}
}
Class OrangeJuice{
@Override
public voidmake(){
System.out.print("오렌지쥬스 만들어");
}
}
Class AppleJuice{
@Override
public void make(){
System.out.print("사과쥬스 만들어");
}
}
Class Customer{
public void drink(Juice juice2){
juice2.make();
}
}
public class Cafe{
public static void main(String[] args){
{
Customer customer = new Customer();
Juice juice1= new OrangeJuice();
customer.drink();
}
}
--> 오버라이드된 오렌지쥬스 만들어가 출력된다. 만약 업캐스팅을 사용하지 않는다면 일일이 조건문으로 확인해서 적절한 drink문을 실행하게 될것임
public void drink(Juice juice1)
{if(juice1의 종류가 사과쥬스?)
{
juice1.drink();/
}
else if(juice1의 종류가 오렌지 쥬스?)
{
juice1.drink();
}
}
참고 :https://woochan-autobiography.tistory.com/201
https://velog.io/@smallcherry/Java-UpCastingAndDownCasting, https://chilas-it.tistory.com/70, https://jhost.tistory.com/27, https://madplay.github.io/post/java-upcasting-and-downcasting
https://www.inflearn.com/questions/47449
불변객체,final (0) | 2022.06.28 |
---|---|
람다와 함수형 인터페이스 (0) | 2021.10.23 |
자바프로그램의 동작, (1) | 2021.10.17 |
[Java]List Interface (0) | 2021.09.18 |
java 환경변수 3가지 셋팅 (0) | 2017.05.05 |
class Employee{
String name="hello"
String city="seoul"
}
final 이 붙었다고 불변객체를 보장하지 않는다. final은 상태가 바뀌지 않는것으로
아래와 같이 조치를 모두 취해진게 불변객체라 불릴수잇음
이펙티브 자바에서는 클래스를 불변으로 만들기 위해 다음의 다섯 가지 규칙을 따르라고 한다.
의문 : private final MemberRepository memberRepository = newMemoryMemberRepository();
코드에서final만 붙이면 memberRepository는 불변객체가 되는것일까?? -> 여기서 final은 재할당을
방지하기 위한 목적이라 생각하면 된다. 불변객체라고는 볼수없을듯
참고
https://velog.io/@conatuseus/Java-Immutable-Object%EB%B6%88%EB%B3%80%EA%B0%9D%EC%B2%B4
https://jins-dev.tistory.com/entry/Java-%EC%9D%98-Final-Object%EC%97%90-%EB%8C%80%ED%95%98%EC%97%AC
https://c-king.tistory.com/496#recentEntries
https://mangkyu.tistory.com/131
https://velog.io/@ohzzi/%EB%B6%88%EB%B3%80-%EA%B0%9D%EC%B2%B4Immutable-Object
업캐스팅, 다운캐스팅 (0) | 2022.07.02 |
---|---|
람다와 함수형 인터페이스 (0) | 2021.10.23 |
자바프로그램의 동작, (1) | 2021.10.17 |
[Java]List Interface (0) | 2021.09.18 |
java 환경변수 3가지 셋팅 (0) | 2017.05.05 |
@Entity
@Getter @Setter
public class Member {
@Id @GeneratedValue
@Column(name="member_id")
private Long id;
@NotEmpty
private String username;
@Embedded
private Address address;
@OneToMany(mappedBy = "member")
private List<Order> orders = new ArrayList();
}
@NotEmpty 를 엔티티쪽에 걸어줄경우 username이 어떤 api스팩에서는 필수이지만 다른 api스팩에서는 필수가아닐때가있기 때문에 아래와 같이 dto에있는 username에 @NotEmpty를 걸어준다.
@RequestMapping("/api/v1/members")
public CreateMemberResponse saveMemberV1(@RequestBody @Valid Member member)
{
Long id = memberService.join(member);
return new CreateMemberResponse(id);
}
@RequestMapping("/api/v2/members")
public CreateMemberResponse saveMemberV2(@RequestBody @Valid CreateMemberRequest memberRequest)
{
Member member = new Member();
member.setUsername(memberRequest.getName());
Long id = memberService.join(member);
return new CreateMemberResponse(id);
}
@Data
static class CreateMemberRequest{
@NotEmpty
private String name;
}
API를 만들때는 엔티티를 파라미터로 받지 말고 DTO(CreateMemberRequest)를 통해서 받는다. 엔티티에서 name->stringname으로 필드 변경시 문제가 발생할 수 있기 때문이다. dto로 받게되면 컴파일오류로 빨갛게 표시가되서 바로 알 수 있고 중간에 파라미터랑 앤티티랑 매핑해줘서 엔티티를 변경해도 api스팩이 바뀌지 않게되는 장점이 있다. 또한 뭐가 올지 dto통해서 알수도 있다.(member만 보고서는 모름), valid도 또한 dto에 적용가능해서 맞춤형으로 쓸수 있다. 또한 entity외부에 노출하지않음.
->dto사용해서 요청과 응답을 api로 처리하는것이 좋다!
이유: 템플릿엔진을 사용해서 렌더링하는 컨트롤러와 api스타일 컨트롤러 패키지를 분리해서 패키지 해서 작성하는데, 공통으로예외처리할때 패키지나 구성단위로 공통처리를 하는데, api와 화면이랑은 공통처리할 요소가 다르다. 화면은 템플릿엔진에서 먼가 문제가 생기면 공통에러화면(공통에러html)이 나와야되고 api때는 공통에러용 json api 스팩이 나가야되기때문에 분리하는것이 좋다.
JPA의 기본키 생성 전략 (0) | 2022.08.24 |
---|---|
엔티티 매핑 (0) | 2022.05.21 |
@Entity
@Entity가 붙은 클래스는 JPA가 관리, 엔티티라 한다.
• JPA를 사용해서 테이블과 매핑할 클래스는 @Entity 필수
• 주의
• 기본 생성자 필수(파라미터가 없는 public 또는 protected 생성자)
• final 클래스, enum, interface, inner 클래스 사용X
• 저장할 필드에 final 사용 X
속성: name
• JPA에서 사용할 엔티티 이름을 지정한다.
• 기본값: 클래스 이름을 그대로 사용(예: Member)
• 같은 클래스 이름이 없으면 가급적 기본값을 사용한다
JPA의 기본키 생성 전략 (0) | 2022.08.24 |
---|---|
REST API 생성시 고려사항1[회원등록] (0) | 2022.06.01 |
알게되거나 배운부분:(int)Math.log10(number) - 로그로 1~9 -> 0 10~99->1 구할수있음
나의풀이
class Solution {
public int solution(String s) {
int answer = 0; int min=s.length(); int money=s.length();
String temp=""; int t=1;
for(int i=1;i<=s.length()/2;i++)
{
for(int j=1;j*i<=s.length();j++)
{
if(temp.equals(s.substring((j-1)*i,j*i)))
{
t++;
if((j+1)*i>s.length())//마지막부분 예외처리
{
money-=(t-1)*i; if(t<10){money+=1;}else if(t<100){money+=2;}else if(t<1000){money+=3;}
else if(t==1000){money+=4;}
}
}
else
{
money-=(t-1)*i;
temp=s.substring((j-1)*i,j*i);//0 2 2 4 4 6... 0 3 3 6 6 9
if(t>1){if(t<10){money+=1;}else if(t<100){money+=2;}else if(t<1000){money+=3;}
else if(t==1000){money+=4;}
}
t=1;
}
}
temp="";
if(min>=money)
{min=money;}
money=s.length();
t=1;
}
answer=min;
return answer;
}
}
다른사람의 풀이
class Solution {
public int solution(String s) {
int answer = 0;
for(int i=1; i<=(s.length()/2)+1; i++){
int result = getSplitedLength(s, i, 1).length();
answer = i==1 ? result : (answer>result?result:answer);
}
return answer;
}
public String getSplitedLength(String s, int n, int repeat){
if(s.length() < n) return s;
String result = "";
String preString = s.substring(0, n);
String postString = s.substring(n, s.length());
// 불일치 -> 현재까지 [반복횟수 + 반복문자] 조합
if(!postString.startsWith(preString)){
if(repeat ==1) return result += preString + getSplitedLength(postString, n, 1);
return result += Integer.toString(repeat) + preString + getSplitedLength(postString, n, 1);
}
return result += getSplitedLength(postString, n, repeat+1);
}
}
[LEVEL1]문자열 내 마음대로 정렬하기 (0) | 2022.04.07 |
---|---|
[LEVEL1]문자열 내림차순으로 배치하기 (0) | 2022.04.05 |
[LEVEL1] 정수 내림차순으로 배치하기 (0) | 2022.03.30 |
[LEVEL1] 정수 내림차순으로 배치하기 (0) | 2022.03.30 |
[LEVEL1] 최대공약수와 최소공배수 (0) | 2022.03.28 |
새로 알게된점 - Comparator의 이용, 자바 compareTo는 char에서 안된다
import java.util.*;
class Solution {
public String[] solution(String[] strings, int n) {
Arrays.sort(strings,new Comparator<String>(){
public int compare(String s1, String s2){
if(s1.charAt(n)==s2.charAt(n)){
System.out.print("dfg");
// return s1.charAt(n).compareTo(s2.charAt(n));
return s1.compareTo(s2);
}
else{
return s1.charAt(n)-s2.charAt(n);
}
}
});
for(String i:strings)
{System.out.println(i);}
String[] answer = strings;
return answer;
}
}
다른사람의풀이
[LEVEL2] 문자열압축 (0) | 2022.04.09 |
---|---|
[LEVEL1]문자열 내림차순으로 배치하기 (0) | 2022.04.05 |
[LEVEL1] 정수 내림차순으로 배치하기 (0) | 2022.03.30 |
[LEVEL1] 정수 내림차순으로 배치하기 (0) | 2022.03.30 |
[LEVEL1] 최대공약수와 최소공배수 (0) | 2022.03.28 |
알게된점 - Collections.reverse 이용해서도 가능
나의풀이
import java.util.*;
class Solution {
public String solution(String s) {
String answer = ""; //알아볼거-대소문자 무시, 대문자소문자 아스키대로 정렬인지/
//string으로하면오래걸림..
String [] arr = s.split("");
Arrays.sort(arr,Comparator.reverseOrder());
for(int i=0;i<arr.length;i++){
answer+=arr[i];
}
return answer;
}
}
다른사람의 풀이
import java.util.*;
class Solution {
public String solution(String s) {
return s.chars().boxed().sorted(Collections.reverseOrder()).
collect(StringBuilder::new, StringBuilder::appendCodePoint,
StringBuilder::append).toString();
}
}
[LEVEL2] 문자열압축 (0) | 2022.04.09 |
---|---|
[LEVEL1]문자열 내 마음대로 정렬하기 (0) | 2022.04.07 |
[LEVEL1] 정수 내림차순으로 배치하기 (0) | 2022.03.30 |
[LEVEL1] 정수 내림차순으로 배치하기 (0) | 2022.03.30 |
[LEVEL1] 최대공약수와 최소공배수 (0) | 2022.03.28 |