트랜잭션을 지원하는 쓰기 지연"은 데이터베이스 엔티티를 생성, 수정 또는 삭제할 때, 이러한 변경 내용을 데이터베이스에 즉시 반영하지 않고, 트랜잭션 내에서 변경 내용을 모아두었다가 트랜잭션이 커밋될 때 한 번에 데이터베이스에 적용하는 기술을 가리킨다.
Entitymanager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
ts.begin(); //트랜잭션 시작
em.persist(memberA);
em.persist(memberB);
//여기까지 InsertSQL을 데이터베이스에 보내지 않는다.
//커밋하는 순간 데이터베이스에 insert SQL을 보낸다.
ts.commit(); //트랜잭션 커밋(종료)
Entitymanager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
ts.begin(); //트랜잭션 시작
// 영속 엔티티 조회
Member memberA = em.find(Member.class, "memberA");
//엔티티 데이터 수정 - 변경감지(dirty checking)
memberA.setUsername("admin")
memberA.setAge(20);
//em.update(memberA); 이런 코드가 있어야하지 않을까?(아님)
ts.commit(); //트랜잭션 커밋(종료)
em.update(memberA); 이 코드가 필요하지 않은 이유는, JPA는 엔티티 객체의 상태를 관리하고, 변경을 감지하고, 트랜잭션 커밋 시에 변경 내용을 데이터베이스에 자동으로 반영해주기 때문에 굳이 쓸 필요가 없다.
그렇다면 옳은 코드는EntityManager em = emf.createEntityManager(); EntityTransaction transaction = em.getTransaction(); transaction.begin(); Member memberA = em.find(Member.class, "memberA"); memberA.setUsername("admin"); memberA.setAge(20); // 여기서 명시적인 업데이트 호출은 필요하지 않다. transaction.commit();
이런 코드이다. 즉 JPA가 변경 내용을 감지하고 자동으로 데이터베이스에 반영합니다. 명시적인 em.update(memberA); 호출이 필요하지 않으며, JPA가 관리하는 엔티티의 변경은 트랜잭션 커밋 시에 자동으로 처리된다.
-> flush()가 호출되는 시점에 Entitiy와 스냅샷을 전부 비교 후(최적화된 알고리즘으로 진행)변경이 된 것을 감시(Dirty Checking)한 후에 update쿼리를 작성 후,
update쿼리를 날린다.
//삭제 대상 엔티티 조회
Member memberA = em.find(Member.class,"memberA");
em.remove(memberA);
✍️flush가 무엇인가?
JPA(Java Persistence API)에서 사용되는 메서드로, 영속성 컨텍스트(Persistence Context)에 있는 변경 내용을 데이터베이스에 동기화하는 역할을 합니다. 즉, flush를 호출하면 영속성 컨텍스트에 저장된 엔티티의 변경 내용이 데이터베이스에 반영된다.
트랜잭션 커밋 - 플러시 자동 호출
em.flush() - 직접 호출
jpql 쿼리 실행 - 플러시 자동 호출
영속성 컨텍스트를 비우지 않음
영속성 컨텍스트의 변경 내용을 데이터베이스에 동기화
트랜잭션이라는 작업 단위가 중요 -> 커밋 직전에만 동기화 하면 됨
JPA는 동시성, 데이터를 맞추거나 모두 트랜잭션에 위임한다.
hibernate.hbm2ddl.auto
create : 기존 테이블 삭제 후 다시생성(Drop + Create)
create-drop : create와 같으나 종료시점에 drop
update : 변경문만 반영(운영 DB에는 사용하면 안됨)
validate : 엔티티와 테이블이 정상 매핑 되었는지만 확인
none : 사용하지 않음
=> 데이터베이스 방언별로 달라진다.
운영장비에는 절대 create, create-drop,update사용하면 안됨
개발 초기 단계는 create 또는 update
테스트 서버는 update 또는 validate
스테이징과 운영서버는 validate 또는 none
create, update등을 함부로 사용했다가는 실제 개발과정에서 큰 문제가 생길 수 있다. 자동생성을 이용하자.
제약조건 추가: 회원이름은 필수, 10자 초과X
-> @Column(nullable = false, length=10)
유니크 제약조건 추가
-> @Table(uniqueConstraints={
@UniqueConstraint(name="NAME_AGE_UNIQUE",
columnNames={"NAME","AGE"}
)
})
=> DDL 생성 기능은 DDL을 자동 생성할 때만 사용되고 JPA의 실행 로직에는 영향을 주지 않는다.
-@Column : 컬럼 매핑
-@Temporal : 날짜 타입 매핑
-@Enumerated : enum타입 매핑
-@Lob :BLOB,CLOB매핑
-@Transient :특정 필드를 컬럼에 매핑하지 않음(매핑 무시)
-name:필드와 매핑할 테이블의 컬럼 이름
-nullable : null값의 허용 여부를 설정한다. false로 설정하면 DDL 생성시에 not null 제약조건이 붙는다.
-unique : uniqueConstraints와 같지만 한 컬럼에 간단히 유니크 제약조건을 걸 때 사용한다.
-length : 문자길이 제약조건, String 타입에만 사용
직접 할당 : @Id만 사용
자동 생성 : @GeneratedValue -> 전략
-> IDENTITY
: 데이터베이스에 위임, MYSQL,SQL Server, DB2
->SEQUENCE
: 데이터베이스 시퀀스 오브젝트 사용, ORACLE, PostgreSQL, DB2, H2
@SequenceGenerator 필요
->TABLE
: 키 생성용 테이블 사용, 모든 DB에서 사용
@TableGenerator필요
->AUTO
:방언에 따라 자동 지정, 기본값
-> auto는 DB방언에 맞춰서 IDENTITY,SEQUENCE,TABLE 3개의 방식중 하나가 선택이 된다.