SPRING

Spring Framework는 자바 플랫폼을 위한 오픈 소스 프레임워크로, 복잡한 애플리케이션 개발을 간편하고 생산성을 높이는 데 중점을 둔다. 2003년에 처음 출시된 이후, Spring은 자바 개발 커뮤니티에서 널리 사용되며, 기업 애플리케이션 개발의 표준으로 자리잡았다.

 

 

스프링은 무료로 사용이 가능하며, 소스 코드가 공개되어 있어 누구나 수정하거나 개선할 수 있다. 하지만, 스프링의 발전과 유지보수는 스프링소스(SpringSource)라는 IT 기업이 담당하고 있어 안정성이 보장된다. 스프링은 많은 기능을 제공하면서도 상대적으로 적은 코드로 복잡한 문제를 해결할 수 있게 해준다. 기존의 EJB 같은 기술들보다 단순하고 유연하다. 애플리케이션 개발에 필요한 다양한 기능들을 미리 준비된 코드 형태로 제공하여 개발자들이 빠르게 애플리케이션을 구축할 수 있도록 도와준다.

 

POJO 프로그래밍 지향

 

POJO(Plain Old Java Object)

순수 Java 객체를 사용하여 비즈니스 로직을 구현하도록 권장한다.

외부 라이브러리나 모듈에 의존하지 않아 코드가 간결하다.

 

IoC (Inversion of Control) / DI (Dependency Injection)

 

  • IoC (제어의 역전): 객체 생성과 의존 관계를 스프링 컨테이너가 관리하여 개발자가 직접 객체를 생성하고 관리하지 않아도 된다.
  • DI (의존성 주입): 객체의 의존성을 외부에서 주입받아, 코드의 결합도를 낮춘다.

AOP (Aspect Oriented Programming)

공통 관심 사항(로깅, 보안 등)을 핵심 비즈니스 로직과 분리하여 코드 중복을 방지하고, 유지보수를 쉽게 한다.

관심사의 분리로 공통 기능을 모듈화하고 재사용성을 높였다.

 

PSA (Portable Service Abstraction)

다양한 데이터베이스와 외부 시스템에 대한 일관된 접근 방법을 제공하여, 기술적인 종속성을 줄였다. 데이터베이스나 외부 서비스의 변경에 간편하게 대응할 수 있다.

 

SPRING BOOT

스프링 부트는 스프링 프레임워크를 기반으로 하여 애플리케이션 개발을 더욱 간편하게 해주는 프레임워크이다.

 

스프링 부트는 스프링 애플리케이션의 초기 설정을 자동화하고, 복잡한 XML 설정이나 코드 구성을 최소화했다.

Spring Initializr을 사용해 기본적인 프로젝트 구조와 필요한 라이브러리를 쉽게 설정할 수 있으며, 독립 실행이 가능한 Jar 파일로 빌드하여 Tomcat 같은 웹 서버를 내장하고 있어 외부 웹 서버를 설치할 필요가 없다 (War 형식의 외장 톰캣도 지원하긴 한다)

 

 

 

 

'CS > SPRING' 카테고리의 다른 글

JPA 기본키 매핑  (0) 2024.08.12
데이터베이스 스키마 자동 생성  (0) 2024.08.12
JPA 필드와 컬럼 매핑  (0) 2024.08.12
JPQL과 SQL의 차이점  (0) 2024.08.12
JPA의 영속성 컨텍스트  (0) 2024.08.12

기본키 매핑

  • @Id 어노테이션은 꼭 필요하다.
  • 자동 생성을 위한 @grneratedValue 어노테이션을 붙일 수 있다.

KEY 자동 할당

  • key를 자동 할당하는 방법에는 IDENTITY, SEQUENCE, TABLE, AUTO 가 있다.
  • Key 자동 생성 시에는 해당 Entity의 PK로 설정한 필드에 아무 값도 설정하지 않고 DB에 저장해야 한다.

IDENTITY

  • 기본키 생성을 데이터베이스에 위임한다.
  • 원래는 em.persist()를 해도 쿼리가 바로 DB에 적용되지 않는 쓰기 지연이 JPA의 특징이지만,
  • IDENTITY 전략 사용시에는 즉시 insert 쿼리가 DB에 적용된다.
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
Member member = new Member();
member.setName("hello");

