'인강 > 자바 ORM 표준 JPA 프로그래밍 - 기본편' 카테고리의 다른 글
연관관계 매핑 (0) | 2024.09.10 |
---|---|
엔티티 매핑 (0) | 2024.09.09 |
연관관계 매핑 (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;
}
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();
다양한 연관관계 매핑 (0) | 2024.10.28 |
---|---|
엔티티 매핑 (0) | 2024.09.09 |
@Column
속성 | 설명 | 기본값 |
name | 필드와 매핑할 테이블의 컬럼 이름 | 객체의 필드 이름 |
insertable updatable |
등록, 변경 가능 여부 설정 | true |
nullable | null값 허용 여부 설정 false -> not null 제약조건 붙음 |
|
unique | 해당 컬럼의 유니크 제약조건 이름이 랜덤하게 들어가서 사용 잘 안함 |
|
length | 문자 길이 제약조건, String 타입에서만 사용 | 255 |
다양한 연관관계 매핑 (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());
}
- 다형적 참조의 핵심은 부모는 자식을 품을 수 있다는 것이다.
- 하나의 변수 타입으로 다양한 자식 인스턴스를 참조할 수 있다.
- 다형적 참조시 오버라이딩 된 메서드가 항상 우선권을 가진다.
- 자식 클래스 타입에서 부모 클래스 타입으로 형 변환
- 자식 인스턴스를 생성하면 부모도 같이 생성되기 때문에 업캐스팅시 문제가 발생하지 않는다.
- 그래서 업캐스팅 사용시 생략이 가능하다.
- 부모 클래스에서 자식 클래스 타입으로 형 변환
- 부모 인스턴스를 생성시 하위 자식은 생성되지 않기때문에 문제가 발생한다.
- 다운캐스팅 사용시 생략할 수 없다.
Child child = new Child();
// 업캐스팅
Parent parent = (Parents) child;
Parent parent = child; // 업캐스팅시 () 생략 권장
// 다운캐스팅
Child child1 = (Child) parent;
- 추상 클래스를 선언할때 abstract 키워드를 붙여주면 된다.
- 추상 클래스는 직접 인스턴스 생성을 못한다.
ex) AbstractA abstract = new AbstractA() -> 불가능
- 추상 클래스는 일반 클래스와 동일하게 생성자, 인스턴스 멤버변수, 메서드 선언이 가능하다.
- 추상메서드가 하나라도 있는 클래스는 추상 클래스로 선언해야 한다.
- 추상 메서드는 상속 받은 자식 클래스에서 반드시 오버라이딩 해서 사용해야 한다.
- 동작이 정의되어 있지 않은 추상 메서드를 포함하고 있기 때문에
- 추상클래스를 상속받아 자식 클래스들이 각자의 방식으로 구현하는게 목적이기 때문에
부모 클래스(슈퍼 클래스) : 상속을 통해 자신의 필드와 메서드를 다른 클래스에 제공하는 클래스
자식 클래스(서브 클래스) : 부모 클래스로부터 필드와 메서드를 상속받는 클래스
- 공통으로 사용되는 속성 혹은 기능을 상위 클래스에 정의하여 공유함으로써 중복 코드를 줄일 수 있다.
- 자식클래스는 1개의 부모클래스만 상속받을 수 있다.
- 부모 클래스로부터 상속받은 필드나 메서드를 접근할때는 super 키워드를 사용한다.
- 자식 객체에서 기능을 호출시 자식 객체에서 해당 기능이 있는지 찾고 찾지못한다면 부모 객체에서 찾는다.
- 자바의 모든 클래스는 최상위 클래스인 Object클래스를 상속받는다.
- 자식 클래스의 인스턴스 생성시 부모 인스턴스도 같이 생성된다.
- 자식 인스턴스 생성시 부모 생성자가 호출된다.(하지만 기본 생성자는 생략 가능 -> 자바에서 자동으로 만들어 주기 때문)
- 부모 클래스의 메서드를 자식 클래스에서 재정의함으로써 다형성을 구현할 수 있다.- 부모 클래스의 메서드가 자식 클래스의 요구사항에 맞지 않은 경우 자식 클래스에서 해당 메서드를 재정의 할 수 있다.
- 메서드 이름이 같아야 한다.
- 메서드 매개변수(파라미터) 타입, 순서, 개수가 같아야 한다.
- 반환타입이 같아야 한다.
- 상위 클래스의 메서드보다 더 많은 체크 예외를 선언할 수 없다.
- final 메서드는 재정의를 금지한다.
- 부모 클래스의 메서드보다 접근제어자가 제한적이어서는 안된다.
(ex)
부모클래스 : protected, 자식클래스 : private, default -> 불가능
부모클래스 : protected , 자식클래스 : public, protected -> 가능
접근 제어자 이론 문제
https://rnwns2.tistory.com/145
접근 제어자 실습 문제
- 자신의 인스턴스에 접근할때 사용
- 보통 this.을 사용하여 멤버 변수에 접근함
- 메서드, 생성자에서 사용하는 매개변수(파라미터)이름과 해당 클래스 멤버 변수명이 같을때 구분하기 위해 사용
public class Student {
public String name;
public String grade;
public Student(String name, String grade) {
this.name = name;
this.grade = grade;
}
}
- 생성자의 목적은 객체 초기화 이다.
- 생성자의 이름은 클래스 이름과 같아야 한다.
- 생성자는 반환 타입이 없다.
- 생성자는 인스턴스를 생성한 후 바로 호출된다.(객체당 한번만 호출)
- 개발자가 생성자를 작성하지 않으면 컴파일러가 자동으로 기본 생성자 삽입
- 생성자는 오버로딩 가능하다
- 직접 정의한 생성자를 호출 하지 않을경우 컴파일 오류가 발생하기 때문에 필수값 입력을 보장할 수 있다.
- 생성자 내부에서만 사용할 수 있다.
- 생성자의 첫 줄에서만 this()를 사용할 수 있다.
public class Student {
public String name;
public String grade;
Student(String name, String grade) {
this.name = name;
this.grade = grade;
}
Student(String name) {
this(name, "A");
}
}
public class Main {
public static void main(String[] args) {
// Student student0 = new Student(); // error : no suitable constructor found for Student(no arguments)
Student student1 = new Student("Kim");
Student student2 = new Student("Kim", "C");
Student[] students = {student1, student2};
for (Student student : students) {
System.out.println("student.name = " + student.name);
System.out.println("student.grade = " + student.grade);
}
}
}
멤버 변수 : 클래스 내부에서 선언
지역 변수 : 메서드 내부에서 선언, 매개변수도 지역 변수의 한 종류
- 멤버 변수(자동 초기화)
- 개발자가 초기값을 지정할 수 있음
- 초기값을 지정하지 않았을 경우
- int -> 0
- boolean -> false
- 참조형 -> null
// 멤버 변수 초기화
class Test {
int num;
String str;
boolean check;
String[] strArr = new String[5];
int[] numArr = new int[5];
}
public class Main {
public static void main(String[] args) {
Test test = new Test();
System.out.println("test.num = " + test.num); // 0
System.out.println("test.str = " + test.str); // null
System.out.println("test.check = " + test.check); // false
System.out.println("test.check = " + test.strArr[0]); // null
System.out.println("test.check = " + test.strArr[3]); // null
System.out.println("test.check = " + test.numArr[0]); // 0
System.out.println("test.check = " + test.numArr[3]); // 0
}
}
- 지역 변수(수동 초기화)
- 항상 직접 초기화해야 한다.
// 지역변수 초기화 안했을 경우
int num;
String str;
boolean check;
String[] strArr = new String[5];
int[] numArr = new int[5];
System.out.println("num = " + num); // error : variable num might not have been initialized
System.out.println("str = " + str); // error : variable str might not have been initialized
System.out.println("check = " + check); // error : variable check might not have been initialized
System.out.println("check = " + strArr[0]); // null
System.out.println("check = " + strArr[3]); // null
System.out.println("check = " + numArr[0]); // 0
System.out.println("check = " + numArr[3]); // 0