2일차
persist()
메서드를 호출하게 되면 영속화 선언이 됨.persist()
: 비영속 상태의 엔티티를 영속 상태로 전환.flush()
: DB에 연산을 실행.detach()
: 영속 상태의 엔티티를 준영속 상태로 전환.clear()
: 영속 상태의 모든 엔티티를 준영속 상태로 전환.close()
: 영속성 컨텍스트를 종료시킴. 영속 상태의 모든 엔티티를 준영속 상태로 만들고 영속성 컨텍스트를 종료시킴.merge()
: 준영속 상태의 엔티티를 다시 영속 상태로 만듦.remove()
: 영속화된 엔티티를 삭제.// 객체가 영속성컨텍스트, 데이트베이스와 무관한 상태이다.
Customer customer = new Customer();
customer.setId(1L);
customer.setFirstName("honggu");
customer.setLastName("kang");
Customer customer = new Customer();
customer.setId(1L);
customer.setFirstName("honggu");
customer.setLastName("kang");
// customer객체가 영속성 컨텍스트에서 관리된다.
em.persist(customer);
// 영속상태의 customer객체(엔티티)를 영속성컨텍스트에서 분리한다.
em.detach(customer);
// 영속상태의 모든 객체를 영속성컨텍스트에서 분리한다.
em.clear()
// 영속성컨텍스트를 종료한다.
em.close()
// customer 엔티티를 영속성컨텍스트에서 분리하고, DB에서도 삭제한다.
em.remove(customer)
EntityManager em = emf.createEntityManager(); // 1)엔티티 매니저 생성
EntityTransaction transaction = em.getTransaction(); // 2)트랜잭션 획득
transaction.begin(); // 3)트랙잰셕 begin
Customer customer = new Customer(); // 4-1)비영속
customer.setId(1L);
customer.setFirstName("honggu");
customer.setLastName("kang");
em.persist(customer); // 4-2)영속화
transaction.commit(); // 5)트랜잭션 commit
// 트랜잭션이 커밋이 되는 순간 쿼리가 수행된다. flush DB와 동기화가 된다.
@Test
void 조회_1차캐시_이용() {
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin();
Customer customer = new Customer();
customer.setId(1L);
customer.setFirstName("honggu");
customer.setLastName("kang");
em.persist(customer);
transaction.commit();
Customer entity = em.find(Customer.class, 1L); // 1차 캐시에서 조회한다.
log.info("{} {}", entity.getFirstName(), entity.getLastName());
}
clear()
를 했기 때문에 1차 캐시에 고객정보가 없다. 따라서 DB에서 정보를 조회하고, 정보를 캐시에 저장한 후 반환한다.@Test
void 조회() {
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin();
Customer customer = new Customer();
customer.setId(2L);
customer.setFirstName("guppy");
customer.setLastName("hong");
em.persist(customer);
transaction.commit();
em.clear(); //영속성 컨텍스트를 초기화 한다.
Customer entity = em.find(Customer.class, 2L); // DB 에서 조회한다. SELECT ...
log.info("{} {}", entity.getFirstName(), entity.getLastName());
em.find(Customer.class, 2L); // SELECT Query 수행되지 않는다. 1차캐시 사용
}
@Test
void 수정() {
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin();
Customer customer = new Customer();
customer.setId(1L);
customer.setFirstName("honggu");
customer.setLastName("kang");
em.persist(customer);
transaction.commit();
// 엔티티를 영속화한후, 커밋을해서 flush()를 통해 DB에 저장.
transaction.begin();
Customer entity = em.find(Customer.class, 1L);
entity.setFirstName("guppy");
entity.setLastName("hong");
// em.update(entity) ??!!
transaction.commit(); // flush -> UPDATE ...
}
@Test
void 삭제() {
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin();
Customer customer = new Customer();
customer.setId(1L);
customer.setFirstName("honggu");
customer.setLastName("kang");
em.persist(customer);
transaction.commit();
transaction.begin();
Customer entity = em.find(Customer.class, 1L);
em.remove(entity);
transaction.commit(); // flush -> DELETE ..
}
@Entity
를 사용해서 영속성 컨텍스트에서 관리할 수 있는 객체라는 것을 선언한다.@Table
엔티티 객체를 어떤 RDB 테이블과 맵핑시킬지 테이블 이름을 명시해준다.@Entity // Entity 선언
@Table(name = "member") // Table 선언으로 맵핑할 테이블 명시.
public class Member {
@Id
private Long id;
private String name;
private String nickName;
private int age;
private String address;
private String description;
// getter, setter
}
Auto-generate-ddl
으로 테이블 자동으로 생성.spring:
h2:
console:
enabled: true
jpa:
generate-ddl: true
database: H2
show-sql: true
open-in-view: false
properties:
hibernate:
dialect: org.hibernate.dialect.H2Dialect
query.in_clause_parameter_padding: true
hbm2ddl:
auto: create-drop
create, create-drop, update
는 개발, 혹은 테스트 환경에서 많이 사용한다.
DDL 옵션
@Entity
@Table(name = "member")
@Getter
@Setter
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;
@Column(name = "name", nullable = false, length = 30)
private String name;
@Column(nullable = false, length = 30, unique = true)
private String nickName; // nick_name
private int age; // age
@Column(name = "addres", nullable = false)
private String address;
@Column(name = "description", nullable = true)
private String description;
}
@GenerateValue
: PK의 생성전략.@Column(name = "")
: RDB "name"에 명시한 속성의 컬럼과 맵핑을 시키겠다는 의미로, 위의 경우 name이라는 컬럼을 만들겠다는 의미.nullable
: 테이블에서 not null 제약조건이 추가된다.length
는 String타입에서 사용.unique
는 RDB의 제약조건, unique값 옵션을 추가해줌.drop table if exists member CASCADE
drop sequence if exists hibernate_sequence
create sequence hibernate_sequence start with 1 increment by 1
create table member (id bigint not null, address varchar(255) not null, age integer not null, description varchar(255), name varchar(30) not null, nickName varchar(30) not null, primary key (id))
alter table member add constraint UK_1m3ighjll05v7njjxeopp823j unique (nickName)
@Id
: JPA에서 사용할 Entity이름을 지정.@Id
@Column(name = "id")
private Long id;
@GeneratedValue
의 strategy 전략에 4가지가 있다.@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Id
@GeneratedValue
private Long id;
@Entity
@Table(name = "orders")
public class Order {
@Id
@Column(name = "id")
private String uuid;
@Column(name = "order_datetime", columnDefinition = "TIMESTAMP")
private LocalDateTime orderDatetime;
@Enumerated(EnumType.STRING)
private OrderStatus orderStatus;
@Lob
private String memo;
}
@Enumerated
, @Lob