em.persist(); //insert 쿼리 -> member에 id 값 세팅

Long id = member.getId(); //id값을 알 수 있다.

SEQUENCE

  • 시퀀스는 순서를 뜻하는 것으로 유일한 값을 순서대로 생성하는 것이다.
  • 특정 데이터베이스에는 유일한 값을 생성해 주는 시퀀스라는 오브젝트가 존재한다.
  • 해당 오브젝트로부터 PK로 사용할 유일한 값을 받아서 사용하는 것이다.
@SequenceGenerator(
    name = "member_seq_generator", 
    sequenceName = "member_seq",
    initialValue = 1,
    allocationSize = 50)
@Entity
public class Member {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "member_seq_generator")
    private Long id;
}
Member member = new Member();
member.setName("hello");

em.persist(); //sequence 테이블에서 다음 id 값 불러와서 member 객체에 id 세팅
// insert 쿼리는 나가지 않음.

Long id = member.getId(); //id값을 알 수 있다.
  • IDENTITY 전략과 유사하지만,
  • SEQUENCE 전략일때는 DB의 시퀀스 테이블에서 값을 저장하지만 insert 쿼리는 나가지 않는다.

@SequeceGenerator의 속성

  • name : id 필드에 붙은 @GenerateValue의 generator 이름과 매칭된다.
  • sequenceName : DB에 생성될 시퀀스 테이블의 이름이다.
  • initialValue : 시퀀스 시작 값
  • allocationSize : 시퀀스 테이블에서 한 번에 받아올 시퀀스 사이즈 (아래에서 자세히 다룬다.)

TABLE

@TableGenerator(name = "member_seq_generator", 
        table = "MY_SEQUENCES", 
        pkColumnValue = "MEMBER_SEQ", 
        allocationSize = 1)
@Entity
public class Member {
    @Id
    @GeneratedValue(strategy = GenerationType.TABLE, generator = "member_seq_generator")
    private Long id;
}
  • 키 전용 테이블 하나 만들어 데이터베이스 시퀀스를 흉내내는 전략

  • 장점 : 모든 데이터베이스에 적용 가능

  • 단점 : 성능이 DB 자동 생성에 비해 안 좋다.

AUTO

IDENTITY 전략과 유사하지만, 각 데이터베이스 방언에 따라 해당 데이터베이스의 기본 PK 생성 전략을 따른다.

  • ex) sequence : oracle, PostgreSQL, H2 등

SEQUENCE와 TABLE 전략의 성능 개선 방법

위의 예제에서 SEQUENCE 전략일 때는 DB의 시퀀스 테이블에서 다음 값을 불러와서 사용한다고 했다.

이렇게 하면 객체를 한번 저장할 때 마다 DB에 접근해야 하는 문제가 있다.
이 문제를 해결하기위해 allocationSize라는 개념을 도입해서 DB 접근 횟수를 줄인다.

allocationSize 속성

allocationSize = {size}를 설정하면 DB의 시퀀스 테이블의 값을 {size}만큼 증가시키고 
해당 {size}만큼의 시퀀스가 증가되는 동안은 메모리 환경에서 해당 값을 관리한다.

(ex)
initialValue = 1, allocationSize = 50일 경우

맨 처음 엔티티를 추가할 때, id =1로 설정하고 DB의 시퀀스 테이블의 다음 값은 51로 변경된다.

이후 다음 49번 동안은 엔티티를 추가할 때 
DB의 시퀀스 테이블에 접근하지 않고 메모리에서 값을 증가시켜서 사용한다

'CS > SPRING' 카테고리의 다른 글

SPRING FRAMEWORK + SPRING BOOT  (0) 2024.08.15
데이터베이스 스키마 자동 생성  (0) 2024.08.12
JPA 필드와 컬럼 매핑  (0) 2024.08.12
JPQL과 SQL의 차이점  (0) 2024.08.12
JPA의 영속성 컨텍스트  (0) 2024.08.12

