30만건

Max Memory: 2048 MB
Total Memory: 512 MB
freeMemory: 461 MB
Used Memory: 50 MB
Before: 50 MB
After: 1277 MB
Memory used by API: 1227 MB


2025-04-23T11:45:55.726+09:00  INFO 16128 --- [nio-8080-exec-5] c.h.global.aop.GlobalLoggingAspect       : [종료 메서드]: ExcelUploadUtils.parseExcelToObject(..)
2025-04-23T11:45:55.726+09:00  INFO 16128 --- [nio-8080-exec-5] c.h.global.aop.GlobalLoggingAspect       : [실행 시간]: 14.5688651


2025-04-23T11:45:55.738+09:00  INFO 16128 --- [nio-8080-exec-5] c.h.global.aop.GlobalLoggingAspect       : [실행 메서드]: AdminSalaryService.excelUploadSalary(..)


Max Memory: 2048 MB
Total Memory: 2048 MB
freeMemory: 511 MB
Used Memory: 1536 MB
Before: 1536 MB


2025-04-23T11:45:56.752+09:00  INFO 16128 --- [nio-8080-exec-5] c.h.global.aop.GlobalLoggingAspect       : [실행 메서드]: ListCrudRepository.saveAll(..)
2025-04-23T11:47:22.791+09:00  INFO 16128 --- [nio-8080-exec-5] c.h.global.aop.GlobalLoggingAspect       : [종료 메서드]: ListCrudRepository.saveAll(..)
2025-04-23T11:47:22.791+09:00  INFO 16128 --- [nio-8080-exec-5] c.h.global.aop.GlobalLoggingAspect       : [실행 시간]: 86.0385429


After: 508 MB
Memory used by API: -1028 MB


2025-04-23T11:47:22.791+09:00  INFO 16128 --- [nio-8080-exec-5] c.h.global.aop.GlobalLoggingAspect       : [종료 메서드]: AdminSalaryService.excelUploadSalary(..)
2025-04-23T11:47:22.791+09:00  INFO 16128 --- [nio-8080-exec-5] c.h.global.aop.GlobalLoggingAspect       : [실행 시간]: 87.054041


2025-04-23T11:47:23.847+09:00  INFO 16128 --- [nio-8080-exec-5] c.h.global.aop.GlobalLoggingAspect       : [종료 메서드]: AdminSalaryController.excelUpload(..)
2025-04-23T11:47:23.847+09:00  INFO 16128 --- [nio-8080-exec-5] c.h.global.aop.GlobalLoggingAspect       : [실행 시간]: 102.6899798

 

 

10만건

