ㅅㅇ
[JPA] JPA 구현 및 예제 본문
플레이데이터 빅데이터캠프 공부 내용
JPA 구현 및 예제
1. persistence.xml
1. 해당 entity class작성
- persistence.xml 파일 - 우클릭해서 아래와 같이 클릭하면, 파일에 아래 코드 자동 생성됨.
<class>model.domain.entity.Member</class>
@Entity 엑박 시, 거의 이 부분 추가 안해줘서 임.
2. create 생성 처리
<property name="hibernate.hbm2ddl.auto" value="create" />
= > create 생성 부터 시작. 만약 기존의 테이블이 있다면, 지웠다가 다시 생성
Hibernate:
drop table if exists Member
<property name="hibernate.hbm2ddl.auto" value="none" />
= > create 안함. 기존의 테이블에 데이터 insert
2. model.domain.entity
package model.domain.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.ToString;
@NoArgsConstructor
@AllArgsConstructor
@RequiredArgsConstructor
@Getter
@Setter
@ToString
@Entity
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@NonNull
@Column(length = 10)//, nullable = false)
private String name;
@NonNull
@Column(nullable = true)
private int age;
}
1. 생성자 어노테이션
어떤 데이터 처리를 할 지에 따라 적절한 파라미터를 보유한 생성자가 생성되어야 한다.
이를 고려하며, 사용할 생성자을 생각할 수 있어야 한다.
즉, 아래 세 가지 어노테이션 중에서 사용하던,
bulider 을 사용해 직접 원하는 생성자를 만들던,
일단 먼저, 어떠한 속성을 가진 생성자가 생성 되어야 할 지를 먼저 생각해야 한다.
그래서 entity class 를 작성할 때, 아웃라인 을 잘 체크해야 한다.
1) @NoArgsConstructor 어노테이션
: 파라미터가 없는 기본 생성자를 생성
- JPA에서 기본 생성자(No-args)가 필요한 이유
구체적인 클래스 타입을 알지 못해도,
그 클래스의 메소드, 타입 변수들에 접근할 수 있도록 해주는 API를 java Reflection 이라 하는데,
Java Reflection API를 사용하면 해당 클래스의 매서드, 맴버 변수, 변수 타입 등을 알 수 있다.
하지만 가져올 수 없는 정보 중 하나가 생성자의 인자 정보들이다.
따라서 기본 생성자가 없다면
java Reflection은 해당 객체를 생성 할 수 없기 때문에 JPA의 Entity에는 기본 생성자가 필요하다.
2) @AllArgsConstructor 어노테이션
: 모든 필드 값을 파라미터로 받는 생성자를 생성.
3) @RequiredArgsConstructor 어노테이션
: final이나 @NonNull인 필드 값만 파라미터로 받는 생성자를 생성.
아래의 코드와 같이 NotNull 이 아닌 필드 값이라면, @RequiredArgsConstructor 로 생성자를 만들 수 없다.
@NoArgsConstructor
@AllArgsConstructor
//@RequiredArgsConstructor
@Getter
@Setter
@ToString
@Entity
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@Column(length = 10, nullable = false)
private String name;
}
★ 세 개의 생성자 어노테이션 적용 비교
- @NoArgsConstructor 는 필수
- @AllArgsConstructor , @RequiredArgsConstructor 에서 둘 중 하나는 꼭 들어가야 하는데,
어떤 경우에 어떤 것을 써야 할 것인가?
- 일단, pk 를 제외한 모든 필드 값이 NonNull 의 경우
@RequiredArgsConstructor 는 꼭 추가해서 pk 를 제외한 파라미터로 이뤄진 생성자가 만들어져야 한다.
@AllArgsConstructor 있어도 상관없음.
- 필드값 중 NonNull 이 아닌 변수가 있을 경우, @RequiredArgsConstructor 을 꼭 빼줘야 한다.
해당 어노테이션은 NonNull 이 아닌 파라미터를 가진 생성자를 생성할 수 없기 때문이다.
파라미터가 있는 생성자는 꼭 필요하니
모든 파라미터로 이뤄진 생성자를 생성하는 @AllArgsConstructor 가 있어야 한다.
객체 생성, 멤버 변수 초기화에서
db 의 관점으로 생각했을 때 nonnull 설정, auto 설정 등등 을 위해 JPA 코드를 작성한다면,
당연히 객체 생성에 있어 자바에선 인식을 못하고 오류를 낼 것이다.
이를 잘 고려하기 위해서는 생성자가 중요하다.
원하는 JPA 처리를 위해서는 해당 상황에서 적절한 생성자를 쓸 줄 알아야 한다.
==> 이때, 객체 멤버 변수 선언 및 초기화 코드를 작성할 때,
outline 에서 생성된 생성자를 확인하고 내가 원하는 코드 작성할 수 있는 지 확인해보자.
2. 여러 경우에서 JPA 예제
1) pk 에 auto increment 를 설정하고, 모든 필드값을 NonNull 설정 시
@RequiredArgsConstructor 추가 해줘야 한다.
만약, 안 하면 객체 생성 시점에서 엑박 뜬다.
==> @RequiredArgsConstructor 유무에 따른 outline 차이
2) auto increment 설정
- 설정한 컬럼에 값을 대입하면, 오류
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
3) null 을 허용한 멤버 변수에 null 값을 초기화 했을 때,
- 객체에 다른 멤버 변수가 있을 때,
아래와 같이 바로 값을 초기화하면 에러. 당연히 자바 문법에서는 어떤 값에 null 을 넣었는 지 모르기 때문
== > 따로 초기화 해주기
@NoArgsConstructor
@AllArgsConstructor
//@RequiredArgsConstructor
@Getter
@Setter
@ToString
@Entity
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@Column(length = 10)//, nullable = false)
private String name;
@Column(nullable = true)
private int age;
}
public class RunningTest {
@Test
public void step01() {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("dbinfo");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
Member m1 = new Member();
Member m2 = new Member();
m1.setName(null);
m1.setAge(24);
em.persist(m1);
em.persist(m2);
tx.commit();
}
}
3) int 타입으로 정의된 변수에 @NonNull 을 달았을 때, 주의 가 뜨는 이유
int 타입와 같은 Primitive type 멤버 변수는 자바 문법에서 어차피 null 값을 가질 수 없기에,
NonNull, Nollable 할 필요가 없는 것.
- 그렇다면, JPA 에서 만약 int 타입으로 선언한 멤버 변수 로
생성된 컬럼 값에 null 을 입력하고 싶다면?
== > 객체 생성 후 초기화 시, 해당 컬럼에 아예 값을 넣지 않는다.
만약, 특정 컬럼에는 값을 넣고 싶다면, set 메소드로 따로 값 초기화 해주기.
@Test
public void step01() {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("dbinfo");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
Member m1 = new Member(); // 값 초기화 안 함.
Member m2 = new Member("유모모", 24);
em.persist(m1);
em.persist(m2);
tx.commit();
}
- auto increment를 설정한 pk (null 금지) 이기 때문에, 문법 에러는 뜨지 않았고
나머지 값들은 int 형 age 는 0, String 형 name 은 null 값이 들어간다.
=> 이때, 값을 넣지 않았음에도 0 값이 들어가는데?!?! - - 더 찾아보기.
5) null 을 허용하지 않은 멤버 변수 에 값을 초기화하지 않았을 때,
*** 위 설명과 같이 NonNull 필드값이 아닌 변수가 있으므로 RequiredArgsConstructor 는 사용할 수 없다.
Hibernate:
create table Member (
id integer not null auto_increment,
age integer,
name varchar(10) not null,
primary key (id)
) engine=InnoDB
- 현재, Member 의 멤버 변수의 id 는 pk 로 null 이 들어가선 안된다.
그러나, auto increment 설정으로, 객체 생성 시 값을 넣지 않아도 알아서 들어간다.
name 의 경우 nullable = false 설정으로 null 이 불가능 하다.
age 의 경우는 null 이 가능한 변수이다.
이때, 위와 같이 값을 초기화하지 않은 객체를 persist 한 경우, 어떻게 될 것인가?
- 콘솔창을 보면, 위와 같이 create 까지 되는데, insert 에서 에러가 발생한다.
==> 에러 발생 : null 을 허용하지 않은 name 컬럼에 값이 들어가지 않아서 발생한다.
javax.persistence.PersistenceException: org.hibernate.PropertyValueException: not-null property references a null or transient value : model.domain.entity.Member.name
'SW_STUDY > JDBC&JPA' 카테고리의 다른 글
[JDBC] 개요 & Java - mysql 연동 절차 및 문법 (0) | 2022.08.10 |
---|