데이터베이스 스키마 자동 생성

  • JPA는 애플리케이션 실행 시점에 DDL을 자동 생성하게 할 수 있다
  • 데이터베이스 방언을 활용해 db에 맞는 DDL을 생성한다.
  • 미리 테이블을 만들지 않아도 되므로 객체 중심의 개발을 할 수 있는 장점이 있다.
  • 운영에서 쓰면 안되고 개발 단계에서 쓰면 좋다
  • 각 SQL 방언에 맞게 생성해준다.
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.2"
             xmlns="http://xmlns.jcp.org/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd">

    <persistence-unit name="hello">
        <properties>
            ...
            <property name="hibernate.hbm2ddl.auto" value="create"/>
        </properties>
    </persistence-unit>
</persistence>

스크린샷 2024-08-02 110651

CREATE

시작 시 DROP을 먼저 실행한다

CREATE-DROP

  • 마지막에 DROP으로 날린다.
  • 테스트 같이 결과가 남지 않아야 할 때 사용한다.

UPDATE

  • 새로 칼럼을 추가했을 때 그 내용만 반영한다
  • 만약 AGE 칼럼을 추가했는데 테이블을 새로 만들고 싶지 않다면 추가한 칼럼에 대해 ALTER을 수행한다.
  • 컬럼을 지운것에 대해서는 아무 쿼리도 동작하지 않는다.

VALIDATE

테이블에 없는 칼럼을 클래스에 필드로 추가했을 경우 에러가 난다.

NONE

관례상 집어넣는 값. 무의미한 값을 옵션에 집어넣는 것이다.

운영 장비에는 절대 CREATE, CREATE-DROP, UPDATE를 사용하면 안된다.
테이블을 DROP이나 UPDATE하면 ALTER을 하면서 락이 걸려 서비스가 중단된다.

개발 초기 단계: CREATE, UPDATE
테스트 서버: UPDATE, VALIDATE
스테이징, 운영 서버: NONE, VALIDATE

ddl 생성

제약 조건 추가

@Column(nullable = galse, length = 10)

유니크 제약 조건 추가

@Table(uniqueConstraints = {@UniqueConstraint(name = "NAME_AGE_UNIQUE", columnNames = {"NAME", "AGE"})})
  • 위 조건들은 JPA에는 영향을 주지 않고 DDL 생성, DB에만 영향을 준다.
  • DDL = SQL 명령어

'CS > SPRING' 카테고리의 다른 글

SPRING FRAMEWORK + SPRING BOOT  (0) 2024.08.15
JPA 기본키 매핑  (0) 2024.08.12
JPA 필드와 컬럼 매핑  (0) 2024.08.12
JPQL과 SQL의 차이점  (0) 2024.08.12
JPA의 영속성 컨텍스트  (0) 2024.08.12

필드와 컬럼 매핑

  • @Column : 컬럼을 매핑
  • @Enumerated : Enum 타입을 매핑
  • @Temporal : 날짜 타입을 매핑
  • @Lob : BLOB, CLOB 등의 길이 제한이 없는 문자열 타입을 매핑
  • @Transient : 해당 필드를 매핑하지 않음을 지정
  • @Access : JPA가 엔티티에 접근하는 방식 설정

@Column

속성 기능 기본값
name 필드와 매핑할 테이블의 컬럼 이름을 지정한다. 객체의 필드 이름
insertable 엔티티 저장 시 이 필드도 같이 저장한다.
false로 설정하면 이 필드는 데이터베이스에 저장하지 않는다.
false 옵션은 읽기 전용일 때 사용한다.
true
updateable 엔티티 수정 시 이 필드도 같이 수정한다.
false로 설정하면 데이터베이스에 수정하지 않는다.
false 옵션은 읽기 전용일 때 사용한다.
true
table 하나의 엔티티를 두 개 이상의 테이블에 매핑할 때 사용한다.
(@SecondaryTable 사용) 지정한 필드를
다른 테이블에 매핑할 수 있다.
현재 클래스가 매핑된 테이블
nullable DDL 생성 시 null 값의 허용 여부를 설정한다.
false로 설정하면 not null 제약조건이 붙는다.
true
unique @TableuniqueConstraints와 같으나
한 컬럼에 간단히 유니크 제약조건을 걸 때 사용한다.
false
columnDefinition 데이터베이스 컬럼 정보를 직접 줄 수 있다.
자바 필드의 타입과, 데이터베이스 방언 설정 정보를 사용한다.
자바 필드의 타입
데이터베이스 방언 설정 정보
length 문자 길이 제약조건, String 타입에만 사용한다. 255
precision BigDecimal 타입(혹은 BigInteger)에서 사용한다.
precision은 소수점을 포함한 전체 자리수이다
0
scale BigDecimal 타입(혹은 BigInteger)에서 사용한다.
scale은 소수의 자리수
0

 

