@WebMvcTest(AnswerController.class)
public class QuestionControllerTest {
@Autowired
private MockMvc mockMvc;
@Autowired
private Gson gson;
@MockBean
private QuestionService questionService;
@MockBean
private QuestionMapper questionMapper;
// 테스트 코드들
}
@WebMvcTest(테스트하려는 컨트롤러의 클래스)
해당 어노테이션을 사용하면 컨트롤러 테스트에 필요한 빈만 사용하여 테스트를 수행한다.
@SpringBootTest 어노테이션은 등록된 모든 빈을 사용하여 테스트를 수행하기 때문에
속도적인 측면에서 슬라이스 테스트에 사용하긴 효율적이지 못하다.
MockMvc
컨트롤러를 테스트하기 위해 API를 호출하고 검증하는 기능을 제공한다.
Gson
객체를 json 형식으로 바꿀 때 사용한다. (json 형식 이외에도 다른 형식으로도 바꿀 수 있다.)
@MockBean
테스트에 사용할 목 객체(가짜 객체)를 빈으로 등록하여 실제 빈 대신에 동작하게 한다.
스프링 테스트 프레임워크와 함께 쓰이며 통합 테스트에서 스프링 빈을 목 객체로 대체하려 사용한다.
@MockBean과 @Mock
두 어노테이션 모두 테스트 과정에 사용 할 목객체를 생성하고 대체하는 것은 똑같지만
어떤 프레임워크와 같이 사용되고 어느 테스트에 사용되는지가 다르다.
@MockBean 어노테이션은 위에서 언급했듯이 스프링 테스트프레임워크와 함께 사용하여
주로 통합 테스트에 사용된다.
@Mock어노테이션은 Mockito 프레임워크와 함께 사용되어 주로 단위 테스트에 사용된다.
컨트롤러 테스트에서는 스프링에서 제공하는 WebMvcTest를 사용하기 때문에
@MockBean 어노테이션을 사용한다.
@Test
public void postQuestionTest() throws Exception {
long memberId = 1L;
Member member = new Member();
member.setMemberId(memberId);
Question question = new Question();
question.setQuestionTitle("Question Title");
question.setQuestionText("Question Text");
question.setQuestionStatus(Question.QuestionStatus.QUESTION_REGISTERED);
question.setQuestionOpen(Question.QuestionOpen.SECRET);
question.setMember(member);
QuestionDto.Post postDto = new QuestionDto.Post(
"Question Title",
"Question Text",
Question.QuestionOpen.PUBLIC
);
String requestContent = gson.toJson(postDto);
given(questionMapper.questionPostToQuestion(Mockito.any(QuestionDto.Post.class)))
.willReturn(new Question());
given(questionService.createQuestion(Mockito.any(Question.class), Mockito.anyLong()))
.willReturn(question);
mockMvc.perform(
post(root + "/create")
.param("memberId", String.valueOf(memberId))
.contentType(MediaType.APPLICATION_JSON)
.content(requestContent)
)
.andExpect(status().isCreated())
.andExpect(jsonPath("$.questionTitle").value(question.getQuestionTitle()));
}
POST 컨트롤러의 간단한 테스트 코드를 나눠서 살펴보겠다.
long memberId = 1L;
Member member = new Member();
member.setMemberId(memberId);
Question question = new Question();
question.setQuestionTitle("Question Title");
question.setQuestionText("Question Text");
question.setQuestionStatus(Question.QuestionStatus.QUESTION_REGISTERED);
question.setQuestionOpen(Question.QuestionOpen.SECRET);
question.setMember(member);
@Service
public class MemberService {
private final MemberRepository memberRepository;
public MemberService(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
}
위와 같은 구조의 서비스 클래스를 테스트 해보자
@ExtendWith(MockitoExtension.class)
public class MemberServiceTest {
@Mock
private MemberRepository memberRepository;
@InjectMocks
private MemberService memberService;
// 테스트 코드 생략
}
서비스 슬라이스 테스트는 기본적으로 위와 같은 양식을 가진다.
@ExtendWith(추가할 확장 클래스)
JUnit5의 확장 모델을 사용하기 위해 사용하는 어노테이션이다.
현재 테스트 클래스에서는 Mockito 확장을 추가하기 위해 사용하였다.
@Mock
컨트롤러 테스트에서 알아봤듯이 Mockito 프레임워크를 사용할 때
목 객체를 생성하기 위한 어노테이션이다.
@InjectMocks
@Mock 어노테이션이 적용된 객체들을 해당 어노테이션이 적용된 객체에 주입한다.
서비스 클래스에서 의존관계를 주입하는 것과 같은 작업이라고 볼 수 있다.
@Test
public void saveMemberTest() throws Exception{
Member member = new Member();
member.setMemberName("이름");
member.setMemberId(1L);
member.setMemberEmail("test@email.com");
given(memberRepository.save(Mockito.any(Member.class))).willReturn(member);
assertThat(
memberService.createMember(member).getMemberName(),
is(equalTo(member.getMemberName()))
);
}
다대일 관계의 반대 방향은 항상 일대다 관계이며 일대다 관계의 반대 방향도 다대일 관계다.
데이터베이스에서 일대다 관계에서 외래 키는 항상 다쪽이 가지고 있기 때문에
객체의 양방향 관계에서의 주인도 항상 다쪽이다.
양방향 연관관계는 항상 서로를 참조해야 한다.
setTeam, addMember 같은 편의 메서드를 작성하는 것이 좋지만
양쪽에 모두 작성하는 경우에는 무한루프에 빠질 수 있으니 검사해줘야 한다.
OneToMany
일대다 관계는 엔티티를 하나 이상 참조할 수 있어서 컬렉션 타입을 사용한다.
일대다 단방향 관계를 매핑할 때 @JoinColumn 어노테이션을 명시하지 않으면
연결 테이블을 중간에 두고 연관관계를 관리하는 조인 테이블 전략을 사용하여
반드시 명시해주는게 좋다.
일대다 단방향 매핑은 결국 외래키를 직접 가지고 있는 것이 아니기 때문에
연관관계 처리를 위한 UPDATE SQL을 추가로 실행해야 한다.
그래서 일대다 단방향 매핑은 반대 테이블의 외래 키를 관리해야 하기 때문에
성능과 관리적인 부분에서 좋지 않다.
일대다 단방향 매핑보다는 관리해야 하는 외래 키가 본인 테이블에 있는
다대일 양방향 매핑을 사용하는 것이 좋다.
OneToMany : ManyToOne (일대다 양방향)
다대일 양방향 매핑에서 연관관계의 주인은 항상 다쪽인 ManyToOne이기에
@ManyToOne 속성에는 mappedBy가 없는 것이다.
일대다 양방향 매핑을 사용할 일이 없지만 아래와 같이 매핑 할 수는 있다.
public class Team {
// 기존 코드 생략
@OneToMany
@JoinColumn(name = "TEAM_ID")
private List<Member> members = new ArrayList<Member>();
}
public class Member {
// 기존 코드 생략
@ManyToOne
@JoinColumn(name = "TEAM_ID", insertable = false, updatable = false)
private Team team;
}
위의 코드처럼 양쪽 모두에 같은 외래키를 사용하게 매핑을 하는데
이때 다쪽의 외래키를 읽기 전용으로 만들어 양쪽에서 같은 외래키를 관리하지 못하게 한다.
일대다 양방향이라기 보단 반대쪽은 읽기 전용으로 만들기 때문에
일대다 단방향 매핑이 가지는 단점을 그대로 가셔서 다대일 양방향 매핑을 사용하는 것이 좋다.
OneToOne
한 명의 회원이 하나의 장바구니만 가지는 것과 같은 관계로
아래와 같은 특징을 가지고 있다.
일대일 관계에서는 반대 쪽도 항상 일대일 관계다.
둘 중 어느 곳이나 외래 키를 가질 수 있다.
일대일 관계는 둘 다 외래키를 가질 수 있기 때문에 누가 외래키를 가질지 지정해야한다.
주 테이블에 외래 키를 두는 방법
주 객체가 대상 테이블을 참조하는 것처럼 주 테이블(회원)이 장바구니를 참조한다.
외래키를 객체 참조와 비슷하게 사용할 수 있어서 객체지향 개발자들이 선호하며
주 테이블만 확인해도 연관관계를 확인 할 수 있다.
@Entity
public class Member {
// 기본 필드 생략
@OneToOne
@JoinColumn(name = "LOCKER_ID")
private Locker locker;
}
@Entity
public class Locker {
@Id
@GeneratedValue
@Column(name = "LOCKER_ID")
private Long id;
}
위의 코드처럼 단방향으로 매핑하거나
@Entity
public class Locker {
// 기존코드 생략
@OneToOne(mappedBy = "locker")
private Member member;
}
위의 코드처럼 양방향으로 매핑할 수 있다.
양방향 매핑이니 당연히 연관관계의 주인을 설정해줘야하는데
주 테이블인 멤버 엔티티의 외래키 컬럼을 주인으로 설정한다.
대상 테이블에 외래 키를 두는 방법
JPA에서는 일대일 관계에서 대상 테이블에 외래 키가 있는 단방향 관계를 지원하지 않기 때문에
대상 테이블에서 주 테이블로 단방향 관계를 수정하거나
양방향 관계로 만들고 대상 테이블을 연관관계의 주인으로 설정해야 한다.
@Entity
public class Member {
// 기본 필드 생략
@OneToOne(mappedBy = "member")
private Locker locker;
}
@Entity
public class Locker {
// 기본 필드 생략
@OneToOne
@JoinColumn(name = "MEMBER_ID")
private Member member;
}
위와 같이 일대일 매핑에서 대상 테이블에 외래키를 두기 위해선
양방향으로 설정한 후에 연관관계의 주인을 주 테이블이 아닌
대상 테이블로 설정한다.
ManyToMany
관계형 데이터베이스에서는 테이블 2개로 다대다 관계를 표현할 수 없기 때문에
다대다 관계를 다대일 관계로 풀어내는 연결 테이블을 사용하지만
객체는 테이블과 다르게 객체 2개로 다대다 관계를 만들 수 있다.
단방향
@Entity
public class Member {
// 기본 필드 생략
@ManyToMany
@JoinTable(name = "MEMBER_PRODUCT", joinColumns = @JoinColumn(name = "MEMBER_ID"),
inverseJoinColumns = @JoinColumn(name = "PRODUCT_ID"))
private List<Product> products = new ArrayList<Product>();
}
위와 같이 @ManyToMany 어노테이션을 사용하여 다대다 단방향 관계를 설정할 수 있으며
@JoinTable 어노테이션을 사용하여 연결 테이블을 바로 매핑할 수 있다.
@JoinTable의 속성은 아래와 같다.
name : 연결 테이블을 지정
joinColumns : 현재 방향인 회원과 매핑할 조인 컬럼 정보를 지정 (회원 테이블의 기본키)
inverseJoinColumns : 반대 방향인 상품 테이블과 매핑할 조인 컬럼 정보를 지정 (상품 테이블의 기본키)
양방향
@Entity
public class Product {
// 기본 필드 생략
@ManyToMany(mappedBy = "products")
private List<Member> members;
}
@Entity
public class Member {
// 기존 코드 생략
public void addProduct(Product product) {
products.add(product);
product.getMembers().add(this);
}
}
member.addProduct(product);
@ManyToMany 어노테이션을 사용한 매핑의 단점
어노테이션을 사용하여 연결 테이블을 자동으로 매핑하면 편리하지만
관계를 맺는 양쪽 테이블의 기본키만 외래키로 가지고 있기 때문에
추가적인 컬럼이 필요한 경우 추가할 수가 없다.
그래서 N:M 관계를 직접 연결 테이블을 추가하여 매핑하는 것이 좋다.
만약 회원과 주문이 N:M 관계라면
회원N : M주문 >> 회원1 : N:연결 테이블M : 1주문 형태로 바꿀 수 있다.
@Entity
public class Member {
@OneToMany(mappedBy = "member")
private List<MemberProducts> memberProducts;
}
@Entity
@IdClass(MemberProductId.class)
public class MemberProduct {
@Id
@ManyToOne
@JoinColumn(name = "MEMBER_ID")
private Member member;
@Id
@ManyToOne
@JoinColumn(name = "PRODUCT_ID")
private Product product;
}
@Entity
public class Product {
@OneToMany(mappedBy = "product")
private List<MemberProducts> memberProducts;
}
위의 코드는 다대다 양방향 관계를 코드로 표현한 예시다.
만약 회원상품 엔티티처럼 복합 키를 사용하는 경우에는
식별자 클래스가 추가로 필요하다.
public class MemberProductId implements Serializable {
// 회원멤버 엔티티의 member / product와 연결
private String member;
private String product;
// hashCode, equals 메서드 오버라이딩 하기
}
위의 코드처럼 복합 키는 별도의 식별자 클래스를 사용해서 만들어야 하며
Serializable을 구현하여야 하며 hashCode, equals 메서드를 구현해야 하고
기본 생성자가 있어야 하며 해당 클래스는 public이어야 한다.
@Entity
public class Order {
@Id
@GeneratedValue
@Column(name = "ORDER_ID")
private Long id;
@ManyToOne
@JoinColumn(name = "MEMBER_ID")
private Member member;
@ManyToOne
@JoinColumn(name = "PRODUCT_ID")
private Product product;
}
@Entity
@Table
@Getter @Setter
public class Member {
@Id
@Column(name = "member_id")
private int id;
@Column(name = "member_name")
private String memberName;
@ManyToOne
@JoinColumn(name = "team_id")
private Team team;
}
@Entity
@Table
@Getter @Setter
public class Team {
@Id
@Column(name = "team_id")
private int Id;
@Column(name = "team_name")
private String teamName;
}
하지만 객체에서는 참조하고자 하는 필드에서
팀 객체를 필드로 선언하여 연관관계를 맺는다.
테이블과는 다르게 객체에서의 연관관계의 방향성은
객체를 참조한 쪽에서만 접근할 수 있는 단방향 관계다.
참조를 통한 연관관계는 언제나 단방향이기에 양방향으로 만들려면
반대쪽에서도 객체 참조를 해줘야한다.
하지만 이건 엄밀히 따진 서로 다른 단방향 관계 두 개라고 보는게 맞다.
Member member1 = new Member(1,"고길동");
Member member2 = new Member(2,"신짱구");
Team team1 = new Team(1,"팀1");
member1.setTeam(team1); // Member 객체의 Setter를 통해 연관관계 설정
member2.setTeam(team1);
Team findTeam = member1.getTeam(); // Member 객체의 Getter를 통해 객체 참조 탐색
객체는 위와 같이 참조를 사용해 연관관계를 탐색하며
이러한 탐색을 객체 그래프 탐색이라고 한다.
다대일 관계 매핑
@ManyToOne
@JoinColumn(name = "team_id")
private Team team;
참조하고자 하는 객체의 필드에서 참조하려는 객체를 필드에 선언한다.
해당 필드에는 @ManyToOne 어노테이션과 @JoinColumn 어노테이션을 추가한다.
@ManyToOne
다대일 관계를 정의할 때 사용하는 어노테이션으로
하나의 팀(One)에 여러 멤버(Many)가 속할 수 있으니
위의 코드에서는 Many(Member) To One(Team)이라고 볼 수 있다.
아래와 같은 속성들을 사용할 수 있다.
optional : 기본값은 true로 false로 설정하면 연관된 엔티티가 항상 있어야 함
fetch : 글로벌 패치 전략을 설정한다. 기본값은 FetchType.Eager
cascade : 영속성 전이 기능을 사용한다
targetEntity : 연관된 엔티티의 타입 정보를 설정한다. 거의 사용하지 않음
@JoinColumn
외래키 를 매핑할 때 사용하는 어노테이션
아래와 같은 속성들을 사용할 수 있다.
name : 매핑할 외래 키 이름을 지정하며 미지정시 필드명_참조하는 기본 키 컬럼명
referencedColumnName : 외래 키가 참조하는 대상 테이블의 컬럼명
foreignKey(DDL) : 외래 키 제약조건을 직접 지정하며 테이블을 생성할 때만 사용
추가로 @Column 어노테이션의 속성도 사용가능
연관관계 사용
저장
Team team1 = new Team(1, "팀1"); // 비영속
em.persist(team1); // 영속
Member member1 = new Member(1, "홍길동"); // 비영속
member1.setTeam(team1); // 비영속 연간관계 설정
em.persist(member1); // 영속
JPA에서 엔티티를 저장하려면 연관된 모든 엔티티까지 영속 상태여야 하기 때문에
팀과 멤버 엔티티를 모두 영속 상태로 만든다.
조회
연간관계가 있는 엔티티의 조회 방법은 두 가지가 있다.
Team findTeam = member1.getTeam();
첫 번째 방법은 이전에 살펴보았던 객체 그래프 탐색이 있다.
필드에 참조하고 있는 객체를 사용하여 조회한다.
String jpql = "select m from Member m join m.team t where t.name = :teamName"
List<Member> resultList = em.createQuery(jpql, Member.class)
.setParameter("teamName", "팀1");
.getResultList();
두 번째 방법은 객체지향 쿼리인 JPQL을 사용하는 방법이다.
객체 참조 방식으로는 데이터베이스의 조인을 사용할 수 없었지만
이 방식을 사용하면 조인을 사용하여 조회할 수 있다.
String jpql = "select m from Member m join m.team t where t.name = :teamName"
위의 코드를 살펴보면 변수 jpql에 쿼리문을 담아두는데
여기서 사용되는 m과 t는 각각 멤버와 팀 테이블의 별칭을 지정한 것이며
:teamName 같은 부분은 이후에 파라미터로 값을 받아올 부분이다.
쿼리문으로 변환하면 아래와 같다.
SELECT * FROM MEMBER AS M JOIN TEAM ON M.TEAM_ID = T.TEAM_ID
@Entity
@Table
@Getter @Setter
public class Team {
@Id
@Column(name = "team_id")
private int Id;
@Column(name = "team_name")
private String teamName;
@OneToMany(mappedBy = "team")
private List<Member> members = new ArrayList<Member>();
}
멤버는 여러 멤버가 하나의 팀에 속하는 것이니 @ManyToOne 어노테이션을 사용했다면
팀은 하나의 팀이 여러 멤버를 가지니 @OneToMany 어노테이션을 사용한다.
또한 멤버는 하나의 팀만 가지니 팀 객체를 하나만 가지는 필드를 선언했다면
팀은 여러 멤버를 가지는 리스트 필드를 선언한다.
일대다 컬렉션 조회
Team team = em.find(Team.class, 1);
List<Member> members = team.getMembers();
일대다 컬렉션도 마찬가지로 객체 그래프 탐색을 이용해서 조회한다.
연관관계의 주인
데이터베이스에서는 외래 키 하나 만으로 양방향 관계를 맺을 수 있지만
객체는 두 개의 단방향 관계를 사용하여 양방향 관계를 흉내내는 것만 가능하다.
하지만 객체를 양방향으로 만들면 참조는 둘인데 외래 키가 하나인 경우가 되기에
둘 사이에 차이가 발생하는 문제가 생긴다.
이를 해결하기 위해 두 객체의 연관관계 중 하나를 정해서
테이블의 연관관계를 관리하게 하고 이러한 역할을 연관관계의 주인이라 한다.
양방향 매핑 규칙
양방향 매핑을 하는 경우 두 연관관계 중 하나를 무조건 연관관계의 주인으로 정해야 한다.
연관관계의 주인만 데이터베이스 연관관계와 매핑되어 외래 키를 관리할 수 있게 만들고
나머지 반대 쪽은 읽기만 할 수 있게 만들어 위에서 언급한 차이를 없앤다.
public class Member {
// 기존 코드 생략
@ManyToOne
@JoinColumn(name = "team_id")
private Team team;
}
public class Team {
// 기존 코드 생략
@OneToMany(mappedBy = "team")
private List<Member> members = new ArrayList<Member>();
}
위의 코드처럼 연관관계의 주인인 Member 엔티티의 필드에는
mappedBy 속성을 사용하지 않고
주인이 아닌 Team 엔티티의 필드에는
mappedBy 속성을 사용하여 연관관계의 주인을 Member 엔티티의 team 필드로 지정한다.
즉, 연관관계의 주인은 테이블에 외래 키가 있는 곳으로 지정해야 한다.
멤버는 팀을 옮길 수 있으니 수정권한이 필요하지만
팀은 멤버를 옮길 수 없으니 수정권한이 필요 없다고 볼 수 있다.
다대일과 일대다 관계에서는 항상 다 쪽이 외래키를 가진다.
양방향 연관관계 저장
Team team1 = new Team(1, "팀1");
em.persist(team1);
Member member1 = new Member(1, "홍길동");
member1.setTeam(team1);
em.persist(member1);
위의 코드를 보면 단방향 연관관계에서의 코드와 완전히 일치하지만
이 코드가 양방향 연관관계를 저장하는 방식이다.
연관관계의 주인만 연관관계의 작업이 가능하기에
팀 엔티티가 아닌 멤버 엔티티를 통해 작업하는 것이다.
양방향 연관관계의 주의점
Member member1 = new Member(1, "홍길동");
em.persist(member1);
Team team1 = new Team(1, "팀1");
team1.getMembers().add(member1);
em.persist(team1);
위의 코드처럼 연관관계의 주인이 아닌 곳에서 값을 입력하는 경우에는
읽기전용이기 때문에 값이 추가되지 않는다.
public class Member {
// 기존 코드 생략
@ManyToOne
@JoinColumn(name = "team_id")
private Team team;
}
public class Team {
// 기존 코드 생략
@OneToMany(mappedBy = "team")
private List<Member> members = new ArrayList<Member>();
}
객체까지 고려해서 주인이 아닌 곳에도 값을 입력하는 것이 좋고,
객체의 양방향 연관관계는 반드시 양쪽 모두 관계를 맺어줘야 한다.
연관관계 편의 메서드
기존의 연관관계의 주인인 쪽의 Setter 메서드는 자신 쪽의 객체의 값만 수정하여
반대 쪽의 객체에는 값이 입력되지 않는다.
이러한 문제를 해결하기 위해 Setter를 수정하는데
이렇게 양쪽에 값을 추가하게수정된 Setter를 편의 메서드라고 부른다.
수정된 코드는 아래와 같다.
public void SetTeam(Team team) {
// 기존의 팀이 있다면 연관관계를 제거
if(this.team != null) {
this.team.getMembers().remove(this);
}
// 주인뿐만 아니라 반대 쪽의 객체에도 값을 추가
this.team = team;
team.getMembers().add(this);
}
SEQUENCE:데이터베이스 시퀀스를 사용해서 할당 (Oracle, PostgreSQL, DB2, H2)
유일한 값을 순서대로 생성
사용하기 위해 시퀀스를 매핑해야 함
IDENTITY와 비슷하지만 식별자를 조회한 후에 엔티티에 할당한다.
그렇기 때문에 영속성 컨텍스트에 저장이 가능하다.
영속성 컨텍스트를 사용할 수 있기 때문에 쓰기 지연 기능 사용 가능
데이터베이스의 시퀀스를 조회하는 작업이 필요해서 통신 횟수가 2회다.
//SEQUENCE 전략 사용
@Entity
@SequenceGenerator ( //시퀀스 생성기 등록
name = "BOARD_SEQ_GENERATOR", // 시퀀스 생성기 이름
sequenceName = "BOARD_SEQ", // DB의 시퀀스 이름
initialValue = 1, //시작값
allocationSize = 1 //증가하는 범위, 기본값 50
//catalog //카탈로그명
//schema //스키마명
)
public class Board {
@Id
@GeneratedValue(startegy = GenerationType.SEQUENCE,
generator = "BOARD_SEQ_GENERATOR") //시퀀스 생성기 사용
private long Id;
}
TABLE : 키 생성 테이블을 사용
기본키의 이름과 값 컬럼을 가진 키 생성 전용 테이블을 생성하여 사용
테이블을 사용하여 모든 데이터베이스에서 사용할 수 있음
테이블 전략 조회와 값을 증가시키기 위한 작업 때문에 통신 횟수가 1회 더 많다.
sequence_name == pkColumnName
next_val == valueColumnName
BOARD_SEQ == pkColumnValue
2 == valueColumnValue
MEMBER_SEQ
10
PRODUCT_SEQ
50
//TABLE 전략 사용
@Entity
@SequenceGenerator ( //테이블 시퀀스 생성기 등록
name = "BOARD_SEQ_GENERATOR", //테이블 시퀀스 생성기 이름
sequenceName = "MY_SEQUENCE", //DB의 시퀀스 테이블 이름
pkColumnValue = "BOARD_SEQ", //키로 사용할 값 이름
allocationSize = 1 //증가하는 범위, 기본값 50
)
public class Board {
@Id
@GeneratedValue(startegy = GenerationType.TABLE,
generator = "BOARD_SEQ_GENERATOR") //테이블 시퀀스 생성기 사용
private long Id;
}
문자열의 길이에 제한이 없는 경우 사용하는 BLOB, CLOB 타입으로 매핑할 때 사용하는 어노테이션
속성
지정할 수 있는 속성은 없지만
매핑하는 필드 타입에 따라 문자면 CLOB으로 매핑되고
나머지는 BLOB으로 매핑한다.
@Transient
@Transient
private Integer temp;
특정 필드를 매핑하지 않고 싶은 경우에 사용하는 어노테이션
데이터베이스에 저장되지도 않고 조회되지도 않으므로
객체에 임시로 데이터를 보관하고 싶을 때 사용
@Access
@Entity
@Access(AccessType.FIELD)
public class Member {
@Id
private String id;
}
@Entity
@Access(AccessType.PROPERTY)
public class Member {
private String id;
@Id
public String getId() {
return id;
}
}
JPA가 엔티티에 접근하는 방식을 지정할 때 사용하는 어노테이션
속성
AccessType
FIELD : 필드에 직접 접근하는 방식으로 접근 권한이 private이여도 가능
PROPERTY : 접근자(Getter)를 사용하여 접근하는 방식
기본키의 위치에 따라서 AccessType 속성을 적용한 것과 같기 때문에 생략해도 상관없다.