환경설정 & 기본 코드
|
| apllication.xml |
전용속성 hibernate.show_sql :SQL 출력 hibernate.format_sql: 자동정렬 출력 hibernate.use_sql_commentss: 주석도 같이 출력 hibernate.id.new_generator_mapping: false(default) : jpa 표준에 맞춘 새로운 키 생성 전략을 사용. allocationSize 속성사용바뀜 hibernate.hbm2ddl.auto : - create(스키마 자동생성) - create-drop(create속성 + 종료후 생성한 DDL 제거 : drop +create+drop) - update(변경사항만 수정) - validate(변경사항 있으면 경고를 남기고 어플리케이션 실행안함) - none(자동 생성기능을 사용하지 않음, 속성자체를 삭제 or 유효하지 않은 값 입력.) jpa.hibernate.naming.physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl : 카멜 -> 스네이크 spring.jpa.hibernate.use-new-id-generator-mappings =true : 키 생성 전략시, false 일 겨우 기존 하비어네이트 시스템 유지보수. true 설정시 allocatonSize 속성 사용방식 달라짐. ** 운영주의 사항 : create, create-drop, update 옵션 사용 불가 개발단계에서만 *개발시 초기 create, update, 자동화테스트 ci서버 create or create-drop, 테스트 서버 update or validate, 스테이징, 운영은 validate or none JPA2.1부터 스키마 자동생성기능 표준으로 지원. 하지만 update, validate 옵션은 지원하지 않음. ????
JPA 어노테이션 패키지 위치 import javax.persistence.*;
JPA 실행 위한 기본 설정파일 persistence.xml - 구현체들이 자동으로 엔티티 인식못할때 설정가능, JPA 표준속성, 하이버네이트 속성 외 - persistence-unit : DB 이름 그와 관련 DB 설정 |
| 커넥션 풀 설정 |
spring.datasource.hikari.connection-timeout = 20000 : 최대 커넥션 수n spring.datasource.hikari.minimum-idle= 10 : #HikariCP 사용 유지 최소 커넥션 수 spring.datasource.hikari.maximum-pool-size= 10 : 최대 풀 사이즈 spring.datasource.hikari.idle-timeout=10000 : 최대 유휴(대기)시간 spring.datasource.hikari.max-lifetime= 1000 : 종료 후 최대 연결 시간 spring.datasource.hikari.auto-commit =true : 자동 커밋 기본설정
https://www.javadevjournal.com/spring-boot/spring-boot-hikari/#:~:text=a%20connection%20spring.-,datasource.,in%20a%20connection%20pool%20spring. |
| 방언 dialect 방언 |
표준 아닐때 사용 spring.jooq.sql-dialect https://wannaqueen.gitbook.io/spring5/spring-boot/undefined-1/31.-sql-by-ys/31.6-jooq
데이터 타입 - 가변문자 타입 MySQL(VARCHAR), 오라클(VARCHAR2) - 숫자 타입 MySQL(integer), 오라클(Number) 다른 함수명 - SQL표준(SUBSTRING()), 오라클(SUBSTR()) 페이징 처리 - MySQL(LIMIT), 오라클(ROWNUM
Hibernate- 현재 45개 데이터베이스 방언 지원. )
|
| 엔티티 |
엔티티 (사전) 독립체, 인간이 생각하는 개념 또는 정보의 세계에서는 의미있는 정보의 단위
엔티티 매니저 팩토리 - DB 갯수만큼 - 엔티티 매니저 팩토리는 스레드 세이프, 엔티티 매니저는 동시성 문제, 스레드간 공유 안됨. - 하는일 1. 에플리케이션에서 관리- 직접 생성, 종료 2. 컨테이너에서 관리 - JBoss EAP, 웹로직, TomEE와 같은 JEE 컨테이너
영속성 컨텍스트 - 엔티티를 영구 저장하는 환경. - 개념적, 엔티티 매니저 생성할 때 하나 만들어짐, 엔티티 매니저를 통해서 영속성 컨텍스트에 접근가능, 관리 - 기본적으로 하나의 엔티티 매니저에 하나의 영속성 컨텍스트 만듬.
* 엔티티매니저 팩토리 코드 public T find(Class entityClass, Object primaryKey); 먼저 1차 캐시에서 엔티티를 찾고 만약 찾는 엔티티가 1차 캐시에 없으면 데이터베이스에서 조회 한다. 존재하지 않으면 null 1차캐시 - 어플리케이션 수준의 캐시. 조회 -> 1차캐시없으면 데이터베이스 조회->조회 데이터로 엔티티 생성, 1차 캐시 저장-> 조회한 엔티티 반환 ==>동일성, 동등성 모두 같은이유 , Repeatable read 등급 트랜잭션 격리 수준을 제공
public T getReference(Class entityClass, Object primaryKey); 존재하지 않으면 EntityNotFoundException 쿼리를 바로 실행하지 않고 프록시 객체를 리턴, 프록시 객체는 최초 데이터가 필요한 시점에 select 쿼리를 실행. 세션 범위 밖에서 첫 실행시 ({}) getFiled 실행시 LazyInitializationException -no Session 발생
public void persist(Object entity); 쓰기지연(transactional write-behind) : 트랜젝션 커밋 직전까지 데이터베이스에 엔티티를 저장하지 않고 내부 쿼리 저장소에 insert 쿼리를 모아둠.
@PersistenceContext EntityManager em; --JEE 관리하는 트랜젝션 참여. |
| 엔티티 생명주기 |
엔티티 생명주기 비영속 new/transient : 영속성 컨텍스트와 전혀 관계가 없는 상태 , 객체만 생성했고 아직 저장안함. - Member member = new Member(); 영속 managed: 영속성 컨텍스트에 저장된 상태 - em.persist(member); - em.find() - jpql 사용 상태 준영속 detached : 영속성 컨텍스트에 저장되었다가 분리된 상태 - em.detach() - em.close(); - em.clear() ; 영속성 초기화 삭제 removed : 삭제된 상태 - em.remove(member);
영속성 컨텍스트 특징 1. 식별자 존재 2. 보통은 트랜젝션 커밋할때 데이터베이스 반영(flush) 3. 장점: 1차 캐시, 동일성 보장, 트랜잭션을 지원하는 쓰기 지연, 변경감지(update시 dirty checking), 지연로딩
동적 update, insert @org.hibernate.annotations.DynamicUpdate @Dynamic Insert 컬럼이 30개 이상될때 정적수정쿼리보다 빠름. 컬럼 많을때 고려.
플러시 영속성 컨텍스트의 변경 내용을 데이터베이스에 "동기화" 하는 작업. 변경감지동작, 영속성 컨텍스트에 있는 모든 엔티티 스냅샷과 비교, 수정된 엔티티를 찾는다. 수정쿼리 SQL 젖아소, 후에 데이터베이스 전송 호출 방법: 직접호출(em.flush()), 트랜잭션 커밋 시 플러시 자동호출, JPQL & Criteria 객체지향 쿼리 실행시 플러시 자동 호출 e.setFlushMode(FlushModeType.AUTO); FlushModeType.AUTO : 커밋이나 쿼리를 실행할 때 플러시(기본값) FlushModeType.COMMIT: 커밋할때만 플러시
준영속 영속->준영속 1차 캐시, 지연 SQL 저장소, 변경감지, 지연로딩, 해당 엔티티를 관리하기 위한 모든정보 제거. 식별값 가짐 em.detach() : 특정 한 엔티티 영속성 컨텍스트 관리하지마! em.clear(); : 해당 엔티티 영속성 컨텍스트 관리하지마! , 수정해도 DB 영향 없음 em.close() :개발자가 실제 사용하는경우 드뭄
병합 준영속-> 영속 em.merge(member); 새로운 영속 상태의 엔티티를 반환. cf) 영속성여부(엔티티관리여부) : em.contains(member)
비영속 병합 해당 엔티티가 없으면 생성해서 병합. 있으면 업데이트.
*context : 맥락, 문맥 |
| 엔티티 맵핑 |
@Entity 테이블과 매핑되는 기본 단위. - name : jpa에서 사용할 엔티티 이름. - 기본생성자 필수(public or protected) - final 클래스, enum, interface, inner 클래스에서 사용불가. - 저장할 필드에 final 사용하면안된다.
@Table 클래스가 어떤 테이블과 매핑되는지 설정 - name :매핑할 테이블이름 - catalog : catalog 기능있는 데이터베이스에서 매핑 - schema - uniqueConstraints : DDL 생성시 유니크 제약조건. uniqueConstraints={@UniqueConstraint(name="NAME_AGE_UNIQUE", columnNames={"NAME", "AGE"})}
@Id 엔티티 식별자 - 직접할당 자바 기본형, 자바 래퍼형, String, java.util.Date, java.sql.Date, java.math.BigDecimal, java.math.BigInteger - IDENTITY 전략:자동 키생성 : 주로 MySQL,, PostgreSQL, SQL Server, DB2에서 사용. @GeneratedValue(strategy=GenerationType.IDENTITY) DB 식별 컬럼 사용해서 식별자 생성:persist() 저장 시점 insert 쿼리 실행, 쓰기지연 동작안함. spring.jpa.hibernate.use-new-id-generator-mappings =true - SEQUENCE 전략 : 데이터베이스 시퀀스 사용 : 오라클, PostgreSQL, DB2, H2 @SequenceGenerato(name="review_seq_gen", sequenceName="hotel_review_seq", allocationSize=1) @GeneratedValue(generator="review_seq_gen") persist() 저장 시점 시퀀스 추가 쿼리 실행-> 트랜젝션 commit 시 insert allocationSize 기본값 50 : 시퀀스 전략. 50개를 메모리에 미리 할당받아 호출수를 줄임. 단 두개 이상 jvm 을 사용하면 충돌 우려 allocationSize =1 사용하여 해결. - TABLE 키생성 테이블 사용 : @TableGenerator(name="idgen", table="id_gen", pkColumnName="entity", pkColumnValue="city", valueColumnName="nextid", initialValue=0, allocationSize=1) GenerateValue(generator="idgen") 1. id_gen테이블에서 식별자 구함. 레코드 존재 않을 때 insert 실행, 다음식별자 id_gen 반영 -AUTO전략 @GeneratedValue(strategy=GenerationType.AUTO) 오라클 sequence, mysql identity를 사용 * 자연키 : natural key, : 비즈니스에 의미가 있는 키 ex) 주민번호, 이메일, 전화번호 * 대리키 : surrogate key : 비즈니스와 관련없는 임의로 만들어진 키, 대체키,ex) 오라클 시퀀스, auto_increment, 키생성 테이블 사용. 대리키 권장
@Basic 보통 생략되어 사용, int, long, String과 같은 기본타입, 래퍼타입, BigInteger, BigDecimal, Calendar, Time, Timestamp, enum, 상기의 배열
@Timestamp java.util.Date 사용시 @Temporal(TemporalType.TIMESTAMP) java.sql.Timestamp , java.util.Date로 변환 DATE : java.sql.Date TIME : java.sql.Time TIMESTAMP : java.sql.Timestamp : Mysql : datetime, H2,오라클, postgreSQL : timestamp 하이버 네이트 5.2 LocalDateTime 사용
@Column 없으면 타입명과 컬럼값 같음 - name - nullable=false - length=10 - insertable=false :면 id값 빼고 insert - updatable=false : 면 update 대상 제외 -table 하나의 엔티티 두개이상 테이블 매핑. - unique -columnDefinition - precision, scale : BigDeciaml 타입에서 사용한다. BingInteger도 사용가능, precision 소숫점포함 전체 자릿수, scale 소수의 자릿수 아주 큰숫자, 정밀 한소수 다루어야 할때 사용.
@Enumerated(EnumType.STRING) STRING 설정안하면 기본타입으로 저장. @Lob 필드길이 제한 없음, CLOB: 필드 타입 문자 BLOB : 나머지
@Access(AccessType.PROPERTY) 필드 상단 프로퍼티 접근방식, get, set 메서드 통해서 접근 == @id 를 get 메소드 선언 과 같음 @Access(AccessType.FIELD) get 메서드 상단 필드 접근방식 set 메서드를 사용하지 않음. == @id 를 필드에 선언 과 같음 * 필드에 id 를 선언하고 메서드에 @Access 프로퍼티 선언 하면 동시사용 가능.
@transient transient private long timestamp = System.currentTimeMillis(); 사전 일시적인, 트랜션트 영속대상 제외
기본생성자 필수, public or protected
final class 불가. 프록시 객체를 생성 부락.
Serializable 인터페이스 캐시 구현기술 사용시. 필요
exclude-unlisted-classes true 시 자동추가 비활성화
cf) 필드에서만 쓸수있는게 아니라 get 메소드에 선언가능 |
| 트랜젝션 |
ACID : Atomic 원자성, Consistency 일관성, Isolation 격리성, Durability 지속성 Read Uncommited 커밋되지 않는 읽기 : 커밋안된 데이터 다른트렌젝션 update, insert, delete 읽기 Dirty reads : Rollback 시 정합성 깨짐 Read Commited 커밋된 읽기 : 다른 트랜젝션 update insert delete 읽기 Non-Repeatable read : 업데이트 영향으로 첫번째 조회 값과 두번째 조회값 다름 Repeatable Read 반복 읽기 : 다른 트랜젝션 insert, delete 읽기 Phantom read : insert, delete 영향으로 첫번째 조회 값과 두번째 조회가 있다없음 Serilization 직렬화 : 락을 걸어 트랜잭션 이용하는 부분 사용 못함. 병렬성 저하.
JPA 낙관적 락 : 트랜잭션 충돌이 거의 발생하지 않는다. 커밋 되는 시점에 충돌여부 알수있다. LockModeType.NONE : 커밋시 version정보 update 쿼리로 : 두번의 갱신문제 해결 > 조회 ~ 수정 트랜잭션 격리 LockModeType.Optimistic: 커밋시 version 정보를 select 쿼리로 보냄: dirty read, Non-Repeatable Read 해결 +스칼라 타입 으로 조회 시 소프트락 적용안됨 ?? 스칼라타입: 단하나, <->컴포지트 Optimistic.Force_increment : 커밋시 version 정보를 update 쿼리로 : 연관관계 엔티티 함께 버전 관리
JPA 비관적 락 : 타임아웃. PESSIMISTIC_WRITE PESSIMISTIC_FORCE_INCREMENT
출처 : https://ojt90902.tistory.com/723
RESOURCE_LOCAL : 변경내용 영속 컨텍스트에 보관, 트랜잭션을 커밋하는 시점에서 영속 컨텍스트로 추적한 변경을 DB에 반영.
JTA 트랜잭션 타입. Java Transzction API UserTransaction utx = (UserTransaction)new InitaialContext().lookup("java:comp/UserTransaction"); utx.begin(); EntityManager em = emf.createEntityManager(); em.joinTransaction; (이부분은 필히 작성안해도됨. )
utx.commit() utx.rollback() |
| @JoinTable |
조인테이블 = 연결 테이블 = 링크 테이블 다대다 관계 설정. cf) 연관관계 설정 - @JoinColumn or JoinTable
일대일, 일대다, 다대일, 다대다
|
| 벨류 객체 |
한개의 값, 다른 벨류 객체와 구분하기 위한 식별자를 갖지 않는다. 자신만의 라이프 사이클을 갖지 않는다. 자신이 속한 객체가 생성될 때 함께 생성/삭제시 삭제
생성시 모든 프로퍼티를 파라미터로 전달받는다. 읽기전용 프로퍼티만 제공한다. equals() 메서드를 재정의 한다. 각 프로퍼티의 값을 이용, 해시코드를 생성하도록 hashCode()메서드를 재정의 한다.
public class ValueObject{ private String a; private String b; private String c;
public ValueObject(String a, String b, String c){ this.a = a; this.b = b; this.c = c; }
public String getA(){return a;} public String getB(){return b;} public String getC(){return c;}
@Override public boolean equals(Object o){ if(this==o) return true; if(o==null || getClass() !=o.getClass()) return false; ValueObject vo = (ValueObject)o; return Objects.equals(a, vo.a) && Objects.equals(b, vo.b) & Objects.equals(c, vo.c); }
@Override public int hashCode(){ return Objects.hash(a,b,c); } } |
@Embeddable @Embedded @AttributeOverrides @secondaryTable |
@Embeddable public class ValueObject{ }
@Entity public class UsingObject{
@Id private String id;
@Embedded privae valueObject; }
매핑 대상이 되도록 설정. update 시 트랜젝션 내에서 변경되면 변경내역 DB 반영
@Embedded @AttributeOverrides({ @AttributeOverride(name..., column=@Column(name="valueObject")), @AttributeOverride ...}) private Address valueObject2;
동일 테이블 사용하는 밸류클래스 이름 재정의 사용
@Entity @SecondaryTable( name="sight_detail", pkJoinColumns=@PrimaryKeyJoinColumn(name="sight_id",refferencedColumnName="id" ) ) public class Sight{
@Embeded @AttributeOverrides({ @AttributeOverride }) private SightDetail detail; }
복합키 사용 벨류테이블 1. equals()메서드, hashCode() 메서드 재정의 2. Serializable 인터페이스 상속. (3. 생성자. null 이면 IllegalArgumentException. ) @Entity @public class MonthChage{ @Id privateMonChageId id; } @Embeddable public classMonChagedId implements Serializable{ @Column
} |