// nullable
@Column(nullable = false)
private String data;

SQL : data varchar(255) not null

// unique
@Column(unique = true)
private String userName;

SQL : alter table tablename add constraint UK_xxx unique (username)

// columnDefinition
@Column(columnDefinition = "varchar(100) default 'test'")
private String data;

SQL : data varchar(100) default 'test'

// length
@Column(length = 200)
private String data;

SQL : data varchar(100)

@Enumnerated

속성명 기능 기본값
EnumType.ORDINAL enum의 순서대로 데이터베이스에 저장합니다. 순서 값(0, 1, 2, ...)으로 저장 기본값
EnumType.STRING enum 이름을 문자열로 데이터베이스에 저장한다.
예를 들어, RED, GREEN, BLUE 등으로 저장됨
이거나
// Enum 선언
public enum RoleType{
    ADMIN, USER
}

// 이름으로 매핑
@Enumerated(EnumType.STRING)
private RoleType roleType;

// 순서로 매핑
@Enumerated(EnumType.ORDINAL)
private RoleType roleType;

@Temporal

날짜 타입에 대한 매핑
속성명 기능 기본값
value -TemporalType.DATE: 날짜를 데이터베이스 DATE 타입과 매핑 기본값
* TemporalType.TIME : 시간을 데이터베이스 time 타입과 매핑
* TemporalType.TIMESTAMP : 날짜 + 시간을 데이터베이스 timestamp 타입과 매핑
// DATE
@Temporal(TemporalType.DATE)
private Date date;
예 : 2023-10-25

// TIME
@Temporal(TemporalType.TIME)
private Date time;
예 : 00:00:00

// TIMESTAMP
@Temporal(TemporalType.TIMESTAMP)
private Date timeStamp;
예 : 2023-10-25 00:00:00:00

@Lob

데이터베이스의 BLOB, CLOB 타입과 매핑한다.

해당 어노테이션은 따로 지정할 수 있는 속성이 없다.
매핑하는 필드가 문자열이라면 CLOB으로 매핑하고 그렇지 않다면 BLOB으로 매핑한다.

여기서 잠시 CLOB과 BLOB에 대해 간단히 설명하고 넘어가자.

CLOB(Character Large Object) 

문자 기반의 큰 객체를 나타내며, 주로 텍스트 데이터를 저장하는데 사용된다.
BLOB(Binary Large Object) 
이진 데이터를 저장하는데 사용되며
주로 이미지, 오디오, 비디오, 바이너리 데이터 등을 저장하는데 사용된다.

자바의 자료형으로 분류하면 다음과 같다.

CLOB : String, char[], java.sql.CLOB
BLOB : byte[], java.sql.BLOB

@Transient

  • 해당 필드는 매핑하는 것을 희망하지 않을 경우 사용한다.
  • 저장 및 조회도 하지 않기 때문에 임시로 어떤 값을 보관하고 싶을 때 활용하기도 한다.

@Access

AccessType.FIELD

  • 필드에 직접 접근하며 private로 선언하였더라도 접근이 가능하다.
  • @Id가 필드에 있는 경우 해당 접근 방식은 생략 가능하다.
@Entity
public class Test{
    @Id @GeneratValue // @Id 어노테이션이 필드에 있는 상태
    private Long id;
}
AccessType.PROPERTY : 접근자(getter, setter)를 통해서 접근이 가능하다. @Id가 프로퍼티에 있는 경우 해당 접근 방식은 생략 가능하다.
@Entity
public class Test{
    @GeneratValue
    private Long id;
    ...
    @Id // @Id 어노테이션이 프로퍼티에 있는 상태
    public Long getId(){
    }
}