2025-04-23T12:16:13.108+09:00  INFO 16128 --- [nio-8080-exec-4] c.h.global.aop.GlobalLoggingAspect       : [실행 메서드]: AdminSalaryController.excelUpload(..)
2025-04-23T12:16:13.109+09:00  INFO 16128 --- [nio-8080-exec-4] c.h.global.aop.GlobalLoggingAspect       : [실행 메서드]: ExcelUploadUtils.parseExcelToObject(..)
Max Memory: 2048 MB
Total Memory: 512 MB
freeMemory: 458 MB
Used Memory: 53 MB
Before: 53 MB
After: 456 MB
Memory used by API: 403 MB
2025-04-23T12:16:16.854+09:00  INFO 16128 --- [nio-8080-exec-4] c.h.global.aop.GlobalLoggingAspect       : [종료 메서드]: ExcelUploadUtils.parseExcelToObject(..)
2025-04-23T12:16:16.855+09:00  INFO 16128 --- [nio-8080-exec-4] c.h.global.aop.GlobalLoggingAspect       : [실행 시간]: 3.7453336
2025-04-23T12:16:16.856+09:00  INFO 16128 --- [nio-8080-exec-4] c.h.global.aop.GlobalLoggingAspect       : [실행 메서드]: AdminSalaryService.excelUploadSalary(..)
2025-04-23T12:16:16.864+09:00  INFO 16128 --- [nio-8080-exec-4] c.h.global.aop.GlobalLoggingAspect       : [실행 메서드]: EmployeeRepository.findAllByEmpNoIn(..)
2025-04-23T12:16:17.404+09:00  INFO 16128 --- [nio-8080-exec-4] c.h.global.aop.GlobalLoggingAspect       : [종료 메서드]: EmployeeRepository.findAllByEmpNoIn(..)
2025-04-23T12:16:17.404+09:00  INFO 16128 --- [nio-8080-exec-4] c.h.global.aop.GlobalLoggingAspect       : [실행 시간]: 0.5404145
Max Memory: 2048 MB
Total Memory: 1015 MB
freeMemory: 386 MB
Used Memory: 628 MB
Before: 628 MB
2025-04-23T12:16:17.435+09:00  INFO 16128 --- [nio-8080-exec-4] c.h.global.aop.GlobalLoggingAspect       : [실행 메서드]: ListCrudRepository.saveAll(..)
2025-04-23T12:16:42.403+09:00  INFO 16128 --- [nio-8080-exec-4] c.h.global.aop.GlobalLoggingAspect       : [종료 메서드]: ListCrudRepository.saveAll(..)
2025-04-23T12:16:42.403+09:00  INFO 16128 --- [nio-8080-exec-4] c.h.global.aop.GlobalLoggingAspect       : [실행 시간]: 24.9670936
After: 154 MB
Memory used by API: -473 MB
2025-04-23T12:16:42.403+09:00  INFO 16128 --- [nio-8080-exec-4] c.h.global.aop.GlobalLoggingAspect       : [종료 메서드]: AdminSalaryService.excelUploadSalary(..)
2025-04-23T12:16:42.403+09:00  INFO 16128 --- [nio-8080-exec-4] c.h.global.aop.GlobalLoggingAspect       : [실행 시간]: 25.5476658
2025-04-23T12:16:42.635+09:00  INFO 16128 --- [nio-8080-exec-4] c.h.global.aop.GlobalLoggingAspect       : [종료 메서드]: AdminSalaryController.excelUpload(..)
2025-04-23T12:16:42.636+09:00  INFO 16128 --- [nio-8080-exec-4] c.h.global.aop.GlobalLoggingAspect       : [실행 시간]: 29.5271092

 

 

 

의문점

saveAll을 호출하기전에 메모리 사용량은 왜 1536 MB일까?

saveAll을 호출이후에는 메모리 사용량이 왜 508 MB일까?

'프로젝트' 카테고리의 다른 글

엑셀 100만건 업로드 트러블 슈팅 (1)  (0) 2025.04.17

- 100MB 초과로 인한 엑셀 파싱 실패

org.apache.poi.util.RecordFormatException: Tried to read data but the maximum length for this record type is 100,000,000.
If the file is not corrupt and not large, please open an issue on bugzilla to request 
increasing the maximum allowable size for this record type.
You can set a higher override value with IOUtils.setByteArrayMaxOverride()

 

- 에러 유형
  - org.apache.poi.util.RecordFormatException

- 발생 원인

  - excel 파일을 읽는 도중, 허용된 최대 크기(100MB)를 초과한 데이터를 포함한 레코드를 읽으려고 함

- 제한 사항

  - Apache POI는 기본적으로 1개의 레코드에 대해 100MB(100,000,000 바이트)까지만 읽도록 설정되어 있음.

레코드란??
내부적으로는 파일을 구성하는 여러 XML 혹은 바이너리 블록 단위
ex) sheet1 , styles, drawing

 

 

- 실제 압축 크기와 압축 해제 후 크기 확인

- xl/worksheets/sheet1.xml

  - 압축 크기 : 22.05 MB

  - 압축 해제 크기 : 246.73 MB

public <T> List<T> parseExcelToObject(MultipartFile file, Class<T> clazz) throws IOException {
        // MultipartFile을 임시 파일로 저장
        File tempFile = File.createTempFile("uploaded", ".xlsx");
        file.transferTo(tempFile);

        try (ZipFile zipFile = new ZipFile(tempFile)) {
            Enumeration<? extends ZipEntry> entries = zipFile.entries();
            while (entries.hasMoreElements()) {
                ZipEntry entry = entries.nextElement();
                System.out.println("Entry: " + entry.getName()
                        + ", Compressed Size: " + entry.getCompressedSize()
                        + ", Uncompressed Size: " + entry.getSize());
            }
        } finally {
            // 작업 끝나면 임시 파일 삭제
            tempFile.delete();
        }
        Workbook workbook = WorkbookFactory.create(file.getInputStream());
        Sheet sheet = workbook.getSheetAt(0);

        parseHeader(sheet, clazz);
        return parseBody(sheet, clazz);
    }
    
