👉 기본 환경

- Language: Java

- IDE: Eclipse

 

 

⌨️ 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class Main {
 
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
 
        int N = Integer.parseInt(br.readLine());
 
        Map<String, Integer> map = new HashMap<>();
 
        for (int i = 0; i < N; i++) {
            String s = br.readLine();
            map.put(s, s.length());
        }
 
        String[] mapKeys = (String[]) map.keySet().toArray();
        Arrays.sort(mapKeys);
 
        List<Object> keys = new ArrayList<>();
        for (Object key : mapKeys) {
            keys.add(key);
        }
        Collections.sort(keys, ((k1, k2) -> (map.get(k1).compareTo(map.get(k2)))));
 
        for (Object key : keys) {
            bw.write(key + "\n");
        }
 
        bw.flush();
        bw.close();
    }
 
}
 
 
 

 

 

🖨️오류

 java.lang.ClassCastException: class [Ljava.lang.Object; cannot be cast to class [Ljava.lang.String; ([Ljava.lang.Object; and [Ljava.lang.String; are in module java.base of loader 'bootstrap')

 

 

📡 원인

Object[]를 String[]로 바로 형변환 할 수 없음

 

 

📰 해결 방법

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class Main {
 
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
 
        int N = Integer.parseInt(br.readLine());
 
        Map<String, Integer> map = new HashMap<>();
 
        for (int i = 0; i < N; i++) {
            String s = br.readLine();
            map.put(s, s.length());
        }
 
        String[] mapKeys = map.keySet().toArray(new String[0]);
        Arrays.sort(mapKeys);
 
        List<Object> keys = new ArrayList<>();
        for (Object key : mapKeys) {
            keys.add(key);
        }
        Collections.sort(keys, ((k1, k2) -> (map.get(k1).compareTo(map.get(k2)))));
 
        for (Object key : keys) {
            bw.write(key + "\n");
        }
 
        bw.flush();
        bw.close();
    }
 
}
 
 
 

String[] mapKeys = map.keySet().toArray(new String[0]);

    - Object[]를 String[]을 형변환하는 것이 아닌 개별 요소를 String으로 직접 지정하고 String[]에 저장

    - 요소 타입을 명시적으로 지정하면 map.keySet()에서 반환되는 요소들을 mapeys 배열에 복사

 

+ 배열의 크기를 0으로 지정한 이유

    - 실제 반환될 배열의 크기를 동적으로 조절하고자 0으로 지정

    - 컬렉션의 크기에 맞게 배열이 자동으로 생성되고 요소들이 복사되기 때문에 정확한 크기를 예측하거나 관리할 필요가 없음

 

+ String[] mapKeys = map.keySet().toArray(String s); 가 안되는 이유

    - toArray()의 매개변수는 T[] a이므로 배열을 전달하여 요소 타입을 추론하게 해야 함

 

 

 

📚 참고 자료

 

[Java] ArrayList의 toArray()

ArrayList는 자바로 개발을 하면서 가장 많이 쓰는 리스트의 구현 클래스 중 하나입니다. ArrayList 타입의 String 리스트를 배열로 변환하려 할때는 아래와 같이 사용합니다. ArrayList strs=new ArrayList(); st

jerry92k.tistory.com

 

이 글은 김영한의 [자바 ORM 표준 JPA 프로그래밍 - 기본편] 수강하며 정리한 글입니다.

 

👉 기본 환경

- Language: Java

- DB: H2 Database

- IDE: IntelliJ

 

 

1. Entity 상태

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
@Entity
public class Member {
 
    @Id @GeneratedValue
    @Column(name = "MEMBER_ID")
    private Long id;
 
    @Column(name = "USERNAME")
    private String name;
 
    @ManyToOne // Member : Team = Many : One
    @JoinColumn(name = "TEAM_ID"// JoinColum = FK
    private Team team;
    // FK가 있는 곳(Many to One에서 Many 부분)이 연관 관계의 주인
 
    public Long getId() {
        return id;
    }
 
    public void setId(Long id) {
        this.id = id;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public Team getTeam() {
        return team;
    }
 
    public void setTeam(Team team) {
        this.team = team;
    }
 
 
}
 
 
 

Member.java

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
@Entity
public class Team {
 
    @Id @GeneratedValue
    @Column(name = "TEAM_ID")
    private Long id;
    private String name;
 
    @OneToMany(mappedBy = "team"// mappedBy: 상대 Entity의 FK field 값
    private List<Member> members = new ArrayList<>();
 
    public Long getId() {
        return id;
    }
 
 
    public void setId(Long id) {
        this.id = id;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public List<Member> getMembers() {
        return members;
    }
 
    public void setMembers(List<Member> members) {
        this.members = members;
    }
 
 
}
 
 
 

Team.java

 

Member entity와 Team entity가 양방향으로 매핑되어있음

Member : Team = 다 : 1 관계

 

 

2-1. 데이터 저장

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public class Main {
    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
 
        EntityManager em = emf.createEntityManager();
 
        EntityTransaction tx = em.getTransaction();
        tx.begin();
 
 
        try {
 
            Member member = new Member();
            member.setName("Member1");
            em.persist(member);
 
            Team team = new Team();
            team.setName("TeamA");
            team.getMembers().add(member);
 
            em.persist(team);
 
            em.flush();
            em.clear();
            
            tx.commit();
        } catch (Exception e) {
            tx.rollback();
        } finally {
            em.close();
        }
 
 
        emf.close();
    }
 
}
 
 
 

- Member 객체 생성 후, persist

- Team 객체 생성 후, getter로 member list 호출 후 member 객체 추가

 

Team 객체에 Member를 매핑하였지만, Member 객체의 Team_id가 null값으로 입력됨

 

@OneToMany(mappedBy = "")

양방향 매핑에서 mappedBy 속성은 단순히 매핑되어있음을 안내해주는 역할일 뿐, 실제로 데이터를 매핑시켜주지 않음

 

 

2-2. 데이터 저장 - 수정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public class Main {
    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
 
        EntityManager em = emf.createEntityManager();
 
        EntityTransaction tx = em.getTransaction();
        tx.begin();
 
 
        try {
 
            Team team = new Team();
            team.setName("TeamA");
            em.persist(team);
 
            Member member = new Member();
            member.setName("Member1");
            member.setTeam(team);
            em.persist(member);
 
            em.flush();
            em.clear();
            
            tx.commit();
        } catch (Exception e) {
            tx.rollback();
        } finally {
            em.close();
        }
 
 
        emf.close();
    }
 
}
 
 
 

- Team 객체 생성 후, persist

- Member 객체 생성 및 team 객체 주입 후, persist

 

Member 객체에 매핑한 Team 객체의 Team_id가 입력됨

 

@ManyToOne
@JoinColumn(name = "TEAM_ID")

양방향 매핑에서 실제 데이터 입력을 담당하는 필드는 @Joincolumn이 선언되어있는 필드

 

 

3. 데이터 조회

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
public class Main {
    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
 
        EntityManager em = emf.createEntityManager();
 
        EntityTransaction tx = em.getTransaction();
        tx.begin();
 
 
        try {
 
            Team team = new Team();
            team.setName("TeamA");
            em.persist(team);
 
            Member member = new Member();
            member.setName("Member1");
            member.setTeam(team);
            em.persist(member);
 
//            em.flush();
//            em.clear();
 
            Team findTeam = em.find(Team.class, team.getId());
            List<Member> members = findTeam.getMembers();
 
            System.out.println("==========");
 
            for(Member m : members){
                System.out.println("member: " + m.getName());
            }
 
            System.out.println("==========");
            
            tx.commit();
        } catch (Exception e) {
            tx.rollback();
        } finally {
            em.close();
        }
 
 
        emf.close();
    }
 
}
 
 
 

- flush(), clear()를 제거하고, 같은 트랜잭션 내에서 1차 캐시에 저장된 team과 member를 바로 조회할 경우,

    member 객체에 매핑된 team 객체를 조회할 수 있지만, team 객체에서 매핑된 member 조회할 수 없음

- 1차 캐시 상태에서는 Team 객체와 Member 객체의 관계가 명시적으로 코드로 작성한 부분을 제외하고는 인식되지 않음

    ▶ 양방향으로 객체 주입

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
public class Main {
    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
 
        EntityManager em = emf.createEntityManager();
 
        EntityTransaction tx = em.getTransaction();
        tx.begin();
 
 
        try {
 
            Team team = new Team();
            team.setName("TeamA");
            em.persist(team);
 
            Member member = new Member();
            member.setName("Member1");
            member.setTeam(team);
            em.persist(member);
 
            team.getMembers().add(member);
 
//            em.flush();
//            em.clear();
 
            Team findTeam = em.find(Team.class, team.getId());
            List<Member> members = findTeam.getMembers();
 
            System.out.println("==========");
 
            for(Member m : members){
                System.out.println("member: " + m.getName());
            }
 
            System.out.println("==========");
            
            tx.commit();
        } catch (Exception e) {
            tx.rollback();
        } finally {
            em.close();
        }
 
 
        emf.close();
    }
 
}
 
 
 

 

 

4. 코드 리팩토링

양방향으로 값을 세팅해주는 과정(setTeam, addMember)에서 일부 값만 세팅하는 실수가 발생할 수 있음

▶ 연관관계 편의 메서드를 생성하여, 하나의 메서드로 2개의 값을 세팅

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public class Main {
    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
 
        EntityManager em = emf.createEntityManager();
 
        EntityTransaction tx = em.getTransaction();
        tx.begin();
 
 
        try {
 
            Team team = new Team();
            team.setName("TeamA");
            em.persist(team);
 
            Member member = new Member();
            member.setName("Member1");
            member.changeTeam(team);
            em.persist(member);
 
            Team findTeam = em.find(Team.class, team.getId());
            List<Member> members = findTeam.getMembers();
 
            System.out.println("==========");
            for(Member m : members){
                System.out.println("member: " + m.getName());
            }
            System.out.println("==========");
            
            tx.commit();
        } catch (Exception e) {
            tx.rollback();
        } finally {
            em.close();
        }
 
 
        emf.close();
    }
 
}
 
 
 

- setTeam() 대신 changeTeam을 활용하여, setTeam과 addMember 수행

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
@Entity
public class Member {
 
    @Id @GeneratedValue
    @Column(name = "MEMBER_ID")
    private Long id;
 
    @Column(name = "USERNAME")
    private String name;
 
    @ManyToOne // Member : Team = Many : One
    @JoinColumn(name = "TEAM_ID"// JoinColum = FK
    private Team team;
 
 
    public Long getId() {
        return id;
    }
 
    public void setId(Long id) {
        this.id = id;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public Team getTeam() {
        return team;
    }
 
    public void setTeam(Team team) {
        this.team = team;
    }
 
 
    public void changeTeam(Team team) {
        this.team = team;
        team.getMembers().add(this);
    }
 
}
 
 
 

 

cf. changeTeam() 대신 addMember() 사용 가능

⭐ 단, 연관관계 편의 메서드는 동일한 역할을 수행하므로 하나의 메서드만 생성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
@Entity
public class Team {
 
    @Id @GeneratedValue
    @Column(name = "TEAM_ID")
    private Long id;
    private String name;
 
    @OneToMany(mappedBy = "team"// mappedBy: 상대 Entity의 FK field 값
    private List<Member> members = new ArrayList<>();
 
 
    public Long getId() {
        return id;
    }
 
    public void setId(Long id) {
        this.id = id;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public List<Member> getMembers() {
        return members;
    }
 
    public void setMembers(List<Member> members) {
        this.members = members;
    }
 
    public void addMember(Member member) {
        member.setTeam(this);
        this.getMembers().add(member);
    }
 
}
 
 
 

 

👉 기본 환경

- Language: Java

- IDE: Eclipse

 

 

⌨️ 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    public static void main(String[] args) throws IOException {
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
 
       bw.write(method1({"hello""java""world"}));
 
        bw.flush();
        bw.close();
 
    }
 
    public static String method1(String[] sentence) {
       StringBuffer sb = new StringBuffer();
        for (String s : sentence) {
            sb.append(s);
        }
        return sb.toString();
    }
 
 
 

 

 

🖨️오류

Syntax error, insert 'SimpleName' to complete ArgumentList:

 

 

📡 원인

medthod1의 매개변수로 String[]이 전달되어야 함

{}로 객체 생성을 할 수 없음

 

 

📰 해결 방법

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    public static void main(String[] args) throws IOException {
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
 
        bw.write(method1(new String[]{"hello""java""world"}));
 
        bw.flush();
        bw.close();
 
    }
 
    public static String method1(String[] sentence) {
        StringBuffer sf = new StringBuffer();
        for (String s : sentence) {
            sb.append(s);
        }
        return sb.toString();
    }
 
 
 

new String[]으로 객체 생성 후, 매개변수로 String[] 전달

 

👉 기본 환경

- Language: Java

- IDE: Eclipse

 

 

⌨️ 코드

1
2
3
4
5
        int[] intArr = new int[3];
        while (intArr.length-- > 0) {
 
        }
 
 
 

 

 

🖨️오류

java.lang.Error: Unresolved compilation problem: The final field array.length cannot be assigned

 

 

📡 원인

array의 length 값은 final 값으로 변경할 수 없음

 

 

📰 해결 방법

1
2
3
4
5
6
        int[] intArr = new int[3];
        int len = intArr.length;
        while (len-- > 0) {
 
        }
 
 

새로운 변수를 선언해서 length값을 넣고, 해당 변수의 값을 변경

 

이 글은 김영한의 [자바 ORM 표준 JPA 프로그래밍 - 기본편] 수강하며 정리한 글입니다.

 

👉 기본 환경

- Language: Java

- DB: H2 Database

- IDE: IntelliJ

 

 

1. 객체를 테이블에 맞춰 모델링

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package jpa_basic;
 
import javax.persistence.*;
import java.util.Date;
 
@Entity
public class Member {
 
    @Id @GeneratedValue
    @Column(name = "MEMBER_ID")
    private Long id;
 
    @Column(name = "USERNAME")
    private String name;
 
    @Column(name = "TEAM_ID")
    private Long teamId;
 
    public Long getId() {
        return id;
    }
 
    public void setId(Long id) {
        this.id = id;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public Long getTeamId() {
        return teamId;
    }
 
    public void setTeamId(Long teamId) {
        this.teamId = teamId;
    }
 
 
}
 
 
 

테이블에서 외래키 역할을 하는 teamId가 필드로 선언

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import java.util.List;
 
public class Main {
 
    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
 
        EntityManager em = emf.createEntityManager();
 
        // JPA의 모든 데이터 변경은 transaction 안에서 실행
        EntityTransaction tx = em.getTransaction();
        tx.begin();
 
        try {
 
            // 객체를 테이블에 맞춰 모델링
 
            Team team = new Team();
            team.setName("TeamA");
            em.persist(team);
 
            Member member = new Member();
            member.setName("Member1");
            member.setTeamId(team.getId());
            em.persist(member);
 
            Member findMember = em.find(Member.class, member.getId());
 
            Long findTeamId = findMember.getTeamId();
            Team findItem = em.find(Team.class, findTeamId);
 
            tx.commit();
        } catch (Exception e) {
            tx.rollback();
        } finally {
            em.close();
        }
 
 
        emf.close();
 
    }
 
}
 
 
 

* DB에 맞춰진 설계 방식

    - Member와 Team 사이의 연관관계를 맺는 대신에 teamId를 사용하여 직접적인 관계를 표현

    - OOP에서는 객체 간의 관계를 통해 참조하는 것이 일반적

    - ID 값보다는 실제 객체의 참조를 사용하여 관계를 표현하는 것이 객체 지향적인 방식

    - 객체 간의 연관관계를 활용하여 코드의 가독성과 유지보수성을 높일 수 있음

 

 

2. 객체 지향 모델링

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
package jpa_basic;
 
import javax.persistence.*;
import java.util.Date;
 
@Entity
public class Member {
 
    @Id @GeneratedValue
    @Column(name = "MEMBER_ID")
    private Long id;
 
    @Column(name = "USERNAME")
    private String name;
 
    @ManyToOne // Member : Team = Many : One
    @JoinColumn(name = "TEAM_ID"// JoinColumn = FK
    private Team team;
 
    public Long getId() {
        return id;
    }
 
    public void setId(Long id) {
        this.id = id;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public Team getTeam() {
        return team;
    }
 
    public void setTeam(Team team) {
        this.team = team;
    }
 
}
 
 
 

Entity Team을 필드로 선언하여 연관관계 매핑

Entity 간의 관계 설정(@ManyToOne, Member : Team = 다 : 1)

관계 설정 시, FK 설정(@JoinColumn)

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package jpa_basic;
 
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import java.util.List;
 
public class Main {
    public static void main(String[] args) {
 
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
 
        EntityManager em = emf.createEntityManager();
 
        EntityTransaction tx = em.getTransaction();
        tx.begin();
 
        try {
 
            // 객체 지향 모델링
            Team team = new Team();
            team.setName("TeamA");
            em.persist(team);
 
            Member member = new Member();
            member.setName("Member1");
            member.setTeam(team);
            em.persist(member);
 
            Member findMember = em.find(Member.class, member.getId());
 
            Team findTeam = findMember.getTeam();
 
            tx.commit();
        } catch (Exception e) {
            tx.rollback();
        } finally {
            em.close();
        }
 
 
        emf.close();
    }
 
}
 
 
 

ID 값을 사용하는 대신 Team 객체 사용