'CS > SPRING' 카테고리의 다른 글

JPA 기본키 매핑  (0) 2024.08.12
데이터베이스 스키마 자동 생성  (0) 2024.08.12
JPQL과 SQL의 차이점  (0) 2024.08.12
JPA의 영속성 컨텍스트  (0) 2024.08.12
JPA를 사용한 간단한 CRUD 구현  (0) 2024.08.12

JPQL과 SQL의 차이점

JPQL은 엔티티 객체를 대상으로 쿼리문을 작성하며
SQL은 데이터베이스 테이블을 대상으로 쿼리문을 작성한다

JPQL (Java Persistence Query Language)

EntityManager.find()
JPA는 SQL을 추상화한 JPQL이라는 객체 지향 쿼리 언어를 제공한다.
테이블을 대상으로 쿼리하는 것이 아닌 엔티티 객체를 대상으로 쿼리한다.

추상화로 특정 데이터베이스 SQL에 의존하지 않으며
SELECT, JOIN, WHERE 같은 SQL과 유사한 문법을 지원한다.

JPQL 문법

from절에 들어가는 것은 객체다

select m from Member where m.age > 8

 

JPQL 키워드는 대소문자를 구분하지 않는다. 엔티티 클래스와 필드의 대소문자는 일치해야한다.

select, from, where ...

 

테이블 이름이 아닌 엔티티 이름을 사용한다

테이블명은 User이고 엔티티명이 Member일때
Member 사용

 

별칭은 필수이다

Member의 별칭 m

JOIN

JPQL 에서 조인은 엔티티 간의 관계로 일대일, 일대다, 다대일, 다대다 관계를 조회할 때 사용된다.
JPQL 조인은 연관된 필드를 기준으로 조인하여 외래키를 통해 자동으로 맵핑된다

타입 표현

문자 : 'HELLO', 'She''s'
숫자 : 10L, 10D, 10F //타입 명시
boolean : TRUE, FALSE
ENUM : jpabook.MemberType.Admin (패키지명 포함)
엔티티 타입 : TYPE(m) = Member (상속 관계에서 사용)

'CS > SPRING' 카테고리의 다른 글

데이터베이스 스키마 자동 생성  (0) 2024.08.12
JPA 필드와 컬럼 매핑  (0) 2024.08.12
JPA의 영속성 컨텍스트  (0) 2024.08.12
JPA를 사용한 간단한 CRUD 구현  (0) 2024.08.12
serviceImpl 을 사용하는 이유  (1) 2024.07.23

JPA

관계형 데이터베이스 SQL 테이블과 객체 지향 프로그래밍 (자바)간의 매핑을 자동으로 해주는

ORM 을 사용한 인터페이스이다.

영속성 컨텍스트

엔티티를 저장하는 논리적인 개념이다.
애플리케이션(자바) ~ DB 사이에서 객체를 보관하는 가상의 DB 역할로 
Buffer을 이용해 flush할 때 DB에 반영한다.

장점

1차 캐시

스크린샷 2024-08-01 140216

엔티티 조회시

1차 캐시에서 조회
1차 캐시에 없을 경우 DB에서 조회 (1차 캐시에 저장 후 반환)

EM은 트랜잭션 단위이기에 트랜잭션이 끝나면 1차 캐시도 삭제됨
1차 캐시는 성능 향상도 있지만 매커니즘적인 장점이 큼

(2차 캐시는 애플리케이션 전체에서 공유하는 캐시이다)

영속성 엔티티의 동일성 보장 (1차 캐시)

Member a = em.find(Member.class, "member1");
Member b = em.find(Member.class, "member1");

System.out.println(a == b) // 동일성 보장
Mybatis에서는 동일성이 보장이 안 됐으나 
JPA는 1차 캐시에있는 같은 엔티티를 반환하여 동일성을 보장한다.

쓰기 지연

쓰기 지연 SQL 저장소에 모았다가 
트랜잭션을 커밋하는 순간 DB에 SQL을 보냄
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();

