1. SpringBoot의 JPA
메모장 프로젝트 JPA 설정
build.gradle
// JPA 설정
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
추가
dependencies {
// JPA 설정
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
application.properties
: Hibernate 설정
1/. show_sql, format_sql, use_sql_comments 옵션
Hibernate가 DB에 요청하는 모든 SQL을 보기좋게 출력 해줍니다.
2/. ddl-auto
- create : 기존 테이블 삭제 후 다시 생성합니다. (DROP + CREATE)
- create-drop : create와 같으나 종료시점에 테이블을 DROP 합니다.
- update : 변경된 부분만 반영합니다.
- validate : Entity와 테이블이 정상 매핑되었는지만 확인합니다.
- none: 아무것도 하지 않습니다.
spring.datasource.url=jdbc:mysql://localhost:3306/memo
spring.datasource.username=root
spring.datasource.password=Aa1213811!
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.show_sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.use_sql_comments=true
Memo.java
클래스 를 Entity 로 변경
@Entity // JPA가 관리할 수 있는 Entity 클래스 지정
@Getter
@Setter
@Table(name = "memo") // 매핑할 테이블의 이름을 지정
@NoArgsConstructor
public class Memo {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "username", nullable = false)
private String username;
@Column(name = "contents", nullable = false, length = 500)
private String contents;
public Memo(MemoRequestDto requestDto) {
this.username = requestDto.getUsername();
this.contents = requestDto.getContents();
}
public void update(MemoRequestDto requestDto) {
this.username = requestDto.getUsername();
this.contents = requestDto.getContents();
}
}
SpringBoot 는 EntityManagerFactory 랑 EntityManager 를 자동 생성해줌
그냥 기본 java 프로젝트 에서는 persistance.xml 에서 성정 했어야 했음
(복습)
<?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="memo">
<class>com.sparta.entity.Memo</class>
<properties>
<property name="jakarta.persistence.jdbc.driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="jakarta.persistence.jdbc.user" value="root"/>
<property name="jakarta.persistence.jdbc.password" value="Aa1213811!"/>
<property name="jakarta.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/memo"/>
<property name="hibernate.hbm2ddl.auto" value="update" />
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>
<property name="hibernate.use_sql_comments" value="true"/>
</properties>
</persistence-unit>
</persistence>
Spring 에서는 이거는 인제 필요 없음.
application.properties 에서 있는 정보들로 다 자동으로 생성 해줌
그럼 EntityManagerFactory 랑 EntityManager 를 어떻게 사용하나?
@Transactional 애노테이션을 걸면 사용 할수 있다.
클래스 위에다가 혹을 메소드 위에다가.
@Transactional(readOnly = true) 에서는 데이터 수정 x
조회 (SELECT) 할때 Transactional 필수는 아니지만 필요 할때는 있다.
@Transactional 는 덯어 씌우기가 가능 하다,
@Transactional(readOnly = true)
.....
@Transactional // 수정할때 덮어쓰기
EntityManagerFactory 랑 EntityManager 직접 사용.
@PersistenceContext
@PersistenceContext
원래 기존 java 에서는 autowired 사용.
테스트 1 (성공)
@Test
@Transactional
@Rollback(value = false) // 테스트 코드에서 @Transactional 를 사용하면 테스트가 완료된 후 롤백하기 때문에 false 옵션 추가
@DisplayName("메모 생성 성공")
void test1() {
Memo memo = new Memo();
memo.setUsername("Robbert");
memo.setContents("@Transactional 테스트 중!");
em.persist(memo); // 영속성 컨텍스트에 메모 Entity 객체를 저장합니다.
}
테스트 2 (실패 Transactional 이 없기 때문에)
@Test
@Disabled
@DisplayName("메모 생성 실패")
void test2() {
Memo memo = new Memo();
memo.setUsername("Robbie");
memo.setContents("@Transactional 테스트 중!");
em.persist(memo); // 영속성 컨텍스트에 메모 Entity 객체를 저장합니다.
}
MemoRepository( 우리가 전에 만들었던 repo 클래스 , mvc 기억하시나요?)
에 함수 추가
package com.sparta.memo.memoRepositary;
import com.sparta.memo.dto.MemoRequestDto;
import com.sparta.memo.dto.MemoResponseDto;
import com.sparta.memo.entity.Memo;
import jakarta.persistence.EntityManager;
import jakarta.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.stereotype.Component;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;
@Component
public class memoRepository {
Memo memo; // memo
private JdbcTemplate jdbcTemplate;
@Autowired
public void setmemoRepository(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;// repository
}
.......
@Transactional
public Memo createMemo(EntityManager em) {
Memo memo = em.find(Memo.class, 1);
memo.setUsername("Robbie");
memo.setContents("@Transactional 전파 테스트 중!");
System.out.println("createMemo 메서드 종료");
return memo;
}
}
테스트 3 MemoRepository 안에 있는 거로 JPA 하기.
@Test
@Transactional
@Rollback(value = false)
@DisplayName("트랜잭션 전파 테스트")
void test3() {
memoRepository.createMemo(em);
System.out.println("테스트 test3 메서드 종료");
}
자식 메소트 @Transactional 이 부모 의 @Transactional 과 합쳐진다.
@Transactional 는 default 가 Propagation.REQUIRED.
그래서 부모가 @Transactional 가 있으면 부모 가 끝나기 전까진
Hibernate 업데이트 안함.
'Spring' 카테고리의 다른 글
| Spring 기초 10 (JPA Auditing (시간 받기)) (0) | 2024.01.21 |
|---|---|
| Spring 기초 9 (Spring DATA JPA + 기능들) (0) | 2024.01.21 |
| Spring 기초 7 (Entitiy 상태) (Entitiy 영속/비영속 기능) (0) | 2024.01.20 |
| Spring 기초 6 (영속성) (EntityManager) ( Persistence 기능) (변경 감지(Dirty Checking)) (0) | 2024.01.20 |
| Spring 기초 5 (Entity) (0) | 2024.01.20 |