Entry: xl/drawings/drawing1.xml, Compressed Size: 261, Uncompressed Size: 775
Entry: xl/worksheets/sheet1.xml, Compressed Size: 23125563, Uncompressed Size: 258712875
Entry: xl/worksheets/_rels/sheet1.xml.rels, Compressed Size: 179, Uncompressed Size: 298
Entry: xl/theme/theme1.xml, Compressed Size: 808, Uncompressed Size: 3757
Entry: xl/sharedStrings.xml, Compressed Size: 237, Uncompressed Size: 352
Entry: xl/styles.xml, Compressed Size: 575, Uncompressed Size: 2192
Entry: xl/workbook.xml, Compressed Size: 339, Uncompressed Size: 807
Entry: xl/_rels/workbook.xml.rels, Compressed Size: 234, Uncompressed Size: 697
Entry: _rels/.rels, Compressed Size: 178, Uncompressed Size: 296
Entry: [Content_Types].xml, Compressed Size: 309, Uncompressed Size: 1049

 

코드 수정

public <T> List<T> parseExcelToObject(MultipartFile file, Class<T> clazz) throws IOException {
        IOUtils.setByteArrayMaxOverride(300_000_000); // 레코드 크기 300MB까지 허용
        Workbook workbook = WorkbookFactory.create(file.getInputStream());
        Sheet sheet = workbook.getSheetAt(0);

        parseHeader(sheet, clazz);
        return parseBody(sheet, clazz);
    }

 

 

 

나중에 찾아볼 내용

xlsx 파일은 사실 ZIP 파일이다??

엑셀 크기는 22MB이지만 실제로는 더 클수있다?

'프로젝트' 카테고리의 다른 글

엑셀 100만건 업로드 트러블 슈팅 (2)  (0) 2025.04.23

깨짐 현상

 

1. build tool 설정

gradle(디폴트) -> IntelliJ IDEA로 변경후 저장

 

'인강 > 자바 ORM 표준 JPA 프로그래밍 - 기본편' 카테고리의 다른 글

연관관계 매핑  (0) 2024.09.10
엔티티 매핑  (0) 2024.09.09

중요!!

1. 연관관계의 주인은 외래 키의 위치를 기준으로 정해야함

2. 단방향 매핑 설계를 목표로 하고 필요할 때 양방향 매핑을 추가한다.

 

 

 

방향(Direction) : 단방향, 양방향

다중성(Multiplicity) : 다대일, 일대다, 일대일

연관관계의 주인(Owner) : 객체 양뱡향 연관관계는 관리 주인이 필요

 

객체를 테이블에 맞추어 모델링

@Entity
 public class Member { 
     @Id @GeneratedValue
     private Long id;
     
     @Column(name = "USERNAME")
     private String name;
     
     @Column(name = "TEAM_ID") // 참조 대신에 외래 키를 그대로 사용
     private Long teamId; 
 } 
 
 @Entity
 public class Team {
     @Id @GeneratedValue
     private Long id;
     
     private String name; 

 }

객체 지향 모델링

@Entity
 public class Member { 
     @Id @GeneratedValue
     private Long id;
     
     @Column(name = "USERNAME")
     private String name;
     
     @ManyToOne
     @JoinColumn(name = "TEAM_ID") // 객체의 참조와 테이블의 외래 키를 매핑
     private Team team;
 } 
 
 @Entity
 public class Team {
     @Id @GeneratedValue
     private Long id;
     
     private String name; 

 }

 

객체를 테이블에 맞추어 모델링 vs 객체 지향 모델링

 

1. 멤버가 소속해있는 팀을 찾을때

// 객체를 테이블에 맞추어 모델링

// 멤버 조회
Member findMember = em.find(Member.class, member.getId());

// 해당 멤버 팀 id값 저장
Long findTeamId = findMember.getTeamId();

// 팀 조회(위에 저장한 팀 id값을 이용)
Team findTeam = em.find(Team.class, team.getId());




// 객체 지향 모델링

// 멤버 조회
Member findMember = em.find(Member.class, member.getId()); 

//참조를 사용해서 연관관계 조회
Team findTeam = findMember.getTeam();

 

'인강 > 자바 ORM 표준 JPA 프로그래밍 - 기본편' 카테고리의 다른 글

다양한 연관관계 매핑  (0) 2024.10.28
엔티티 매핑  (0) 2024.09.09

@Column