//엔티티 매니저는 데이터 변경시 트랜잭션을 시작해야 한다.
transaction.begin(); // [트랜잭션] 시작
em.persist(memberA);
em.persist(memberB);

//여기까지 INSERT SQL을 데이터베이스에 보내지 않는다.
//커밋하는 순간 데이터베이스에 INSERT SQL을 보낸다.
transaction.commit(); // [트랜잭션] 커밋

더티 체킹 (엔티티 변경감지)

스크린샷 2024-08-01 141353

JPA에서는 수정할 때 따로 업데이트나 저장을 할 필요가 없다
플러시 시점에 엔티티와 스냅샷을 비교해서 바뀐 엔티티 찾는데
바뀐 엔티티가 있으면→ update 쿼리를 쓰기 지연 저장소에 저장 → 디비에  
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin(); // [트랜잭션] 시작
// 영속 엔티티 조회
Member memberA = em.find(Member.class, "memberA");
// 영속 엔티티 데이터 수정
memberA.setUsername("hi");
memberA.setAge(10);

//em.update(member) 이런 코드가 없어도 된다!
transaction.commit(); // [트랜잭션] 커밋

엔티티의 생명주기

비영속

객체만 생성하고 엔티티와 연결하지 않은 것

영속 = @Id로 키값을 매핑해줘야됨

객체를 생성하고 저장한 상태
영속성 컨텍스트가 관리하는 엔티티 (1차캐시/ 쓰기지연 저장소에 있는 상태)
JPA가 관리하는 상태로 1차 캐시에 있는 상태이다.
em.persist(member);
em.find();
//객체를 생성만 한 상태(비영속)
Member member = new Member();
member.setId("member1");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();

//객체를 저장한 상태(영속)
em.persist(member);

준영속

엔티티가 영속성 컨텍스트에서 분리 된 상태
1차 캐시와 쓰기 지연 SQL 저장소에서 제거된 상태이기 때문에
트랜잭션 커밋할 때 쿼리 생성이 안 된다.
em.detached();

삭제

em.remove();

상태 변화

비영속 → 영속 → 삭제
영속 → 준영속

스크린샷 2024-08-01 140010

플러시

영속성 컨텍스트의 변경내용을 DB에 동기화
em.getTransaction().begin();
Employee emp = new Employee();
emp.setName("Jane Smith");
emp.setSalary(60000);

em.persist(emp);
em.flush(); // 영속성 컨텍스트를 데이터베이스와 동기화

em.getTransaction().commit();
em.close();

플러시 모드

FlushModeType.AUTO (기본값)

기본 플러시 모드로, 트랜잭션 커밋 시 자동으로 플러시된다.

FlushModeType.COMMIT

트랜잭션이 커밋될 때만 플러시가 수행됩니다. 이 모드는 명시적으로 flush()를 호출해야 변경 사항이 데이터베이스에 반영된다.

웬만하면 AUTO 사용함

1차 캐시랑은 상관없이 쓰기 지연 저장소를 한 번에 디비에 반영하는 과정

1. 변경 감지
2. 수정된 엔티티를 쓰기 지연 SQL 저장소에 등록
3. 저장소의 모아둔 쿼리를 한 번에 DB로 보냄

em.detach(entity)

특정 엔티티만 준영속 상태로 바꾼다

em.clear()

1차 캐시를 지우고 영속성 컨텍스트를 처음부터 만든다

em.close()

영속성 컨텐츠를 닫아 관리를 종료한다.
EntityManager을 사용한 후에는 반드시 close를 호출하여 트랜잭션을 명확하게 종료해야한다.

안 그러면 데이터베이스에 대한 변경이 불완전하게 처리될 수 있

'CS > SPRING' 카테고리의 다른 글

JPA 필드와 컬럼 매핑  (0) 2024.08.12
JPQL과 SQL의 차이점  (0) 2024.08.12
JPA를 사용한 간단한 CRUD 구현  (0) 2024.08.12
serviceImpl 을 사용하는 이유  (1) 2024.07.23
웹서버 WAS, SERVLET  (0) 2024.07.08

+ Recent posts