속성 설명 기본값
name 필드와 매핑할 테이블의 컬럼 이름 객체의 필드 이름
insertable
updatable
등록, 변경 가능 여부 설정 true
nullable null값 허용 여부 설정
false -> not null 제약조건 붙음
 
unique 해당 컬럼의 유니크 제약조건
이름이 랜덤하게 들어가서 사용 잘 안함
 
length 문자 길이 제약조건, String 타입에서만 사용 255

 

'인강 > 자바 ORM 표준 JPA 프로그래밍 - 기본편' 카테고리의 다른 글

다양한 연관관계 매핑  (0) 2024.10.28
연관관계 매핑  (0) 2024.09.10

- 클래스 내부 멤버변수에서 사용할 데이터 타입을 외부에서 지정하는 기법이다.
- 제네릭의 타입 인자로 기본형(int, double)은 사용할 수 없다.
- 제네릭은 extends 키워드를 붙여서 타입 매개변수를 제한하고 원하는 타입과 하위 타입들만 받도록 설정할 수 있다.
- 제네릭 메서드를 정의할 때는 메서드의 반환 타입 왼쪽에 <T>와 같이 타입 매개변수를 적어준다.
- 명확한 반환 타입이 필요할때는 제네릭 메서드 반환 타입이 없을때는 와일드카드를 사용하는게 좋다.

 

클래스 수준의 제네릭 타입 파라미터를 사용하는 메서드 vs 메서드 수준의 제네릭 타입 파라미터를 사용하는 제네릭 메서드

package genericTest;

public class Main2 {

    public static void main(String[] args) {
        GenericBox2<Integer> genericBox2 = new GenericBox2<>();

        // 클래스 수준의 제네릭 타입 파라미터를 사용하는 메서드
        genericBox2.genericTypeMethod(123); // value = 123
        //genericBox2.genericTypeMethod("123"); // !! 에러발생 !! GenericBox2객체에 Integer를 할당했기 때문에 

        // 메서드 수준의 제네릭 타입 파라미터를 사용하는 제네릭 메서드
        genericBox2.genericMethod2("kim"); // value = kim
        genericBox2.genericMethod2(123); // value = 123
        genericBox2.genericMethod2(true); // value = true
    }
}
package genericTest;

public class GenericBox2 <T>{

    public T genericTypeMethod (T value) {
        System.out.println("value = " + value);
        return value;
    }
    public <Z> Z genericMethod2 (Z value) {
        System.out.println("value = " + value);
        return value;
    }
}

 

제네릭 클래스 타입 제한 사용법

public class Generic<T extends parent> {

}

 

제네릭 메서드 사용법

public <T> T instanceMethod1 (T value) {                       
        System.out.println("value = " + value);
        return value;
}

public <S extends Number> S instanceMethod2 (S value) {         
	System.out.println("value = " + value);
	return value;
}

static <T> T genericStaticMethod1 (T value) {                 
	System.out.println("value = " + value);
	return value;
}

 

와일드카드를 사용한 메서드

public void wildCard (Box<?> value) {
	System.out.println("value.getValue() = " + value.getValue());
}

public void wildCard2 (Box<? extends Animal> value) {
	System.out.println("value.getValue() = " + value.getValue());
}

- 아래의 코드가 실행되도록 수정하세요.

 

1. Dog, Cat 클래스 추가
2. AnimalMethod 클래스에서 checkUp, bigger 제네릭 메서드 추가
3. checkUp메서드 body에 System.out.println(매개변수); 추가
4. bigger 메서드 호출시 size값이 더 큰 객체 출력

 

// (출력예시)

// checkUp 메서드 호출시
// Dog{name='강아지', size=200}
// Cat{name='고양이', size=100}

// bigger 메서드 호출후 result값 출력시
// result = Dog{name='강아지', size=200}

 

package genericMethod.quiz;

public class Main {

    public static void main(String[] args) {

        Dog dog = new Dog("강아지", 200);
        Cat cat = new Cat("고양이", 100);

        AnimalMethod.checkUp(dog);
        AnimalMethod.checkUp(cat);


        Animal result = AnimalMethod.bigger(dog, cat);
        System.out.println("result = " + result);
    }
}

'자바 문제 > 실습' 카테고리의 다른 글

제네릭 실습 문제  (0) 2024.07.30
다형성 실습 문제  (0) 2024.07.24
상속 실습 문제  (0) 2024.07.22
static 2  (0) 2024.07.17
static 1  (0) 2024.07.15

+ Recent posts